eel4746_avr_piano

For our Microprocessor's class final project, we chose to make a chiptune piano using AVR C on two Arduino UNOs.
Log | Files | Refs | README | LICENSE

lcd.c (7915B)


      1 #include <avr/io.h>		//standard AVR header
      2 #define F_CPU 16000000UL	// THE CPU FREQUENCY
      3 #include <util/delay.h>		//delay header
      4 #include <avr/interrupt.h>      //interrupt header
      5 #include <stdlib.h> 
      6 
      7 #define LCD_DPRT PORTD		//LCD DATA PORT
      8 #define LCD_DDDR DDRD		//LCD DATA DDR
      9 #define LCD_DPIN PIND		//LCD DATA PIN
     10 #define LCD_CPRT PORTB		//LCD COMMANDS PORT
     11 #define LCD_CDDR DDRB		//LCD COMMANDS DDR
     12 #define LCD_CPIN PINB		//LCD COMMANDS PIN
     13 #define LCD_RS 0		//LCD RS
     14 #define LCD_EN 1		//LCD EN
     15 				
     16 // Define your buffer sizes
     17 #define SERIAL_BUFFER_SIZE 20
     18 #define NOTES_BUFFER_SIZE 20
     19 
     20 // Global variables
     21 char serialBuffer[SERIAL_BUFFER_SIZE];
     22 char notesBuffer[NOTES_BUFFER_SIZE];
     23 int serialIndex = 0;
     24 int notesIndex = 0;
     25 volatile int buttonState = 0; // Holds the state of all buttons
     26 unsigned char songBuffer[1024];
     27 int count = 0;
     28 
     29 void
     30 usart_init(void)
     31 {
     32 	// 9600 bps, RX enabled
     33 	UBRR0 = 103;
     34 	UCSR0B = 1 << RXEN0;
     35 	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
     36 }
     37 
     38 char
     39 getNote(void)
     40 {
     41 	while (!(UCSR0A & (1 << RXC0)));
     42 
     43 	unsigned char c = UDR0;
     44 
     45 	// convert 0-9 to ascii character
     46 	if (c <= 9)
     47 		c += '0';
     48 	// convert to capital hex
     49 	else if (c >= 0xa && c <= 0xf)
     50 		c = c - 0xa + 'A';
     51 
     52 	return c;
     53 }
     54 			      //
     55 void lcd_putValue(unsigned char val)
     56 {
     57 	LCD_DPRT &= 0x0F;
     58 	LCD_DPRT |= (val & 0xF0);	//send cmnd to data port
     59 	LCD_CPRT |= (1 << LCD_EN);	//EN = 1 for H-to-L pulse
     60 	_delay_us(1);		//wait to make enable wide
     61 	LCD_CPRT &= ~(1 << LCD_EN);	//EN = 0 for H-to-L pulse
     62 	_delay_us(100);		//wait to make enable wide
     63 	LCD_DPRT &= 0x0F;
     64 	LCD_DPRT |= val << 4;	//send cmnd to data port
     65 	LCD_CPRT |= (1 << LCD_EN);	//EN = 1 for H-to-L pulse
     66 	_delay_us(1);		//wait to make enable wide
     67 	LCD_CPRT &= ~(1 << LCD_EN);	//EN = 0 for H-to-L pulse
     68 	_delay_us(100);		//wait to make enable wide
     69 }
     70 
     71 //*******************************************************
     72 void lcdCommand(unsigned char cmnd)
     73 {
     74 	LCD_CPRT &= ~(1 << LCD_RS);	//RS = 0 for command
     75 	lcd_putValue(cmnd);
     76 }
     77 
     78 //*******************************************************
     79 void lcdData(unsigned char data)
     80 {
     81 	LCD_CPRT |= (1 << LCD_RS);	//RS = 1 for data
     82 	lcd_putValue(data);
     83 }
     84 
     85 void lcd_clear()
     86 {
     87 	lcdCommand(0x01);
     88 	_delay_us(1700);
     89 }
     90 
     91 void lcd_showCursor()
     92 {
     93 	lcdCommand(0x0E);
     94 	_delay_us(50);
     95 }
     96 
     97 void lcd_hideCursor()
     98 {
     99 	lcdCommand(0x0C);
    100 	_delay_us(50);
    101 }
    102 
    103 //*******************************************************
    104 void lcd_init()
    105 {
    106 	LCD_DDDR |= 0xF0;
    107 	LCD_CDDR |= (1 << LCD_RS) | (1 << LCD_EN);
    108 	LCD_CPRT &= ~(1 << LCD_EN);	//LCD_EN = 0
    109 	_delay_us(2000);	//wait for init.
    110 	lcdCommand(0x33);	//send $33 for init.
    111 	lcdCommand(0x32);	//send $32 for init
    112 	lcdCommand(0x28);	//init. LCD 2 line,5*7 matrix
    113 	lcdCommand(0x0e);	//display on, cursor on
    114 	lcdCommand(0x06);	//shift cursor right
    115 	lcd_clear();
    116 }
    117 
    118 //*******************************************************
    119 void lcd_gotoxy(unsigned char x, unsigned char y)
    120 {
    121 	unsigned char firstCharAdr[] = { 0x80, 0xC0, 0x94, 0xD4 };	//Table 12-4
    122 	lcdCommand(firstCharAdr[y - 1] + x - 1);
    123 	_delay_us(100);
    124 }
    125 
    126 //*******************************************************
    127 void lcd_print(char *str)
    128 {
    129 	unsigned char i = 0;
    130 	while (str[i] != 0)	//while it is not end of string
    131 	{
    132 		lcdData(str[i]);
    133 		i++;
    134 	}
    135 }
    136 
    137 char getSerialData() {
    138     // Read serial data and return it
    139     return ' ';
    140 }
    141 
    142 void setup() {
    143     // Initialize Serial communication
    144     // Initialize LCD
    145     // Initialize buttons as inputs
    146     // Set pins A4 and A5 as inputs with pull-up resistors enabled
    147     DDRC &= ~((1 << DDC4) | (1 << DDC5));
    148     PORTC |= (1 << PORTC4) | (1 << PORTC5);
    149 
    150     // Enable Pin Change Interrupt on pins PC4 and PC5
    151     PCMSK1 |= (1 << PCINT12) | (1 << PCINT13); // Enable PCINT for pins PC4 and PC5
    152     PCICR |= (1 << PCIE1); // Enable Pin Change Interrupt 1
    153     sei(); // Enable global interrupts
    154 }
    155 
    156 ISR(PCINT1_vect) {
    157     // Update button state when any pin changes state
    158     for (unsigned char i = 4; i <= 5; i++) {
    159 	    if (PINC & (1 << i)) {
    160 		    if(buttonState == 0) 
    161 		    	buttonState = i;
    162 		    else
    163 			buttonState = 0;
    164 		    break;
    165 	    }
    166     }
    167 }
    168 
    169 void displayNotes() {
    170     char circularBuffer[16];
    171     static int bufferIndex = 0;
    172     
    173     lcd_clear();
    174     lcd_gotoxy(6, 2);
    175     lcd_print("PLAYING");
    176     _delay_ms(1000);
    177     lcd_clear();
    178     _delay_ms(1000);
    179     for(int k = 0; k < count) {
    180 	unsigned char randomValue = songBuffer[k];
    181 
    182         if (bufferIndex == 16) {
    183 
    184             // Remove the first value and shift other values down
    185             for (int i = 0; i < 16 - 1; i++) {
    186                 circularBuffer[i] = circularBuffer[i + 1];
    187             }
    188             // Add the new value at the end
    189             circularBuffer[16 - 1] = randomValue;
    190         } else {
    191             // Add the new value to the buffer
    192             circularBuffer[bufferIndex] = randomValue;
    193 	    bufferIndex++;
    194         }
    195 
    196         lcd_clear();
    197         for (int i = 0; i <= bufferIndex - 1; i++) {
    198             char singleChar[2] = {circularBuffer[i], '\0'};
    199 	    lcd_gotoxy(17-bufferIndex+i ,1);
    200 	    lcd_print(singleChar); // Print the single character
    201 	    lcd_gotoxy(6,2);
    202 	    lcd_print("PLAYING");
    203         }
    204 
    205         _delay_ms(500);
    206     }
    207     buttonState = 0;
    208     bufferIndex = 0;
    209     lcd_clear();
    210 }
    211 
    212 
    213 void displaySerialData() {
    214     char circularBuffer[16];
    215     static int bufferIndex = 0;
    216     lcd_clear();
    217     lcd_gotoxy(3, 2);
    218     lcd_print("RECORDING");
    219     _delay_ms(1000);
    220     lcd_clear();
    221     _delay_ms(1000);
    222     while (buttonState == 5) {
    223         unsigned char randomValue = getNote(); 
    224 	count = 0;
    225 	songBuffer[count] = randomValue;
    226 	count++;
    227 
    228         if (bufferIndex == 16) {
    229             // Remove the first value and shift other values down
    230             for (int i = 0; i < 16 - 1; i++) {
    231                 circularBuffer[i] = circularBuffer[i + 1];
    232             }
    233             // Add the new value at the end
    234             circularBuffer[16 - 1] = randomValue;
    235         } else {
    236             // Add the new value to the buffer
    237             circularBuffer[bufferIndex] = randomValue;
    238 	    bufferIndex++;
    239         }
    240 	
    241         lcd_clear();
    242 	lcd_gotoxy(1,1);
    243         for (int i = 0; i <= bufferIndex-1; i++) {
    244             char singleChar[2] = {circularBuffer[bufferIndex- 1 - i], '\0'};
    245 	    lcd_gotoxy(i+1,1);
    246 	    lcd_print(singleChar); // Print the single character
    247 	    lcd_gotoxy(3,2);
    248 	    lcd_print("RECORDING");
    249         }
    250 	
    251         //_delay_ms(1000);
    252     }
    253     bufferIndex = 0;
    254     lcd_clear();
    255 }
    256 
    257 void displayPiano() {
    258     char circularBuffer[16];
    259     static int bufferIndex = 0;
    260     lcd_clear();
    261     lcd_gotoxy(6, 2);
    262     lcd_print("PIANO");
    263     _delay_ms(1000);
    264     lcd_clear();
    265     _delay_ms(1000);
    266     while (buttonState == 0) {
    267         unsigned char randomValue = getNote();
    268 
    269         if (bufferIndex == 16) {
    270             // Remove the first value and shift other values down
    271             for (int i = 0; i < 16 - 1; i++) {
    272                 circularBuffer[i] = circularBuffer[i + 1];
    273             }
    274             // Add the new value at the end
    275             circularBuffer[16 - 1] = randomValue;
    276         } else {
    277             // Add the new value to the buffer
    278             circularBuffer[bufferIndex] = randomValue;
    279 	    bufferIndex++;
    280         }
    281 	
    282         lcd_clear();
    283 	lcd_gotoxy(1,1);
    284         for (int i = 0; i <= bufferIndex-1; i++) {
    285             char singleChar[2] = {circularBuffer[bufferIndex- 1 - i], '\0'};
    286 	    lcd_gotoxy(i+1,1);
    287 	    lcd_print(singleChar); // Print the single character
    288     	    lcd_gotoxy(6, 2);
    289     	    lcd_print("PIANO");
    290         }
    291 	
    292         //_delay_ms(1000);
    293     }
    294     bufferIndex = 0;
    295     lcd_clear();
    296 }
    297 
    298 //*******************************************************
    299 int main(void) {
    300 	lcd_init();
    301 	lcd_hideCursor();
    302 	usart_init();
    303 	setup();
    304 	lcd_clear();
    305     	while (1) {
    306 		// Check button state and perform actions accordingly
    307         	if (buttonState == 5) {
    308 			displaySerialData();
    309 
    310        		} else if (buttonState == 4) {
    311 			displayNotes();
    312         	} 
    313 		else { 
    314 			displayPiano();
    315 		}
    316 	}
    317     	return 0;
    318 }