2. 1.0 Objective:
The objective of this lab is to generate 4 simple melodic loops using PIC32
microcontroller. Two Pmods are used to produce the 4 different sound loops. The PmodSWT is
used to control which loop plays by assigning each loop to a corresponding switch. The
PmodAMP2 is used to transport the audio signal via a speaker jack. We use pulse width
modulation (PWM) in order to control both the frequency and duty cycle of the signal.
2.0 Introduction:
This lab was completed using the C language. The inputs used are the 4 switches on
PmodSWT and the onboard buttons 1 and 2. The output is PWM signal from the audio jack on
PmodAMP2. For this lab, each switch will cause the board to output a different 5 second
melodic loop for as long as the switch is toggled on. Btn1 is used to produce a 30% duty cycle,
Btn2 produces a 70% duty cycle, and the default is 50%. In addition, a total of 3 timer registers
were used: timer1, timer 4, and timer 5. Timer1 was used as the main clock for the program
and was scaled down by a factor of 256 from the 10MHz bus frequency. Timers 4 and 5 are two
16-bit timers combined to one 32-bit timer used for the actual 5 second tune loops.
3.0 Design:
3.1 Hardware
The hardware in the PIC32 includes timers, ADC (Analogue to digital converter),
memory, and various internal peripherals. The timerx modules have three registers that
are used to initialize and configure the timer. These are TCxON, TMRx, and PRx. TxCON
configures the timer relative to the system clock, PRx defines the period of the clock,
and TMRx stores the value of the timer. We also assigned the Btn1 and Btn2 (bits RA6
and RA7) to outputs using the TRISA register and operations.
We used the PmodSWT to drive the input of our MK4. A picture and the
architecture of the PmodSWT are shown below:
Figure 1: Picture of PmodSWT (left) and block diagram of architecture (right)
3. In addition, we used the PmodAMP2 to produce the audio signal. The picture
and block diagram of the architecture are shown in figure 2 below:
Figure 2: Picture of PmodAMP2 (left) and block diagram of architecture (right)
3.2 Software
We used the MPLabX IDE in C to program our pic32. As always, we set the
system clock of the PIC32 to 80MHz (the maximum), the peripheral bus frequency to
10MHz, and from that Timer1 was scaled down by a factor of 256. Timer4/5 were
combined and scaled such that a 5 second loop could be counted out.The flow chart of
the software is shown in figure 3 and figure 4. The actual C code is included in appendix
A.
Figure 3: Software flow chart for main()
4. Figure 4: software flow chart for Tone()
4.0 Procedure:
The procedure for this lab is as follows:
- Connect the PmodSWT to chosen Pmod port
- Connect the PmodAMP2
- Construct the C code in MPLabX IDE
- Program the board via a USB connection
- Flip switches to play tone loops, hit buttons to affect duty cycle
5.0 Results and Conclusion:
5.1 Results
As TMR1 was used to control the frequency of the tone, finding an algorithm for
producing various frequencies was simply a matter of manipulating the frequency of TMR1.
TMR1 is set to about 39 kHz. The input variable of tone is functionally the number of ticks at 39
kHz to produce the desired frequency’s period. This yields the following equation:
𝑓𝑇𝑀𝑅1
𝑓𝑑𝑒𝑠𝑖𝑟𝑒𝑑
= 𝑡𝑖𝑚𝑒 (𝑛𝑢𝑚𝑏𝑒𝑟 𝑜𝑓 𝑡𝑖𝑐𝑘𝑠)
Using this, a chart of conversions between music notes and frequencies, and various
musical scores I was able to replicate well known melodies.
5.2 Conclusion
In this lab I successfully created various tones using the MK4, PmodSWT, and
PmodAMP2. I was able to find a relation between the frequency of timer1 and the frequency
desired and in turn was able to replicate various well known melodies.
5. Appendix A: Source code
#include <xc.h>
#include <stdio.h>
#pragma config FNOSC = PRIPLL // this is to select the primary PLL for the oscillator
#pragma config POSCMOD = EC // this uses the EC option for the clock (generates 8MHz)
#pragma config FPLLIDIV = DIV_2 // This is used to divide the frequency by 2
#pragma config FPLLMUL = MUL_20 // then it is multiplied by 20 . now we have 80MHz.
#pragma config FPLLODIV = DIV_1 // now we divide by 1 so it is still at 80MHz.
#pragma config FPBDIV = DIV_8 // the frequency of the peripheral bus is divided by 8 which
gives 10MHz
// function Prototypes
void setup_IOs();
void Setup_timer1();
void setup_timer4();
void Loop0();
void Loop1();
void Loop2();
void Loop3();
void Tone(unsigned short);
void Pause(unsigned short);
//
void main(){
setup_IOs();
setup_timer1();
setup_timer4();
while(1){
if (PORTGbits.RG0 == 1){
TMR4 = 0;
Loop0();
}
else if (PORTGbits.RG1 == 1){
Loop1();
}
else if (PORTFbits.RF0 == 1){
Loop2();
}
else if (PORTFbits.RF1 == 1){
Loop3();
}
else
LATEbits.LATE0 = 0;
6. }
}
void setup_IOs(){
// Port E is output
TRISE = 0x0000;
LATE = 0x0000;
LATEbits.LATE1= 0;
LATEbits.LATE3 = 1; // turned on SHUTDOWN bit
// Port G pins 0-3 are inputs for the swithch.
TRISGbits.TRISG0 = 1;
TRISGbits.TRISG1 = 1;
TRISFbits.TRISF0 = 1;
TRISFbits.TRISF1 = 1;
// Btn1 & Btn2 are Inputs
TRISAbits.TRISA6 =1;
TRISAbits.TRISA7 =1;
}
void setup_timer1(){
T1CON= 0x8030;
PR1 = 0xFFF;
TMR1 = 0;
}
void setup_timer4(){
T4CON = 0x0; // Stop any 16/32-bit Timer4 operation
T5CON = 0x0; // Stop any 16-bit Timer5 operation
T4CON = 0x8078; // Start Timer4/5
// internal peripheral clock source
TMR4 = 0x00000000; // Clear contents of the TMR4 and TMR5
PR4 = 0xffffffff; // every five seconds
}
void Loop0(){
TMR4 = 0;
//unsigned int Loop_T = TMR4; // Read Timer5
unsigned int Max = 200000; // Loop time
while (TMR4 <Max){
if (TMR4 < 20000)
Tone(150);
else if ( TMR4 < 30000)
Tone(120);
else if ( TMR4 < 40000)
Tone(100);
else if ( TMR4 < 50000)
Tone(130);
7. else if ( TMR4 < 60000)
Tone(100);
else if (TMR4< 80000)
Tone(110);
else if ( TMR4 < 95000)
Tone(130);
else if ( TMR4 < 110000)
Tone(100);
else if (TMR4< 120000)
Tone(90);
else if ( TMR4 < 140000)
Tone(130);
else if (TMR4< 150000)
Tone(100);
else if ( TMR4 < 170000)
Tone(90);
else if (TMR4< 180000)
Tone(130);
else if (TMR4< 195000)
Tone(180);
else if (TMR4< 200000)
Pause(100);
else
break;
}
}
void Loop1(){
TMR4 = 0;
//unsigned int Loop_T = TMR4; // Read Timer5
unsigned int Max = 200000; // Loop time
while (TMR4 <Max){
if (TMR4 < 7767)
Tone(151);
else if ( TMR4 < 19417)
Pause(150);
else if ( TMR4 < 27184)
Tone(151);
else if ( TMR4 < 50485)
Pause(300);
else if ( TMR4 < 58252)
Tone(151);
else if (TMR4< 81553)
Pause(300);
8. else if ( TMR4 < 89320)
Tone(196);
else if ( TMR4 < 97087)
Pause(100);
else if (TMR4< 104855)
Tone(151);
else if ( TMR4 < 128156)
Pause(300);
else if (TMR4< 135923)
Tone(130);
else if ( TMR4 < 178641)
Pause(550);
else if (TMR4< 186408)
Tone(263);
else if (TMR4< 200000)
Pause(100);
else
break;
}
}
void Loop2(){
TMR4 = 0;
//unsigned int Loop_T = TMR4; // Read Timer5
unsigned int Max = 200000; // Loop time
while (TMR4 <Max){
if (TMR4 < 10000)
Tone(100);
else if ( TMR4 < 20000)
Tone(1125);
else if ( TMR4 < 30000)
Tone(1062);
else if ( TMR4 < 40000)
Tone(1002);
else if ( TMR4 < 50000)
Tone(946);
else if (TMR4< 80000)
Tone(893);
else if ( TMR4 < 95000)
Tone(843);
else if ( TMR4 < 110000)
Tone(795);
else if (TMR4< 120000)
Tone(751);
9. else if ( TMR4 < 140000)
Tone(130);
else if (TMR4< 150000)
Tone(100);
else if ( TMR4 < 170000)
Tone(90);
else if (TMR4< 180000)
Tone(130);
else if (TMR4< 195000)
Tone(180);
else if (TMR4< 200000)
Pause(100);
else
break;
}
}
void Loop3(){
TMR4 = 0;
//unsigned int Loop_T = TMR4; // Read Timer5
unsigned int Max = 200000; // Loop time
while (TMR4 <Max){
if (TMR4 < 12500)
Tone(25);
else if ( TMR4 < 25000)
Tone(25);
else if ( TMR4 < 37500)
Tone(25);
else if ( TMR4 < 46875)
Tone(31);
else if ( TMR4 < 50000)
Tone(21);
else if (TMR4< 62500)
Tone(25);
else if ( TMR4 < 71875)
Tone(31);
else if ( TMR4 < 75000)
Tone(21);
else if (TMR4< 100000)
Tone(25);
else if ( TMR4 < 112500)
Tone(17);
else if (TMR4< 125000)
Tone(17);