initial
This commit is contained in:
551
Firmware/src/main.c
Normal file
551
Firmware/src/main.c
Normal file
@@ -0,0 +1,551 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#ifdef GDBSTUB
|
||||
#include "avr8-stub.h"
|
||||
#else
|
||||
#include "uart.h"
|
||||
#endif
|
||||
|
||||
#include "lcd.h"
|
||||
#include "twi.h"
|
||||
#include "dataflash.h"
|
||||
#include "music.h"
|
||||
|
||||
#define wait_joy_button() \
|
||||
{ \
|
||||
LCD_GotoXY(20, 7); \
|
||||
LCD_PutChar(0x10); \
|
||||
LCD_Update(); \
|
||||
while (((PINA)&0x08)) \
|
||||
; \
|
||||
while (!((PINA)&0x08)) \
|
||||
; \
|
||||
_delay_ms(20); \
|
||||
while (((PINA)&0x08)) \
|
||||
; \
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
const uint8_t PROGMEM emg_logo[640] =
|
||||
{
|
||||
0x80, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf0, 0xf8, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xf8, 0xf8, 0xf0, 0xe0, 0xc0, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0x80, 0xe0, 0xf0,
|
||||
0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xe0, 0x80, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf3, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf7, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x1f, 0x07, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x03, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x07, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x1f, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf1, 0xe1, 0xc1, 0xc1, 0x81, 0x81, 0x81, 0x81, 0xc1, 0xc1, 0xc1,
|
||||
0xc1, 0xc1, 0xc1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
|
||||
0xe1, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0,
|
||||
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
|
||||
0xc0, 0xe0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x01, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x0f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x03, 0x07,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x8f, 0xcf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x0f, 0x07, 0x01,
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
void demo_backlight(void);
|
||||
void demo_start(void);
|
||||
void demo_display(void);
|
||||
void demo_show_emg(void);
|
||||
void demo_uart(void);
|
||||
void demo_music(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// set PA3-PA7 as input and activated internal Pull-Up
|
||||
DDRA &= ~((1 << PINA3) | (1 << PINA4) | (1 << PINA5) | (1 << PINA6) | (1 << PINA7)); // Required for DMM Board 2013
|
||||
PORTA |= ((1 << PINA3) | (1 << PINA4) | (1 << PINA5) | (1 << PINA6) | (1 << PINA7)); // Required for DMM Board 2013
|
||||
|
||||
// set PB0-PB3 as output
|
||||
DDRB = 0x0F;
|
||||
// set PB0-PB3 on high-level
|
||||
PORTB |= 0x0F; // Required for DMM Board DMM Board 2013
|
||||
|
||||
#ifdef GDBSTUB
|
||||
debug_init(); // required for debugging via UART
|
||||
#else
|
||||
UART_Init();
|
||||
#endif
|
||||
|
||||
LCD_Init();
|
||||
sei(); // enable interrupts after drivers initialized
|
||||
|
||||
//demo_start();
|
||||
//demo_show_emg();
|
||||
|
||||
//#ifndef GDBSTUB // UART unavailable if used by GDB stub for debugging
|
||||
//demo_uart();
|
||||
//#endif
|
||||
|
||||
//demo_display();
|
||||
//demo_backlight();
|
||||
//demo_music();
|
||||
|
||||
Backlight_LED(BL_GREEN_ON);
|
||||
|
||||
|
||||
//Backlight_Off();
|
||||
//LCD_Clear();
|
||||
|
||||
// loop forever
|
||||
uint32_t counter = 0;
|
||||
uint8_t button_state = 1;
|
||||
uint8_t button_state_old = 1;
|
||||
while (1){
|
||||
button_state = !(PINA & 0x08);
|
||||
|
||||
if( button_state == 1 && button_state_old == 0 ){
|
||||
_delay_ms(20);
|
||||
counter = 0;
|
||||
}
|
||||
if( button_state == 0 && button_state_old == 1 ){
|
||||
_delay_ms(20);
|
||||
|
||||
/* print to LCD */
|
||||
LCD_Clear();
|
||||
LCD_GotoXY(0, 0);
|
||||
char msg[20];
|
||||
sprintf(msg, "time: %d", counter);
|
||||
LCD_PutString(msg);
|
||||
LCD_Update();
|
||||
/* ------------ */
|
||||
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
counter++;
|
||||
button_state_old = button_state;
|
||||
_delay_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
void demo_start(void)
|
||||
{
|
||||
// Turn on green backlight
|
||||
Backlight_LED(BL_GREEN_ON);
|
||||
|
||||
// Place program memory strings in framebuffer
|
||||
LCD_PutString_P(PSTR("-DMM AVR-Board Demo- \r\n\n"));
|
||||
LCD_PutString_P(PSTR("Always push the \r\n"));
|
||||
LCD_PutString_P(PSTR("joystick button to \r\n"));
|
||||
LCD_PutString_P(PSTR("proceed to the next \r\n"));
|
||||
LCD_PutString_P(PSTR("screen. \r\n\n"));
|
||||
LCD_PutString_P(PSTR("Enjoy the Fuck You! "));
|
||||
|
||||
// Copy framebuffer to display
|
||||
LCD_Update();
|
||||
|
||||
// Wait for joystick button
|
||||
wait_joy_button();
|
||||
}
|
||||
|
||||
void demo_show_emg(void)
|
||||
{
|
||||
// Some counters
|
||||
uint16_t emg_offset = 0;
|
||||
uint8_t fb_x;
|
||||
uint8_t fb_y;
|
||||
|
||||
// Turn on white backlight (red, green and blue)
|
||||
Backlight_LED(BL_RED_ON | BL_GREEN_ON | BL_BLUE_ON);
|
||||
|
||||
// Clear precautionally
|
||||
LCD_Clear();
|
||||
|
||||
// Copy emglogo into framebuffer
|
||||
for (fb_y = 0; fb_y < 5; fb_y++)
|
||||
for (fb_x = 0; fb_x < 128; fb_x++)
|
||||
lcd_framebuffer[fb_y][fb_x] = pgm_read_byte(&emg_logo[emg_offset++]);
|
||||
|
||||
// Mark pages 0-4 for update
|
||||
lcd_frameupdate = 0x1f;
|
||||
|
||||
// Add some text
|
||||
LCD_GotoXY(0, 5);
|
||||
LCD_PutString_P(PSTR(" Institut f\x81r Messt. \r\n"));
|
||||
LCD_PutString_P(PSTR(" und Grundlagen der \r\n"));
|
||||
LCD_PutString_P(PSTR(" Elektrotechnik \r\n"));
|
||||
|
||||
// And copy framebuffer to display
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
}
|
||||
|
||||
#ifndef GDBSTUB
|
||||
void demo_uart(void)
|
||||
{
|
||||
unsigned char loop = 1;
|
||||
signed int c;
|
||||
char buffer[10];
|
||||
|
||||
LCD_Clear();
|
||||
Backlight_LED(BL_BLUE_ON);
|
||||
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("UART-Demonstration \r\n\n"));
|
||||
LCD_PutString_P(PSTR("Setup your terminal: \r\n"));
|
||||
LCD_PutString_P(PSTR("9600 Baud, 8N1 \r\n"));
|
||||
LCD_PutString_P(PSTR("Use joystick to send \r\n"));
|
||||
LCD_PutString_P(PSTR("some strings. \r\n"));
|
||||
|
||||
LCD_GotoXY(20, 7);
|
||||
LCD_PutChar(0x10);
|
||||
|
||||
LCD_Update();
|
||||
|
||||
while ((!((PINA)&0x08)))
|
||||
;
|
||||
_delay_ms(20);
|
||||
while (!((PINA)&0x08))
|
||||
;
|
||||
|
||||
while (loop)
|
||||
{
|
||||
// Get net character from uart fifo
|
||||
c = UART_GetChar();
|
||||
|
||||
// c = -1 means fifo empty
|
||||
if (c > -1)
|
||||
{
|
||||
// wipe last lcd line
|
||||
LCD_WipeLine(7);
|
||||
|
||||
LCD_GotoXY(0, 7);
|
||||
LCD_PutString_P(PSTR("RX-ASCII-Code: "));
|
||||
// Convert interger to ascii
|
||||
itoa(c, buffer, 10);
|
||||
|
||||
LCD_PutString(buffer);
|
||||
LCD_GotoXY(20, 7);
|
||||
LCD_PutChar(0x10);
|
||||
LCD_Update();
|
||||
_delay_ms(10);
|
||||
}
|
||||
|
||||
_delay_ms(20);
|
||||
while (!((PINA)&0xF8))
|
||||
; // Different to DMM 2012 and before
|
||||
|
||||
switch (((PINA)&0xF8))
|
||||
{
|
||||
case 0x78:
|
||||
// Joystick Up
|
||||
UART_PutString("Joystick Up.\r\n");
|
||||
break;
|
||||
case 0xB8:
|
||||
// Joystick Down
|
||||
UART_PutString("Joystick Down.\r\n");
|
||||
break;
|
||||
case 0xD8:
|
||||
// Joystick Left
|
||||
UART_PutString("Joystick Left.\r\n");
|
||||
break;
|
||||
case 0xE8:
|
||||
// Joystick Right
|
||||
UART_PutString("Joystick Right.\r\n");
|
||||
break;
|
||||
case 0xF0:
|
||||
// Joystick Button
|
||||
UART_PutString("Exit.\r\n\n");
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
_delay_ms(200);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void demo_music(void)
|
||||
{
|
||||
LCD_Clear();
|
||||
Backlight_LED(BL_RED_ON);
|
||||
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Let's dance!\r\n\n"));
|
||||
LCD_PutString_P(PSTR("(Finest PWM sounds!)\r\n\n"));
|
||||
LCD_Update();
|
||||
|
||||
Music_PlayTrack(MUSIC_Tetris);
|
||||
|
||||
LCD_PutString_P(PSTR("OK, that's enough...\r\n\n"));
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
}
|
||||
|
||||
void demo_display(void)
|
||||
{
|
||||
// switch white backlight on
|
||||
Backlight_LED(BL_RED_ON | BL_GREEN_ON | BL_BLUE_ON);
|
||||
|
||||
// clear display
|
||||
LCD_Clear();
|
||||
|
||||
// talking to the user
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Set some pixels."));
|
||||
|
||||
LCD_DrawPixel(10, 10, 1);
|
||||
LCD_DrawPixel(12, 44, 1);
|
||||
LCD_DrawPixel(111, 62, 1);
|
||||
LCD_DrawPixel(101, 22, 1);
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
|
||||
// one display page requires 8 pages in dataflash
|
||||
LCD_SavePage(0);
|
||||
LCD_WipeLine(0);
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Connecting."));
|
||||
|
||||
LCD_DrawLine(10, 10, 12, 44, 1);
|
||||
LCD_DrawLine(12, 44, 111, 62, 1);
|
||||
LCD_DrawLine(111, 62, 101, 22, 1);
|
||||
LCD_DrawLine(101, 22, 10, 10, 1);
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
|
||||
// first display page was stored at flash page 0
|
||||
// second display page will start at 8
|
||||
LCD_SavePage(8);
|
||||
LCD_WipeLine(0);
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Adding circles."));
|
||||
|
||||
LCD_DrawCircle(64, 32, 10, 1);
|
||||
LCD_DrawCircle(70, 30, 20, 1);
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
|
||||
// talking to the user
|
||||
LCD_SavePage(16);
|
||||
LCD_Clear();
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Clear/Set/XOR Demo."));
|
||||
|
||||
for (unsigned int fill = 0; fill < 128; fill++)
|
||||
LCD_DrawLine(fill, 10, fill, 53, (fill / 8) & 1);
|
||||
|
||||
// Clear
|
||||
LCD_DrawLine(0, 20, 127, 20, 0);
|
||||
|
||||
// Set
|
||||
LCD_DrawLine(0, 30, 127, 30, 1);
|
||||
|
||||
// XOR
|
||||
LCD_DrawLine(0, 40, 127, 40, 2);
|
||||
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
|
||||
// talking to the user
|
||||
LCD_SavePage(24);
|
||||
LCD_Clear();
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Use the joystick to\r\n"));
|
||||
LCD_PutString_P(PSTR("recall the last\r\n"));
|
||||
LCD_PutString_P(PSTR("screens. Again,\r\n"));
|
||||
LCD_PutString_P(PSTR("button means exit.\r\n"));
|
||||
LCD_Update();
|
||||
|
||||
unsigned char loop = 1;
|
||||
|
||||
while (loop)
|
||||
{
|
||||
// wait
|
||||
while ((!((PINA)&0xF8)))
|
||||
; // Different to DMM 2012 and before
|
||||
_delay_ms(300);
|
||||
while (!((PINA)&0xF8))
|
||||
; // Different to DMM 2012 and before
|
||||
|
||||
switch ((~PINA) & 0xF8) // Different to DMM 2012 and before
|
||||
{
|
||||
case 0x80:
|
||||
// UP
|
||||
LCD_LoadPage(0);
|
||||
LCD_WipeLine(0);
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Screen 1"));
|
||||
LCD_Update();
|
||||
break;
|
||||
case 0x40:
|
||||
// DOWN
|
||||
LCD_LoadPage(24);
|
||||
LCD_WipeLine(0);
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Screen 4"));
|
||||
LCD_Update();
|
||||
break;
|
||||
case 0x20:
|
||||
// LEFT
|
||||
LCD_LoadPage(8);
|
||||
LCD_WipeLine(0);
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Screen 2"));
|
||||
LCD_Update();
|
||||
break;
|
||||
case 0x10:
|
||||
// RIGHT
|
||||
LCD_LoadPage(16);
|
||||
LCD_WipeLine(0);
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Screen 3"));
|
||||
LCD_Update();
|
||||
break;
|
||||
case 0x08:
|
||||
// BUTTON
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// talking to the user
|
||||
LCD_Clear();
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Push button for\r\n"));
|
||||
LCD_PutString_P(PSTR("next demonstration.\r\n"));
|
||||
|
||||
wait_joy_button();
|
||||
}
|
||||
|
||||
void demo_backlight(void)
|
||||
{
|
||||
unsigned char led_active = 0x80;
|
||||
|
||||
// white backlight
|
||||
Backlight_LED(BL_RED_ON | BL_GREEN_ON | BL_BLUE_ON);
|
||||
|
||||
LCD_Clear();
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR("Use the joystick to\r\n"));
|
||||
LCD_PutString_P(PSTR("toggle the backlight\r\n"));
|
||||
LCD_PutString_P(PSTR("on the next screen."));
|
||||
LCD_Update();
|
||||
|
||||
wait_joy_button();
|
||||
|
||||
// no backlight
|
||||
Backlight_Off();
|
||||
|
||||
LCD_Clear();
|
||||
LCD_GotoXY(0, 0);
|
||||
LCD_PutString_P(PSTR(" Red \r\n"));
|
||||
LCD_PutString_P(PSTR(" \r\n"));
|
||||
LCD_PutString_P(PSTR(" \x18 \r\n"));
|
||||
LCD_PutString_P(PSTR(" Green \x1b Exit \x1a Blue \r\n"));
|
||||
LCD_PutString_P(PSTR(" \x19 \r\n"));
|
||||
LCD_PutString_P(PSTR(" \r\n"));
|
||||
LCD_PutString_P(PSTR(" Toggle \r\n"));
|
||||
LCD_PutString_P(PSTR(" all \x10\r\n"));
|
||||
LCD_Update();
|
||||
|
||||
while (!((PINA)&0x08))
|
||||
;
|
||||
_delay_ms(20);
|
||||
while (!((PINA)&0x08))
|
||||
;
|
||||
|
||||
while (led_active & 0x80)
|
||||
{
|
||||
|
||||
while ((~(PINA)&0xF8))
|
||||
; // Different to DMM 2012 and before
|
||||
_delay_ms(300);
|
||||
while (!((PINA)&0xF8))
|
||||
; // Different to DMM 2012 and before
|
||||
|
||||
switch ((~PINA) & 0xF8) // Different to DMM 2012 and before
|
||||
{
|
||||
case 0x08:
|
||||
// Button -> Exit
|
||||
led_active = 0x00;
|
||||
|
||||
break;
|
||||
case 0x80:
|
||||
// Up -> Toggle Red
|
||||
led_active ^= 0x01;
|
||||
break;
|
||||
case 0x20:
|
||||
// Up -> Toggle Green
|
||||
led_active ^= 0x04;
|
||||
break;
|
||||
case 0x10:
|
||||
// Up -> Toggle Blue
|
||||
led_active ^= 0x10;
|
||||
break;
|
||||
case 0x40:
|
||||
// Up -> Toggle All
|
||||
led_active ^= 0x15;
|
||||
break;
|
||||
}
|
||||
|
||||
while (!(PINA & 0xf8))
|
||||
;
|
||||
|
||||
Backlight_LED(led_active & 0x15);
|
||||
|
||||
PORTB &= ~0x0f;
|
||||
if (led_active & 0x01)
|
||||
PORTB |= 0x01;
|
||||
if (led_active & 0x04)
|
||||
PORTB |= 0x02;
|
||||
if (led_active & 0x10)
|
||||
PORTB |= 0x04;
|
||||
}
|
||||
|
||||
LCD_Clear();
|
||||
}
|
||||
109
Firmware/src/music.c
Normal file
109
Firmware/src/music.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
#include <util/atomic.h>
|
||||
|
||||
#include "music.h"
|
||||
|
||||
/* Sine lookup table for the PWM generator (pp = 32) */
|
||||
static const PROGMEM unsigned char sine_lookup[]={
|
||||
0x10,0x13,0x16,0x19,0x1b,0x1d,0x1f,0x20,
|
||||
0x20,0x20,0x1f,0x1d,0x1b,0x19,0x16,0x13,
|
||||
0x10,0x0d,0x0a,0x07,0x05,0x03,0x01,0x00,
|
||||
0x00,0x00,0x01,0x03,0x05,0x07,0x0a,0x0d
|
||||
};
|
||||
|
||||
const MUSIC_Note MUSIC_Tetris[] = {
|
||||
{ MUSIC_E5, MUSIC_4 },
|
||||
{ MUSIC_B4, MUSIC_8 },
|
||||
{ MUSIC_C5, MUSIC_8 },
|
||||
{ MUSIC_D5, MUSIC_4 },
|
||||
{ MUSIC_C5, MUSIC_8 },
|
||||
{ MUSIC_D5, MUSIC_8 },
|
||||
|
||||
{ MUSIC_A4, MUSIC_4 },
|
||||
{ MUSIC_A4, MUSIC_8 },
|
||||
{ MUSIC_C5, MUSIC_8 },
|
||||
{ MUSIC_E5, MUSIC_4 },
|
||||
{ MUSIC_D5, MUSIC_8 },
|
||||
{ MUSIC_C5, MUSIC_8 },
|
||||
|
||||
{ MUSIC_B4, MUSIC_4 + MUSIC_8 },
|
||||
{ MUSIC_C5, MUSIC_8 },
|
||||
{ MUSIC_D5, MUSIC_4 },
|
||||
{ MUSIC_E5, MUSIC_4 },
|
||||
|
||||
{ MUSIC_C5, MUSIC_4 },
|
||||
{ MUSIC_A4, MUSIC_4 },
|
||||
{ MUSIC_A4, MUSIC_8 },
|
||||
|
||||
MUSIC_END };
|
||||
|
||||
static void delay_ms(uint16_t delay);
|
||||
static void pwm_init (void);
|
||||
static void pwm_deinit (void);
|
||||
static void pwm_gen(uint16_t tone, uint16_t periods);
|
||||
|
||||
void Music_PlayTrack (MUSIC_Track track)
|
||||
{
|
||||
pwm_init();
|
||||
|
||||
while (!MUSIC_IS_END(*track)) {
|
||||
|
||||
if (track->tone == 0) {
|
||||
delay_ms(track->duration);
|
||||
} else {
|
||||
uint16_t periods = (uint32_t)track->duration * (uint32_t)track->tone / 1000;
|
||||
pwm_gen(track->tone, periods);
|
||||
|
||||
delay_ms(MUSIC_32 / 2);
|
||||
}
|
||||
|
||||
++track;
|
||||
}
|
||||
|
||||
pwm_deinit();
|
||||
}
|
||||
|
||||
static void delay_ms(uint16_t delay)
|
||||
{
|
||||
while (delay--)
|
||||
_delay_ms(1);
|
||||
}
|
||||
|
||||
void pwm_init (void)
|
||||
{
|
||||
//setup PWM timer
|
||||
DDRD |= _BV(PIND5); // speaker pin => output
|
||||
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM10); //set on match
|
||||
TCCR1B = _BV(CS10) | _BV(WGM12); //fast PWM (8 bit), clk/1 source
|
||||
|
||||
//setup sample timer (CTC Mode)
|
||||
TCCR3A = 0;
|
||||
TCCR3B = _BV(CS30) | _BV(WGM32); // clk/1
|
||||
}
|
||||
|
||||
void pwm_deinit (void)
|
||||
{
|
||||
TCCR1A = 0;
|
||||
TCCR1B = 0;
|
||||
TCCR3A = 0;
|
||||
TCCR3B = 0;
|
||||
}
|
||||
|
||||
void pwm_gen(uint16_t tone, uint16_t periods)
|
||||
{
|
||||
//calculate single sine sample duration
|
||||
OCR3A = F_CPU / tone / sizeof(sine_lookup) - 1;
|
||||
|
||||
for (uint16_t period=0; period < periods; ++period) {
|
||||
for (uint8_t spl=0; spl < sizeof(sine_lookup); ++spl) {
|
||||
//wait for timer ready for next spl
|
||||
loop_until_bit_is_set(TIFR3, OCF1A);
|
||||
TIFR3 = _BV(OCF1A); //clear OCF
|
||||
|
||||
OCR1A = pgm_read_byte(sine_lookup + spl) + 0x70;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user