Oh my goodness! I suddenly remembered that I may have still keep that program code, despite me taking apart that actual hardware. That actual program code could still tell me some stories of how it would work (or not).
So I rummaged that old archive of mine, all that paper-work from my college days in 2009 (man, how time zips past me!), a mountain of really failed PIC projects code, and finally, here it is!
The project was compiled using MPLab C18, which is no longer in use nowadays, but it can be ported to MPLab XC8 with some modifications. That PIC18F4221 was because my lecturer (and my former colleague later) advised me to buy it because he was going to use it in his new syllabus in his Microcontroller subject. After that semester ended, I 'rehomed' it on that decoration for two years.
Here is the fragment of the code that contains what made that first design (probably) work. There are errors on it of course, and this copy is not edited, or in other words - "Thus it had been written" (sic erat scriptum) :
void T0_ISR(void)
{
f_count1++;
f_count2++;
if (f_count1 == 0)
TRISAbits.TRISA0 = 0;
if (f_count1 > f_maxcount1)
{
TRISAbits.TRISA0 = ~TRISAbits.TRISA0;
// PORTAbits.RA0 = ~PORTAbits.RA0;
f_count1 = 0;
}
if (f_count2 == 0)
TRISAbits.TRISA1 = 0;
if (f_count2 > f_maxcount2)
{
TRISAbits.TRISA1 = ~TRISAbits.TRISA1;
// PORTAbits.RA1 = ~PORTAbits.RA1;
f_count2 = 0;
}
TMR0H = 0xFF; // reload values into the TMR0H and TMR0L
TMR0L = 0xBD;
INTCONbits.TMR0IF = 0;
}
void T1_ISR(void)
{
t_count1++;
t_count2++;
if (t_count1 == 25)
PORTBbits.RB0 = 1;
if (t_count1 == 1250)
PORTBbits.RB0 = 0;
if (t_count1 == t_maxcount1)
{
chan1_num++;
if(chan1_num == chan1_max)
{
count1++;
// if (count1 == 2)
// count1 == 0;
chan1_sw(count1);
//break;
//default: count1 = 0;
}
t_count1 = 0;
PORTDbits.RD0 = 0; // chip enable
SPI(0x03);
SPI((char)((chan1_freq_address + chan1_num) >> 8)); // send MSB address first
SPI((char)(chan1_freq_address + chan1_num));
f_maxcount1 = SPI(0xff);
PORTDbits.RD0 = 1;
PORTDbits.RD0 = 0;
SPI(0x03);
SPI((char)((chan1_dur_address + chan1_num*2) >> 8)); // send MSB address first
SPI((char)(chan1_dur_address + chan1_num*2)); // send LSB address afterwards
buffer_lo = SPI(0xff);
buffer_hi = SPI(0xff);
PORTDbits.RD0 = 1;
duration_b = buffer_hi;
duration_b = (duration_b << 8) | buffer_lo;
t_maxcount1 = duration_b;
//f_maxcount1 = channel1_f[chan1_num]; // next frequency
//t_maxcount1 = channel1_d[chan1_num]; // next duration
}
if (t_count2 == 25)
PORTBbits.RB1 = 1;
if (t_count2 == 1250)
PORTBbits.RB1 = 0;
if (t_count2 == t_maxcount2)
{
chan2_num++;
if(chan2_num == chan2_max)
{
count2++;
// if (count2 == 2)
// count2 == 0;
chan2_sw(count2);
}
t_count2 = 0;
PORTDbits.RD0 = 0; // chip enable
SPI(0x03); // read
SPI((char)((chan2_freq_address + chan2_num) >> 8)); // send MSB address first
SPI((char)(chan2_freq_address + chan2_num)); // send LSB address afterwards
f_maxcount2 = SPI(0xff);
PORTDbits.RD0 = 1; // chip disable
PORTDbits.RD0 = 0;
SPI(0x03);
SPI((char)((chan2_dur_address + chan2_num*2) >> 8)); // send MSB address first
SPI((char)(chan2_dur_address + chan2_num*2)); // send LSB address afterwards
buffer_lo2 = SPI(0xff);
buffer_hi2 = SPI(0xff);
PORTDbits.RD0 = 1;
duration_b2 = buffer_hi2;
duration_b2 = (duration_b2 << 8) | buffer_lo2;
t_maxcount2 = duration_b2;
// f_maxcount2 = channel2_f[chan2_num]; // next frequency
// t_maxcount2 = channel2_d[chan2_num];
}
TMR1H = t1_b_hi;
TMR1L = t1_b_lo; // 0xfeff
PIR1bits.TMR1IF = 0;
}
There was SPI inside because the little music box draws out the music note values from an SPI EEPROM. I do not know why I did that when the microcontroller has like 4KB of space. Probably I thought of swapping that EEPROM out later to change tunes, who knows?
Anyway, that trick was to toggle the TRIS, not the PORT bit. The code in the webpage mentioned is the same, but in BASIC flavour:
'----[INTERRUPT HANDLER]------------------------------------------------ NOTE_INT: TIMER1 = 65490 ' Load TMR1 with a preset value Inc NOTE_COUNTER ' Increment the note counter If NOTE_COUNTER > NOTE Then ' Is it time to toggle the pin ? TRISB = TRISB ^ 1 ' Toggle pin PORTB.0 Clear NOTE_COUNTER ' Clear the note counter Endif Clear PIR1.0 ' Clear TMR1 interrupt flag Retfie FAST ' Exit the interrupt
I have not tested this again - since this give me some ideas, why not try it? It wouldn't hurt to try something new, right?
Note: Do not struggle to understand that code fragment I wrote earlier. It was an unorganized mess and I wrote all that when I was a college student. I will fix all that and place it in my github soon.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.