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