some code formatting
This commit is contained in:
parent
06dc89109f
commit
84bf510e36
|
@ -1,30 +1,29 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* Minimal Bootloader for Atmega644(p/a)
|
||||
*
|
||||
*
|
||||
* Based on:
|
||||
*
|
||||
* AVRPROG compatible boot-loader
|
||||
* Version : 0.85 (Dec. 2008)
|
||||
* Compiler : avr-gcc 4.1.2 / avr-libc 1.4.6
|
||||
* size : depends on features and startup ( minmal features < 512 words)
|
||||
* by : Martin Thomas, Kaiserslautern, Germany
|
||||
* eversmith@heizung-thomas.de
|
||||
* Additional code and improvements contributed by:
|
||||
* - Uwe Bonnes
|
||||
* - Bjoern Riemer
|
||||
* - Olaf Rempel
|
||||
*
|
||||
* License : Copyright (c) 2006-2008 M. Thomas, U. Bonnes, O. Rempel
|
||||
* Free to use. You have to mention the copyright
|
||||
* owners in source-code and documentation of derived
|
||||
* work. No warranty! (Yes, you can insert the BSD
|
||||
* license here)
|
||||
*
|
||||
******************************************************************************/
|
||||
*
|
||||
* Minimal Bootloader for Atmega644(p/a)
|
||||
*
|
||||
*
|
||||
* Based on:
|
||||
*
|
||||
* AVRPROG compatible boot-loader
|
||||
* Version : 0.85 (Dec. 2008)
|
||||
* Compiler : avr-gcc 4.1.2 / avr-libc 1.4.6
|
||||
* size : depends on features and startup ( minmal features < 512 words)
|
||||
* by : Martin Thomas, Kaiserslautern, Germany
|
||||
* eversmith@heizung-thomas.de
|
||||
* Additional code and improvements contributed by:
|
||||
* - Uwe Bonnes
|
||||
* - Bjoern Riemer
|
||||
* - Olaf Rempel
|
||||
*
|
||||
* License : Copyright (c) 2006-2008 M. Thomas, U. Bonnes, O. Rempel
|
||||
* Free to use. You have to mention the copyright
|
||||
* owners in source-code and documentation of derived
|
||||
* work. No warranty! (Yes, you can insert the BSD
|
||||
* license here)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/* MCU frequency */
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 8000000
|
||||
|
@ -38,11 +37,10 @@
|
|||
|
||||
/* use second UART on mega128 / can128 / mega162 / mega324p / mega644p */
|
||||
//#define UART_USE_SECOND
|
||||
|
||||
/* Device-Type:
|
||||
For AVRProg the BOOT-option is prefered
|
||||
which is the "correct" value for a bootloader.
|
||||
avrdude may only detect the part-code for ISP */
|
||||
For AVRProg the BOOT-option is prefered
|
||||
which is the "correct" value for a bootloader.
|
||||
avrdude may only detect the part-code for ISP */
|
||||
#define DEVTYPE DEVTYPE_BOOT
|
||||
// #define DEVTYPE DEVTYPE_ISP
|
||||
|
||||
|
@ -61,7 +59,9 @@
|
|||
*/
|
||||
#define EXIT_WDT_TIME WDTO_250MS
|
||||
|
||||
void __vector_default(void) { ; }
|
||||
void __vector_default(void) {
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* define the following if the bootloader should not output
|
||||
|
@ -69,11 +69,9 @@ void __vector_default(void) { ; }
|
|||
*/
|
||||
#define READ_PROTECT_BOOTLOADER
|
||||
|
||||
|
||||
#define VERSION_HIGH '0'
|
||||
#define VERSION_LOW '8'
|
||||
|
||||
|
||||
#ifdef UART_DOUBLESPEED
|
||||
// #define UART_CALC_BAUDRATE(baudRate) (((F_CPU*10UL) / ((baudRate) *8UL) +5)/10 -1)
|
||||
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 4UL)) / ((uint32_t)(baudRate) * 8UL) - 1)
|
||||
|
@ -82,7 +80,6 @@ void __vector_default(void) { ; }
|
|||
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 8UL)) / ((uint32_t)(baudRate) * 16UL) - 1)
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
|
@ -95,32 +92,31 @@ void __vector_default(void) { ; }
|
|||
|
||||
uint8_t gBuffer[SPM_PAGESIZE];
|
||||
|
||||
static void sendchar(uint8_t data)
|
||||
{
|
||||
while (!(UART_STATUS & (1<<UART_TXREADY)));
|
||||
static void sendchar(uint8_t data) {
|
||||
while (!(UART_STATUS & (1 << UART_TXREADY)))
|
||||
;
|
||||
UART_DATA = data;
|
||||
}
|
||||
|
||||
static uint8_t recvchar(void)
|
||||
{
|
||||
while (!(UART_STATUS & (1<<UART_RXREADY)));
|
||||
static uint8_t recvchar(void) {
|
||||
while (!(UART_STATUS & (1 << UART_RXREADY)))
|
||||
;
|
||||
return UART_DATA;
|
||||
}
|
||||
|
||||
static inline void eraseFlash(void)
|
||||
{
|
||||
static inline void eraseFlash(void) {
|
||||
// erase only main section (bootloader protection)
|
||||
uint32_t addr = 0;
|
||||
while (APP_END > addr) {
|
||||
boot_page_erase(addr); // Perform page erase
|
||||
boot_spm_busy_wait(); // Wait until the memory is erased.
|
||||
boot_page_erase(addr);
|
||||
// Perform page erase
|
||||
boot_spm_busy_wait(); // Wait until the memory is erased.
|
||||
addr += SPM_PAGESIZE;
|
||||
}
|
||||
boot_rww_enable();
|
||||
}
|
||||
|
||||
static inline void recvBuffer(pagebuf_t size)
|
||||
{
|
||||
static inline void recvBuffer(pagebuf_t size) {
|
||||
pagebuf_t cnt;
|
||||
uint8_t *tmp = gBuffer;
|
||||
|
||||
|
@ -129,9 +125,8 @@ static inline void recvBuffer(pagebuf_t size)
|
|||
}
|
||||
}
|
||||
|
||||
static inline uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size)
|
||||
{
|
||||
uint32_t pagestart = (uint32_t)waddr<<1;
|
||||
static inline uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size) {
|
||||
uint32_t pagestart = (uint32_t) waddr << 1;
|
||||
uint32_t baddr = pagestart;
|
||||
uint16_t data;
|
||||
uint8_t *tmp = gBuffer;
|
||||
|
@ -140,26 +135,24 @@ static inline uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size)
|
|||
data = *tmp++;
|
||||
data |= *tmp++ << 8;
|
||||
|
||||
if ( baddr < APP_END )
|
||||
{
|
||||
boot_page_fill(baddr, data); // call asm routine.
|
||||
if (baddr < APP_END) {
|
||||
boot_page_fill(baddr, data);
|
||||
// call asm routine.
|
||||
}
|
||||
|
||||
baddr += 2; // Select next word in memory
|
||||
size -= 2; // Reduce number of bytes to write by two
|
||||
} while (size); // Loop until all bytes written
|
||||
baddr += 2; // Select next word in memory
|
||||
size -= 2; // Reduce number of bytes to write by two
|
||||
} while (size); // Loop until all bytes written
|
||||
|
||||
boot_page_write(pagestart);
|
||||
boot_spm_busy_wait();
|
||||
boot_rww_enable(); // Re-enable the RWW section
|
||||
boot_rww_enable(); // Re-enable the RWW section
|
||||
|
||||
return baddr>>1;
|
||||
return baddr >> 1;
|
||||
}
|
||||
|
||||
|
||||
static inline uint16_t readFlashPage(uint16_t waddr, pagebuf_t size)
|
||||
{
|
||||
uint32_t baddr = (uint32_t)waddr<<1;
|
||||
static inline uint16_t readFlashPage(uint16_t waddr, pagebuf_t size) {
|
||||
uint32_t baddr = (uint32_t) waddr << 1;
|
||||
uint16_t data;
|
||||
|
||||
do {
|
||||
|
@ -172,30 +165,26 @@ static inline uint16_t readFlashPage(uint16_t waddr, pagebuf_t size)
|
|||
#endif
|
||||
#else
|
||||
// don't read bootloader
|
||||
if ( baddr < APP_END ) {
|
||||
if (baddr < APP_END) {
|
||||
#if defined(RAMPZ)
|
||||
data = pgm_read_word_far(baddr);
|
||||
#else
|
||||
data = pgm_read_word_near(baddr);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
data = 0xFFFF; // fake empty
|
||||
}
|
||||
#endif
|
||||
sendchar(data); // send LSB
|
||||
sendchar((data >> 8)); // send MSB
|
||||
baddr += 2; // Select next word in memory
|
||||
size -= 2; // Subtract two bytes from number of bytes to read
|
||||
} while (size); // Repeat until block has been read
|
||||
sendchar(data); // send LSB
|
||||
sendchar((data >> 8)); // send MSB
|
||||
baddr += 2; // Select next word in memory
|
||||
size -= 2; // Subtract two bytes from number of bytes to read
|
||||
} while (size); // Repeat until block has been read
|
||||
|
||||
return baddr>>1;
|
||||
return baddr >> 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void send_boot(void)
|
||||
{
|
||||
static void send_boot(void) {
|
||||
sendchar('A');
|
||||
sendchar('V');
|
||||
sendchar('R');
|
||||
|
@ -207,55 +196,52 @@ static void send_boot(void)
|
|||
|
||||
static void (*jump_to_app)(void) = 0x0000;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int main(void) {
|
||||
|
||||
bootloader_wdt_off();
|
||||
bootloader_wdt_off();
|
||||
|
||||
uint16_t address = 0;
|
||||
uint8_t device = 0, val;
|
||||
|
||||
BLDDR &= ~(1<<BLPNUM); // set as Input
|
||||
BLPORT |= (1<<BLPNUM); // Enable pullup
|
||||
BLDDR &= ~(1 << BLPNUM); // set as Input
|
||||
BLPORT |= (1 << BLPNUM); // Enable pullup
|
||||
|
||||
|
||||
UART_STATUS = ( 1<<UART_DOUBLE );
|
||||
UART_STATUS = (1 << UART_DOUBLE);
|
||||
UART_BAUD_HIGH = 0;
|
||||
UART_BAUD_LOW = 25;
|
||||
|
||||
UART_CTRL = UART_CTRL_DATA;
|
||||
UART_CTRL2 = UART_CTRL2_DATA;
|
||||
|
||||
if (BLPIN & (1<<BLPNUM)) {
|
||||
if (BLPIN & (1 << BLPNUM)) {
|
||||
// jump to main app if pin is not grounded and GPIOR2 is zero
|
||||
jump_to_app(); // Jump to application sector
|
||||
jump_to_app(); // Jump to application sector
|
||||
}
|
||||
|
||||
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
val = recvchar();
|
||||
// Autoincrement?
|
||||
if (val == 'a') {
|
||||
sendchar('Y'); // Autoincrement is quicker
|
||||
sendchar('Y'); // Autoincrement is quicker
|
||||
|
||||
//write address
|
||||
//write address
|
||||
} else if (val == 'A') {
|
||||
address = recvchar(); //read address 8 MSB
|
||||
address = (address<<8) | recvchar();
|
||||
address = recvchar(); //read address 8 MSB
|
||||
address = (address << 8) | recvchar();
|
||||
sendchar('\r');
|
||||
|
||||
// Buffer load support
|
||||
// Buffer load support
|
||||
} else if (val == 'b') {
|
||||
sendchar('Y'); // Report buffer load supported
|
||||
sendchar((sizeof(gBuffer) >> 8) & 0xFF); // Report buffer size in bytes
|
||||
sendchar('Y'); // Report buffer load supported
|
||||
sendchar((sizeof(gBuffer) >> 8) & 0xFF); // Report buffer size in bytes
|
||||
sendchar(sizeof(gBuffer) & 0xFF);
|
||||
|
||||
// Start buffer load
|
||||
// Start buffer load
|
||||
} else if (val == 'B') {
|
||||
pagebuf_t size;
|
||||
size = recvchar() << 8; // Load high byte of buffersize
|
||||
size |= recvchar(); // Load low byte of buffersize
|
||||
val = recvchar(); // Load memory type ('E' or 'F')
|
||||
size = recvchar() << 8; // Load high byte of buffersize
|
||||
size |= recvchar(); // Load low byte of buffersize
|
||||
val = recvchar(); // Load memory type ('E' or 'F')
|
||||
recvBuffer(size);
|
||||
|
||||
if (device == DEVTYPE) {
|
||||
|
@ -267,75 +253,76 @@ int main(void)
|
|||
sendchar(0);
|
||||
}
|
||||
|
||||
// Block read
|
||||
// Block read
|
||||
} else if (val == 'g') {
|
||||
pagebuf_t size;
|
||||
size = recvchar() << 8; // Load high byte of buffersize
|
||||
size |= recvchar(); // Load low byte of buffersize
|
||||
val = recvchar(); // Get memtype
|
||||
size = recvchar() << 8; // Load high byte of buffersize
|
||||
size |= recvchar(); // Load low byte of buffersize
|
||||
val = recvchar(); // Get memtype
|
||||
|
||||
if (val == 'F') {
|
||||
address = readFlashPage(address, size);
|
||||
}
|
||||
|
||||
// Chip erase
|
||||
} else if (val == 'e') {
|
||||
// Chip erase
|
||||
} else if (val == 'e') {
|
||||
if (device == DEVTYPE) {
|
||||
eraseFlash();
|
||||
}
|
||||
sendchar('\r');
|
||||
|
||||
// Exit upgrade
|
||||
// Exit upgrade
|
||||
} else if (val == 'E') {
|
||||
wdt_enable(EXIT_WDT_TIME); // Enable Watchdog Timer to give reset
|
||||
wdt_enable(EXIT_WDT_TIME);
|
||||
// Enable Watchdog Timer to give reset
|
||||
sendchar('\r');
|
||||
|
||||
// Enter programming mode
|
||||
// Enter programming mode
|
||||
} else if (val == 'P') {
|
||||
sendchar('\r');
|
||||
|
||||
// Leave programming mode
|
||||
// Leave programming mode
|
||||
} else if (val == 'L') {
|
||||
sendchar('\r');
|
||||
|
||||
// return programmer type
|
||||
// return programmer type
|
||||
} else if (val == 'p') {
|
||||
sendchar('S'); // always serial programmer
|
||||
sendchar('S'); // always serial programmer
|
||||
|
||||
// Return device type
|
||||
// Return device type
|
||||
} else if (val == 't') {
|
||||
sendchar(DEVTYPE);
|
||||
sendchar(0);
|
||||
|
||||
// clear and set LED ignored
|
||||
// clear and set LED ignored
|
||||
} else if ((val == 'x') || (val == 'y')) {
|
||||
recvchar();
|
||||
sendchar('\r');
|
||||
|
||||
// set device
|
||||
// set device
|
||||
} else if (val == 'T') {
|
||||
device = recvchar();
|
||||
sendchar('\r');
|
||||
|
||||
// Return software identifier
|
||||
// Return software identifier
|
||||
} else if (val == 'S') {
|
||||
send_boot();
|
||||
|
||||
// Return Software Version
|
||||
// Return Software Version
|
||||
} else if (val == 'V') {
|
||||
sendchar(VERSION_HIGH);
|
||||
sendchar(VERSION_LOW);
|
||||
|
||||
// Return Signature Bytes (it seems that
|
||||
// AVRProg expects the "Atmel-byte" 0x1E last
|
||||
// but shows it first in the dialog-window)
|
||||
// Return Signature Bytes (it seems that
|
||||
// AVRProg expects the "Atmel-byte" 0x1E last
|
||||
// but shows it first in the dialog-window)
|
||||
} else if (val == 's') {
|
||||
sendchar(SIG_BYTE3);
|
||||
sendchar(SIG_BYTE2);
|
||||
sendchar(SIG_BYTE1);
|
||||
|
||||
/* ESC */
|
||||
} else if(val != 0x1b) {
|
||||
/* ESC */
|
||||
} else if (val != 0x1b) {
|
||||
sendchar('?');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,23 +22,17 @@
|
|||
#define UART_CTRL2_DATA (1<<UCSZ00)|(1<<UCSZ01)//((1<<URSEL0) | (1<<UCSZ10) | (1<<UCSZ00))
|
||||
#define UART_DATA UDR0
|
||||
|
||||
|
||||
static inline void bootloader_wdt_off(void)
|
||||
{
|
||||
static inline void bootloader_wdt_off(void) {
|
||||
// cli();
|
||||
wdt_reset();
|
||||
/* Clear WDRF in MCUSR */
|
||||
MCUSR &= ~(1<<WDRF);
|
||||
MCUSR &= ~(1 << WDRF);
|
||||
/* Write logical one to WDCE and WDE */
|
||||
/* Keep old prescaler setting to prevent unintentional time-out */
|
||||
WDTCSR |= (1<<WDCE) | (1<<WDE);
|
||||
WDTCSR |= (1 << WDCE) | (1 << WDE);
|
||||
/* Turn off WDT */
|
||||
WDTCSR = 0x00;
|
||||
}
|
||||
|
||||
|
||||
#endif // #ifndef _MEGA88_H_
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,106 +1,104 @@
|
|||
#include <avr/pgmspace.h>
|
||||
|
||||
|
||||
|
||||
const uint16_t freq_table[] PROGMEM = {
|
||||
/*0x00*/ 39,
|
||||
/*0x01*/ 41,
|
||||
/*0x02*/ 43,
|
||||
/*0x03*/ 46,
|
||||
/*0x04*/ 49,
|
||||
/*0x05*/ 51,
|
||||
/*0x06*/ 54,
|
||||
/*0x07*/ 58,
|
||||
/*0x08*/ 61,
|
||||
/*0x09*/ 65,
|
||||
/*0x0a*/ 69,
|
||||
/*0x0b*/ 73,
|
||||
/*0x0c*/ 77,
|
||||
/*0x0d*/ 82,
|
||||
/*0x0e*/ 87,
|
||||
/*0x0f*/ 92,
|
||||
/*0x10*/ 97,
|
||||
/*0x11*/ 103,
|
||||
/*0x12*/ 109,
|
||||
/*0x13*/ 115,
|
||||
/*0x14*/ 122,
|
||||
/*0x15*/ 130,
|
||||
/*0x16*/ 137,
|
||||
/*0x17*/ 145,
|
||||
/*0x18*/ 154,
|
||||
/*0x19*/ 163,
|
||||
/*0x1a*/ 173,
|
||||
/*0x1b*/ 183,
|
||||
/*0x1c*/ 194,
|
||||
/*0x1d*/ 206,
|
||||
/*0x1e*/ 218,
|
||||
/*0x1f*/ 231,
|
||||
/*0x20*/ 245,
|
||||
/*0x21*/ 259,
|
||||
/*0x22*/ 275,
|
||||
/*0x23*/ 291,
|
||||
/*0x24*/ 308,
|
||||
/*0x25*/ 327,
|
||||
/*0x26*/ 346,
|
||||
/*0x27*/ 367,
|
||||
/*0x28*/ 388,
|
||||
/*0x29*/ 412,
|
||||
/*0x2a*/ 436,
|
||||
/*0x2b*/ 462,
|
||||
/*0x2c*/ 489,
|
||||
/*0x2d*/ 518,
|
||||
/*0x2e*/ 549,
|
||||
/*0x2f*/ 582,
|
||||
/*0x30*/ 617,
|
||||
/*0x31*/ 653,
|
||||
/*0x32*/ 692,
|
||||
/*0x33*/ 733,
|
||||
/*0x34*/ 777,
|
||||
/*0x35*/ 823,
|
||||
/*0x36*/ 872,
|
||||
/*0x37*/ 924,
|
||||
/*0x38*/ 979,
|
||||
/*0x39*/ 1037,
|
||||
/*0x3a*/ 1099,
|
||||
/*0x3b*/ 1164,
|
||||
/*0x3c*/ 1233,
|
||||
/*0x3d*/ 1306,
|
||||
/*0x3e*/ 1384,
|
||||
/*0x3f*/ 1466,
|
||||
/*0x40*/ 1554,
|
||||
/*0x41*/ 1646,
|
||||
/*0x42*/ 1744,
|
||||
/*0x43*/ 1848,
|
||||
/*0x44*/ 1957,
|
||||
/*0x45*/ 2074,
|
||||
/*0x46*/ 2197,
|
||||
/*0x47*/ 2328,
|
||||
/*0x48*/ 2466,
|
||||
/*0x49*/ 2613,
|
||||
/*0x4a*/ 2768,
|
||||
/*0x4b*/ 2933,
|
||||
/*0x4c*/ 3107,
|
||||
/*0x4d*/ 3292,
|
||||
/*0x4e*/ 3488,
|
||||
/*0x4f*/ 3695,
|
||||
/*0x50*/ 3915,
|
||||
/*0x51*/ 4148,
|
||||
/*0x52*/ 4394,
|
||||
/*0x53*/ 4656,
|
||||
/*0x54*/ 4933,
|
||||
/*0x55*/ 5226,
|
||||
/*0x56*/ 5537,
|
||||
/*0x57*/ 5866,
|
||||
/*0x58*/ 6215,
|
||||
/*0x59*/ 6584,
|
||||
/*0x5a*/ 6976,
|
||||
/*0x5b*/ 7390,
|
||||
/*0x5c*/ 7830,
|
||||
/*0x5d*/ 8295,
|
||||
/*0x5e*/ 8789,
|
||||
/*0x5f*/ 9311,
|
||||
/*0x60*/ 9865,
|
||||
/*0x61*/ 10452,
|
||||
/*0x62*/ 11073,
|
||||
/*0x63*/ 11732,
|
||||
/*0x00*/39,
|
||||
/*0x01*/41,
|
||||
/*0x02*/43,
|
||||
/*0x03*/46,
|
||||
/*0x04*/49,
|
||||
/*0x05*/51,
|
||||
/*0x06*/54,
|
||||
/*0x07*/58,
|
||||
/*0x08*/61,
|
||||
/*0x09*/65,
|
||||
/*0x0a*/69,
|
||||
/*0x0b*/73,
|
||||
/*0x0c*/77,
|
||||
/*0x0d*/82,
|
||||
/*0x0e*/87,
|
||||
/*0x0f*/92,
|
||||
/*0x10*/97,
|
||||
/*0x11*/103,
|
||||
/*0x12*/109,
|
||||
/*0x13*/115,
|
||||
/*0x14*/122,
|
||||
/*0x15*/130,
|
||||
/*0x16*/137,
|
||||
/*0x17*/145,
|
||||
/*0x18*/154,
|
||||
/*0x19*/163,
|
||||
/*0x1a*/173,
|
||||
/*0x1b*/183,
|
||||
/*0x1c*/194,
|
||||
/*0x1d*/206,
|
||||
/*0x1e*/218,
|
||||
/*0x1f*/231,
|
||||
/*0x20*/245,
|
||||
/*0x21*/259,
|
||||
/*0x22*/275,
|
||||
/*0x23*/291,
|
||||
/*0x24*/308,
|
||||
/*0x25*/327,
|
||||
/*0x26*/346,
|
||||
/*0x27*/367,
|
||||
/*0x28*/388,
|
||||
/*0x29*/412,
|
||||
/*0x2a*/436,
|
||||
/*0x2b*/462,
|
||||
/*0x2c*/489,
|
||||
/*0x2d*/518,
|
||||
/*0x2e*/549,
|
||||
/*0x2f*/582,
|
||||
/*0x30*/617,
|
||||
/*0x31*/653,
|
||||
/*0x32*/692,
|
||||
/*0x33*/733,
|
||||
/*0x34*/777,
|
||||
/*0x35*/823,
|
||||
/*0x36*/872,
|
||||
/*0x37*/924,
|
||||
/*0x38*/979,
|
||||
/*0x39*/1037,
|
||||
/*0x3a*/1099,
|
||||
/*0x3b*/1164,
|
||||
/*0x3c*/1233,
|
||||
/*0x3d*/1306,
|
||||
/*0x3e*/1384,
|
||||
/*0x3f*/1466,
|
||||
/*0x40*/1554,
|
||||
/*0x41*/1646,
|
||||
/*0x42*/1744,
|
||||
/*0x43*/1848,
|
||||
/*0x44*/1957,
|
||||
/*0x45*/2074,
|
||||
/*0x46*/2197,
|
||||
/*0x47*/2328,
|
||||
/*0x48*/2466,
|
||||
/*0x49*/2613,
|
||||
/*0x4a*/2768,
|
||||
/*0x4b*/2933,
|
||||
/*0x4c*/3107,
|
||||
/*0x4d*/3292,
|
||||
/*0x4e*/3488,
|
||||
/*0x4f*/3695,
|
||||
/*0x50*/3915,
|
||||
/*0x51*/4148,
|
||||
/*0x52*/4394,
|
||||
/*0x53*/4656,
|
||||
/*0x54*/4933,
|
||||
/*0x55*/5226,
|
||||
/*0x56*/5537,
|
||||
/*0x57*/5866,
|
||||
/*0x58*/6215,
|
||||
/*0x59*/6584,
|
||||
/*0x5a*/6976,
|
||||
/*0x5b*/7390,
|
||||
/*0x5c*/7830,
|
||||
/*0x5d*/8295,
|
||||
/*0x5e*/8789,
|
||||
/*0x5f*/9311,
|
||||
/*0x60*/9865,
|
||||
/*0x61*/10452,
|
||||
/*0x62*/11073,
|
||||
/*0x63*/11732,
|
||||
};
|
||||
|
|
|
@ -2,223 +2,211 @@
|
|||
#include <avr/io.h>
|
||||
#include "bughal.h"
|
||||
#include "util.h" //for timer
|
||||
|
||||
/* Hardware abstraction layer for Pentabug hardware */
|
||||
|
||||
/*
|
||||
* initialize LEDs on C0-C3
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
static uint8_t oldinput; // button readings from last poll cycle
|
||||
static uint8_t curinput; // button readings from current poll cycle
|
||||
|
||||
//each switch has its own state machine
|
||||
static uint8_t btnstates[BTN_BUTTONS]; //array for current button states
|
||||
static uint8_t btncounters[BTN_BUTTONS]; //individual counter for button state machine
|
||||
static timer_t btntimers[BTN_BUTTONS]; //individiual timer for for button state machine
|
||||
static timer_t btntimers[BTN_BUTTONS]; //individiual timer for for button state machine
|
||||
|
||||
|
||||
|
||||
void init_leds(void){
|
||||
void init_leds(void) {
|
||||
//enable LED channels as output
|
||||
DDRC |= (1 << PORTC0) | (1 << PORTC1) | (1 << PORTC2) | (1 << PORTC3);
|
||||
// both LEDs off
|
||||
PORTC &= ~((1 << PORTC0) | (1 << PORTC1) | (1 << PORTC2) | (1 << PORTC3));
|
||||
|
||||
|
||||
//TCCR2A = (1 << WGM21);
|
||||
//TCCR2B = (1 << CS20)|(1 << CS21);
|
||||
//OCR2A = 255; /* TOP */
|
||||
// TCNT2 = 0;
|
||||
// /*enable interrupt*/
|
||||
// TIMSK2 |= (1<<OCIE2A);
|
||||
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
inline void led_on(int leds){
|
||||
PORTC |= leds;
|
||||
inline void led_on(int leds) {
|
||||
PORTC |= leds;
|
||||
}
|
||||
|
||||
inline void led_off(int leds){
|
||||
inline void led_off(int leds) {
|
||||
PORTC &= ~leds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void init_buzzr(void){
|
||||
//its on B2 and C5, for reasons
|
||||
void init_buzzr(void) {
|
||||
// its on B2 and C5
|
||||
DDRC |= (1 << PORTC5);
|
||||
DDRB |= (1 << PORTB2);
|
||||
//switch it off
|
||||
// switch it off
|
||||
buzzr_off();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void init_mic(void){
|
||||
//buzzer is on B2 and C5, for reasons
|
||||
// we use it as a mic
|
||||
DDRC &= ~(1 << PORTC5); //switch C5 to input
|
||||
DDRB |= (1 << PORTB2); //B2 as output
|
||||
PORTB &= ~(1 << PORTB2);//and to GND
|
||||
ADMUX = (1<<REFS1) | (1<<REFS0); //use internal 1.1V as reference
|
||||
ADCSRA = (1<<ADPS1) | (1<<ADPS0);// prescaler F_CPU/8
|
||||
ADCSRA |= (1<<ADEN) | (1<<ADATE);// ADC enable - turn it on in free running mode
|
||||
ADCSRB &= (1<<ACME); //leave only ACME as it is (others zerp for free running)
|
||||
ADMUX = (ADMUX & ~(0x1F)) | 5; // select channel 5
|
||||
ADCSRA |= (1<<ADSC); // start conversion
|
||||
void init_mic(void) {
|
||||
// buzzer is on B2 and C5, for reasons
|
||||
// ... we use it as microphone
|
||||
DDRC &= ~(1 << PORTC5); // switch C5 to input
|
||||
DDRB |= (1 << PORTB2); // B2 as output
|
||||
PORTB &= ~(1 << PORTB2); //and to GND
|
||||
ADMUX = (1 << REFS1) | (1 << REFS0); // use internal 1.1V as reference
|
||||
ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8
|
||||
ADCSRA |= (1 << ADEN) | (1 << ADATE); // ADC enable - turn it on in free running mode
|
||||
ADCSRB &= (1 << ACME); //leave only ACME as it is (others zerp for free running)
|
||||
ADMUX = (ADMUX & ~(0x1F)) | 5; // select channel 5
|
||||
ADCSRA |= (1 << ADSC); // start conversion
|
||||
uint16_t __attribute__((unused)) dummy = ADCW; //read once
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void buzzr_up(void){
|
||||
void buzzr_up(void) {
|
||||
// one pin Vcc, other GND
|
||||
PORTC &= ~(1 << PORTC5);
|
||||
PORTB |= (1 << PORTB2);
|
||||
return;
|
||||
}
|
||||
;
|
||||
|
||||
void buzzr_down(void){
|
||||
void buzzr_down(void) {
|
||||
// one pin GND,other pin Vcc
|
||||
PORTC |= (1 << PORTC5);
|
||||
PORTB &= ~(1 << PORTB2);
|
||||
}
|
||||
|
||||
inline void buzzr_off(void){
|
||||
inline void buzzr_off(void) {
|
||||
// both pins to GND
|
||||
PORTC &= ~(1 << PORTC5);
|
||||
PORTB &= ~(1 << PORTB2);
|
||||
}
|
||||
void buzzr_inv(void){
|
||||
|
||||
|
||||
void buzzr_inv(void) {
|
||||
// read and invert pin settings, make the piezo flip polarity
|
||||
PORTC ^= (1 << PORTC5);
|
||||
PORTB ^= (1 << PORTB2);
|
||||
}
|
||||
|
||||
void init_switch(void){
|
||||
DDRD &= ~( (1 << PORTD1) | (1<<PORTD0));
|
||||
PORTD |= (1 << PORTD1) | (1<<PORTD0); //Pullups FTW
|
||||
// set predefined buttonstates
|
||||
|
||||
void init_switch(void) {
|
||||
// init switch 1 and switch 2
|
||||
DDRD &= ~((1 << PORTD1) | (1 << PORTD0)); // D0 and D1 as input
|
||||
PORTD |= (1 << PORTD1) | (1 << PORTD0); // pull-ups FTW
|
||||
// set predefined button states
|
||||
oldinput = 0;
|
||||
curinput = 0;
|
||||
for(uint8_t i=0; i<BTN_BUTTONS; i++){
|
||||
// initialize the state machine of each button
|
||||
for (uint8_t i = 0; i < BTN_BUTTONS; i++) {
|
||||
btnstates[i] = BTNST_NTRL; //init button states
|
||||
btncounters[i] = 0; //init button counters
|
||||
btncounters[i] = 0; //init button counters
|
||||
timer_set(&btntimers[i], 0x05); //50ms - init button timers
|
||||
}
|
||||
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
bool switch_l(void){
|
||||
|
||||
bool switch_l(void) {
|
||||
return !(PIND & 0b00000001);
|
||||
};
|
||||
}
|
||||
|
||||
bool switch_r(void){
|
||||
|
||||
bool switch_r(void) {
|
||||
return !(PIND & 0b00000010);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void init_motor(void)
|
||||
{
|
||||
void init_motor(void) {
|
||||
/* vibration motor on B1, initially off: */
|
||||
DDRB |= (1 << PORTB1);
|
||||
PORTB &= ~( 1<<PORTB1);
|
||||
DDRB |= (1 << PORTB1);
|
||||
PORTB &= ~(1 << PORTB1);
|
||||
return;
|
||||
}
|
||||
|
||||
void set_motor(int val){
|
||||
if (val==MOTOR_ON) {
|
||||
PORTB |= 0x02;
|
||||
} else {
|
||||
PORTB &= ~(0x02);
|
||||
void set_motor(int val) {
|
||||
if (val == MOTOR_ON) {
|
||||
PORTB |= 0x02;
|
||||
} else {
|
||||
PORTB &= ~(0x02);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// reset button to neutral state
|
||||
void button_clear(uint8_t button){
|
||||
void button_clear(uint8_t button) {
|
||||
btnstates[button] = BTNST_NTRL;
|
||||
}
|
||||
|
||||
|
||||
void stateswitch(uint8_t i ){
|
||||
switch(btnstates[i])
|
||||
{
|
||||
case BTNST_NTRL:
|
||||
if (curinput & (1<<i)){ //button down
|
||||
btncounters[i] = 0;
|
||||
btnstates[i] = BTNST_DBNC;
|
||||
void stateswitch(uint8_t i) {
|
||||
switch (btnstates[i]) {
|
||||
case BTNST_NTRL:
|
||||
if (curinput & (1 << i)) { //button down
|
||||
btncounters[i] = 0;
|
||||
btnstates[i] = BTNST_DBNC;
|
||||
}
|
||||
break;
|
||||
//intermediate state, check if button is still pressed to debounce
|
||||
case BTNST_DBNC:
|
||||
btnstates[i] = (curinput & (1 << i)) ? BTNST_SDN : BTNST_NTRL;
|
||||
(btncounters[i])++;
|
||||
break;
|
||||
case BTNST_SDN:
|
||||
if (curinput & (1 << i)) {
|
||||
btncounters[i]++;
|
||||
if (btncounters[i] > BTN_T_LONGFACT) { //500ms held
|
||||
btnstates[i] = BTNST_LDN;
|
||||
}
|
||||
break;
|
||||
//intermediate state, check if button is still pressed to debounce
|
||||
case BTNST_DBNC:
|
||||
btnstates[i] = (curinput & (1<<i))? BTNST_SDN: BTNST_NTRL;
|
||||
(btncounters[i])++;
|
||||
break;
|
||||
case BTNST_SDN:
|
||||
if (curinput & (1<<i)){
|
||||
btncounters[i]++;
|
||||
if (btncounters[i] > BTN_T_LONGFACT){ //500ms held
|
||||
btnstates[i] = BTNST_LDN;
|
||||
}
|
||||
} else { //button was released
|
||||
btnstates[i] = BTNST_SUP;
|
||||
//signal shortclick
|
||||
}
|
||||
break;
|
||||
case BTNST_LDN:
|
||||
if (!(curinput & (1<<i))){
|
||||
//button was released
|
||||
btnstates[i] = BTNST_LUP; //signal longpress
|
||||
}
|
||||
break;
|
||||
case BTNST_SUP:
|
||||
if ((curinput & (1<<i))){
|
||||
//button was pressed again or is bouncing after release
|
||||
btnstates[i] = BTNST_SUPDBNC; //going in special debounce
|
||||
btncounters[i] = 0;
|
||||
}
|
||||
break;
|
||||
case BTNST_LUP:
|
||||
if ((curinput & (1<<i))){
|
||||
//button was pressed again or is bouncing after release
|
||||
btnstates[i] = BTNST_LUPDBNC; //going in special debounce
|
||||
btncounters[i] = 0;
|
||||
}
|
||||
break;
|
||||
case BTNST_SUPDBNC:
|
||||
if ((curinput & (1<<i))){
|
||||
//button is still pressed --> going to shortpress
|
||||
btncounters[i]++;
|
||||
btnstates[i] = BTNST_SDN; //starting over from short pressed
|
||||
} else {
|
||||
btnstates[i] = BTNST_SUP; //nope, it was bouncing, back to old state
|
||||
}
|
||||
break;
|
||||
case BTNST_LUPDBNC:
|
||||
if ((curinput & (1<<i))){
|
||||
//button is still pressed --> going to shortpress
|
||||
btncounters[i]++;
|
||||
btnstates[i] = BTNST_SDN; //starting over from short pressed
|
||||
} else {
|
||||
btnstates[i] = BTNST_LUP; //nope, it was bouncing, back to old state
|
||||
}
|
||||
break;
|
||||
} else { //button was released
|
||||
btnstates[i] = BTNST_SUP;
|
||||
//signal shortclick
|
||||
}
|
||||
break;
|
||||
case BTNST_LDN:
|
||||
if (!(curinput & (1 << i))) {
|
||||
//button was released
|
||||
btnstates[i] = BTNST_LUP; //signal longpress
|
||||
}
|
||||
break;
|
||||
case BTNST_SUP:
|
||||
if ((curinput & (1 << i))) {
|
||||
//button was pressed again or is bouncing after release
|
||||
btnstates[i] = BTNST_SUPDBNC; //going in special debounce
|
||||
btncounters[i] = 0;
|
||||
}
|
||||
break;
|
||||
case BTNST_LUP:
|
||||
if ((curinput & (1 << i))) {
|
||||
//button was pressed again or is bouncing after release
|
||||
btnstates[i] = BTNST_LUPDBNC; //going in special debounce
|
||||
btncounters[i] = 0;
|
||||
}
|
||||
break;
|
||||
case BTNST_SUPDBNC:
|
||||
if ((curinput & (1 << i))) {
|
||||
//button is still pressed --> going to shortpress
|
||||
btncounters[i]++;
|
||||
btnstates[i] = BTNST_SDN; //starting over from short pressed
|
||||
} else {
|
||||
btnstates[i] = BTNST_SUP; //nope, it was bouncing, back to old state
|
||||
}
|
||||
break;
|
||||
case BTNST_LUPDBNC:
|
||||
if ((curinput & (1 << i))) {
|
||||
//button is still pressed --> going to shortpress
|
||||
btncounters[i]++;
|
||||
btnstates[i] = BTNST_SDN; //starting over from short pressed
|
||||
} else {
|
||||
btnstates[i] = BTNST_LUP; //nope, it was bouncing, back to old state
|
||||
}
|
||||
break;
|
||||
default: //curently catches nothing
|
||||
// do nothing yet
|
||||
;
|
||||
break;
|
||||
} //end switch
|
||||
// do nothing yet
|
||||
;
|
||||
break;
|
||||
}; //end switch
|
||||
timer_set(&btntimers[i], BTN_T_DEBOUNCE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void button_poll(){
|
||||
void button_poll() {
|
||||
curinput = ~(PIND & 0b00000011);
|
||||
for(uint8_t i=0; i<BTN_BUTTONS; i++){
|
||||
if (timer_expired(&btntimers[i])){
|
||||
for (uint8_t i = 0; i < BTN_BUTTONS; i++) {
|
||||
if (timer_expired(&btntimers[i])) {
|
||||
stateswitch(i);
|
||||
} //end if timer expired
|
||||
} //end for
|
||||
|
@ -226,9 +214,7 @@ void button_poll(){
|
|||
return;
|
||||
}
|
||||
|
||||
bool btn_state(uint8_t btnstate, uint8_t btn){
|
||||
return (btnstates[btn]==btnstate);
|
||||
bool btn_state(uint8_t btnstate, uint8_t btn) {
|
||||
return (btnstates[btn] == btnstate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
enum {
|
||||
BUZZR_OUT, //initialize buzzer for OUTPUT mode (emmiting soundwaves)
|
||||
BUZZR_IN //initialize buzzer for INPUT mode (registering soundwaves)
|
||||
BUZZR_IN
|
||||
//initialize buzzer for INPUT mode (registering soundwaves)
|
||||
};
|
||||
|
||||
#define LED_L (1 << PORTC0)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
@ -10,47 +9,35 @@
|
|||
|
||||
//static volatile uint16_t currentNote;
|
||||
|
||||
void music_init(void){
|
||||
void music_init(void) {
|
||||
|
||||
TCCR1A = 0; //TIMER1, normal, no PWM
|
||||
TCCR1B = (1 << WGM12) | (1 << CS11); //CTC Mode, Clear Timer on Compare, Prescaler = 8
|
||||
// OCR1A = 500; //invert with 2 KHz --> 1 KHz sound --> 8000000/8/2000
|
||||
// OCR1A = 10000;
|
||||
// TIMSK1 |= (1 << OCIE1A); //enable Output Compare Interrupt
|
||||
TIMSK1 &= ~(1 << OCIE1A); //disable Output Compare Interrupt
|
||||
TCCR1A = 0; //TIMER1, normal, no PWM
|
||||
TCCR1B = (1 << WGM12) | (1 << CS11); //CTC Mode, Clear Timer on Compare, Prescaler = 8
|
||||
TIMSK1 &= ~(1 << OCIE1A); //disable Output Compare Interrupt
|
||||
return;
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
void music_setNote(uint16_t note, uint8_t octave) {
|
||||
|
||||
void music_setNote(uint16_t note, uint8_t octave){
|
||||
|
||||
|
||||
cli();
|
||||
if (note != NOTE_PAUSE){
|
||||
//Play a Note
|
||||
buzzr_up();
|
||||
TIMSK1 |= (1 << OCIE1A); //enable Output Compare Interrupt
|
||||
OCR1A = octave==0 ? note : note / (1 << octave);
|
||||
cli();
|
||||
if (note != NOTE_PAUSE) {
|
||||
//Play a Note
|
||||
buzzr_up();
|
||||
TIMSK1 |= (1 << OCIE1A); //enable Output Compare Interrupt
|
||||
OCR1A = octave == 0 ? note : note / (1 << octave);
|
||||
} else { // Pause (silence)
|
||||
buzzr_off();
|
||||
TIMSK1 &= ~(1 << OCIE1A); //disable Output Compare Interrupt
|
||||
buzzr_off();
|
||||
TIMSK1 &= ~(1 << OCIE1A); //disable Output Compare Interrupt
|
||||
}
|
||||
sei();
|
||||
return;
|
||||
}
|
||||
|
||||
/* timer interrupt function */ISR(TIMER1_COMPA_vect, ISR_NOBLOCK) {
|
||||
|
||||
|
||||
|
||||
/* timer interrupt function */
|
||||
ISR(TIMER1_COMPA_vect, ISR_NOBLOCK) {
|
||||
|
||||
// invert buzzer polarity
|
||||
buzzr_inv();
|
||||
|
||||
// invert buzzer polarity
|
||||
buzzr_inv();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
#ifndef _MUSIC_H
|
||||
#define _MUSIC_H
|
||||
|
||||
|
||||
#define NOTE_PAUSE (65000) //Pause
|
||||
|
||||
//Values for Octave 0
|
||||
#define NOTE_C (30577) // note C
|
||||
#define NOTE_Db (28862) // note C# / Db
|
||||
|
@ -20,8 +18,6 @@
|
|||
#define NOTE_Bb (17161) // note A# / Bb
|
||||
#define NOTE_B (16198) // note B
|
||||
|
||||
|
||||
|
||||
void music_init(void);
|
||||
void music_setNote(uint16_t note, uint8_t octave);
|
||||
#endif
|
||||
|
|
|
@ -14,171 +14,54 @@ enum {
|
|||
pattern_length = 16
|
||||
};
|
||||
|
||||
static const synth_instrument_t instruments[] = { { 1 << 15, 100, 12, 0 }, { 0,
|
||||
100, 12, 0 }, { 0, 200, 10, 0 }, { 1 << 13, 0, 0, 2 }, { 1 << 13, 0, 5,
|
||||
2 }, };
|
||||
|
||||
static const uint8_t wave_table[][2] = { { 0, WAVE_PULSE }, { 3, WAVE_PULSE }, {
|
||||
7, WAVE_PULSE }, { 12, WAVE_PULSE }, { 256 - 4, 0xff },
|
||||
|
||||
static const synth_instrument_t instruments[] = {
|
||||
{ 1<<15, 100, 12, 0 },
|
||||
{ 0, 100, 12, 0 },
|
||||
{ 0, 200, 10, 0 },
|
||||
{ 1<<13, 0, 0, 2 },
|
||||
{ 1<<13, 0, 5, 2 },
|
||||
};
|
||||
{ 0, WAVE_PULSE }, { 2, WAVE_PULSE }, { 7, WAVE_PULSE }, { 10, WAVE_PULSE }, {
|
||||
256 - 4, 0xff },
|
||||
|
||||
static const uint8_t wave_table[][2] = {
|
||||
{ 0, WAVE_PULSE },
|
||||
{ 3, WAVE_PULSE },
|
||||
{ 7, WAVE_PULSE },
|
||||
{ 12, WAVE_PULSE },
|
||||
{ 256 - 4, 0xff },
|
||||
{ 0, WAVE_NOISE }, { 0, WAVE_PULSE }, { 0xff, 0xff },
|
||||
|
||||
{ 0, WAVE_PULSE },
|
||||
{ 2, WAVE_PULSE },
|
||||
{ 7, WAVE_PULSE },
|
||||
{ 10, WAVE_PULSE },
|
||||
{ 256 - 4, 0xff },
|
||||
|
||||
{ 0, WAVE_NOISE },
|
||||
{ 0, WAVE_PULSE },
|
||||
{ 0xff, 0xff },
|
||||
|
||||
{ 0, WAVE_PULSE },
|
||||
{ 0xff, 0xff },
|
||||
{ 0, WAVE_PULSE }, { 0xff, 0xff },
|
||||
|
||||
};
|
||||
|
||||
static const uint8_t patterns[][pattern_length][2] PROGMEM = { { }, { { 33 - 12,
|
||||
0 }, { 0, 0 }, { 0xff, 1 }, { 0, 0 }, { 33, 1 }, { 0xff, 1 }, { 33, 1 },
|
||||
{ 0xff, 1 }, { 33, 1 }, { 0xff, 1 }, { 33 - 12, 1 }, { 0xff, 1 }, { 33
|
||||
- 12, 1 }, { 0xff, 1 }, { 33, 1 }, { 0xff, 1 }, }, { { 28 - 12,
|
||||
0 }, { 0, 0 }, { 0xff, 1 }, { 0, 0 }, { 28, 1 }, { 0xff, 1 }, { 28, 1 },
|
||||
{ 0xff, 1 }, { 28, 1 }, { 0xff, 1 }, { 28 - 12, 1 }, { 0xff, 1 }, { 28
|
||||
- 12, 1 }, { 0xff, 1 }, { 28, 1 }, { 0xff, 1 }, }, { { 0, 0 }, {
|
||||
0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, {
|
||||
57, 3 }, }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
||||
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 57, 4 }, },
|
||||
|
||||
static const uint8_t patterns[][pattern_length][2] PROGMEM = {
|
||||
{},
|
||||
{
|
||||
{ 33 - 12, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0xff, 1 },
|
||||
{ 0, 0 },
|
||||
{ 33, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 33, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 33, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 33 - 12, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 33 - 12, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 33, 1 },
|
||||
{ 0xff, 1 },
|
||||
},
|
||||
{
|
||||
{ 28 - 12, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0xff, 1 },
|
||||
{ 0, 0 },
|
||||
{ 28, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 28, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 28, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 28 - 12, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 28 - 12, 1 },
|
||||
{ 0xff, 1 },
|
||||
{ 28, 1 },
|
||||
{ 0xff, 1 },
|
||||
},
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 57, 3 },
|
||||
},
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 57, 4 },
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
{ 60, 2 },
|
||||
},
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 57, 2 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 55, 2 },
|
||||
{ 0, 0 },
|
||||
{ 57, 2 },
|
||||
{ 0, 0 },
|
||||
},
|
||||
{
|
||||
{ 55, 2 },
|
||||
},
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 57, 2 },
|
||||
},
|
||||
{
|
||||
{ 55-3, 2 },
|
||||
},
|
||||
|
||||
|
||||
|
||||
{ { 60, 2 }, }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 57, 2 }, { 0, 0 }, {
|
||||
0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 55, 2 }, {
|
||||
0, 0 }, { 57, 2 }, { 0, 0 }, }, { { 55, 2 }, }, { { 0, 0 }, { 0, 0 }, {
|
||||
0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0,
|
||||
0 }, { 0, 0 }, { 0, 0 }, { 57, 2 }, }, { { 55 - 3, 2 }, },
|
||||
|
||||
};
|
||||
|
||||
static const uint8_t pattern_table[][channel_count] = {
|
||||
{ 1, 0, 5 },
|
||||
{ 1, 3, 0 },
|
||||
{ 1, 0, 7 },
|
||||
{ 1, 3, 6 },
|
||||
{ 2, 0, 7 },
|
||||
{ 2, 4, 8 },
|
||||
{ 2, 0, 9 },
|
||||
{ 2, 4, 0 },
|
||||
};
|
||||
static const uint8_t pattern_table[][channel_count] = { { 1, 0, 5 },
|
||||
{ 1, 3, 0 }, { 1, 0, 7 }, { 1, 3, 6 }, { 2, 0, 7 }, { 2, 4, 8 }, { 2, 0,
|
||||
9 }, { 2, 4, 0 }, };
|
||||
enum {
|
||||
pattern_table_length = sizeof(pattern_table) / sizeof(pattern_table[0])
|
||||
};
|
||||
|
||||
|
||||
static synth_channel_t channels[channel_count];
|
||||
static int8_t sample;
|
||||
static int8_t tick;
|
||||
static int8_t row;
|
||||
static int8_t seq;
|
||||
|
||||
|
||||
/* PROTOTYPES */
|
||||
uint8_t synth_mix(void);
|
||||
|
||||
|
@ -189,12 +72,10 @@ static uint8_t timeslots_read; // current read head
|
|||
/*register for atomic ++ and -- */
|
||||
register uint8_t timeslots_fill asm("r2");
|
||||
|
||||
|
||||
static void enqueue_timeslot(uint8_t synthval);
|
||||
static uint8_t dequeue_timeslot(void);
|
||||
|
||||
void synth_init(void)
|
||||
{
|
||||
void synth_init(void) {
|
||||
sample = 0;
|
||||
tick = 0;
|
||||
row = 0;
|
||||
|
@ -202,66 +83,69 @@ void synth_init(void)
|
|||
timeslots_fill = 0;
|
||||
}
|
||||
|
||||
inline uint8_t synth_mix(void)
|
||||
{
|
||||
if(sample == 0) { // new tick
|
||||
for(int i = 1; i < channel_count; i++) {
|
||||
inline uint8_t synth_mix(void) {
|
||||
if (sample == 0) { // new tick
|
||||
for (int i = 1; i < channel_count; i++) {
|
||||
synth_channel_t* chan = &channels[i];
|
||||
|
||||
const synth_instrument_t* inst = &instruments[chan->inst_nr];
|
||||
|
||||
if(chan->level > inst->decay) chan->level -= inst->decay;
|
||||
else chan->level = 0;
|
||||
if (chan->level > inst->decay)
|
||||
chan->level -= inst->decay;
|
||||
else
|
||||
chan->level = 0;
|
||||
|
||||
chan->pulse_width += inst->pulse_sweep;
|
||||
|
||||
chan->pos++;
|
||||
if(wave_table[chan->pos][1] == 0xff) chan->pos += wave_table[chan->pos][0];
|
||||
|
||||
if (wave_table[chan->pos][1] == 0xff)
|
||||
chan->pos += wave_table[chan->pos][0];
|
||||
|
||||
// enter new rol
|
||||
// w
|
||||
if(tick == 0) {
|
||||
if (tick == 0) {
|
||||
uint8_t pattern_nr = pattern_table[seq][i];
|
||||
uint8_t note = pgm_read_byte(&patterns[pattern_nr][row][0]);
|
||||
|
||||
if(note) { // new note, maybe?
|
||||
if(note == 0xff) {
|
||||
if (note) { // new note, maybe?
|
||||
if (note == 0xff) {
|
||||
chan->level = 0;
|
||||
} else {
|
||||
chan->level = 80; // TODO: less?
|
||||
chan->note = note;
|
||||
chan->inst_nr = pgm_read_byte(&patterns[pattern_nr][row][1]);
|
||||
chan->inst_nr =
|
||||
pgm_read_byte(&patterns[pattern_nr][row][1]);
|
||||
inst = &instruments[chan->inst_nr];
|
||||
chan->pos = inst->wave_table_pos;
|
||||
if(inst->pulse_width) chan->pulse_width = inst->pulse_width;
|
||||
if (inst->pulse_width)
|
||||
chan->pulse_width = inst->pulse_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(++sample == 0){
|
||||
if(++tick == row_length) {
|
||||
if (++sample == 0) {
|
||||
if (++tick == row_length) {
|
||||
tick = 0;
|
||||
if(++row == pattern_length) {
|
||||
if (++row == pattern_length) {
|
||||
row = 0;
|
||||
if(++seq == pattern_table_length) {
|
||||
if (++seq == pattern_table_length) {
|
||||
seq = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t output = 0;
|
||||
for(int i = 0; i < channel_count; i++) {
|
||||
for (int i = 0; i < channel_count; i++) {
|
||||
synth_channel_t* chan = &channels[i];
|
||||
// const synth_instrument_t* inst = &instruments[chan->inst_nr];
|
||||
// const synth_instrument_t* inst = &instruments[chan->inst_nr];
|
||||
|
||||
chan->phase += pgm_read_word(&freq_table[(uint8_t)(chan->note + wave_table[chan->pos][0])]);
|
||||
chan->phase +=
|
||||
pgm_read_word(&freq_table[(uint8_t)(chan->note + wave_table[chan->pos][0])]);
|
||||
|
||||
uint8_t amp;
|
||||
switch(wave_table[chan->pos][1]) {
|
||||
switch (wave_table[chan->pos][1]) {
|
||||
case WAVE_PULSE:
|
||||
amp = -(chan->phase < chan->pulse_width);
|
||||
break;
|
||||
|
@ -286,12 +170,11 @@ inline uint8_t synth_mix(void)
|
|||
return output;
|
||||
}
|
||||
|
||||
|
||||
/* fill all the timeslots */
|
||||
inline void synth_poll(void) {
|
||||
/* refill timeslots queue */
|
||||
// while (timeslots_fill < (SYNTH_BUFSIZE-1))
|
||||
if (timeslots_fill < (SYNTH_BUFSIZE-1))
|
||||
if (timeslots_fill < (SYNTH_BUFSIZE - 1))
|
||||
enqueue_timeslot(synth_mix());
|
||||
}
|
||||
|
||||
|
@ -304,21 +187,18 @@ static inline void enqueue_timeslot(uint8_t synthval) {
|
|||
|
||||
static inline uint8_t dequeue_timeslot() {
|
||||
uint8_t t = timeslots[timeslots_read & SYNTH_BUFMASK];
|
||||
if(timeslots_fill){
|
||||
if (timeslots_fill) {
|
||||
/* buffer not underrun... move forward in readbuffer */
|
||||
|
||||
timeslots_fill --;
|
||||
timeslots_read ++;
|
||||
}
|
||||
timeslots_fill--;
|
||||
timeslots_read++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
ISR(TIMER0_COMPA_vect)
|
||||
{
|
||||
ISR(TIMER0_COMPA_vect) {
|
||||
/* calculate next analog sample value in synth mixer:*/
|
||||
OCR1B = dequeue_timeslot();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,30 +4,30 @@
|
|||
#define SYNTH_BUFSIZE (16)
|
||||
#define SYNTH_BUFMASK (0b00001111)
|
||||
|
||||
enum { WAVE_OFF, WAVE_PULSE, WAVE_SAW, WAVE_NOISE };
|
||||
enum {
|
||||
WAVE_OFF, WAVE_PULSE, WAVE_SAW, WAVE_NOISE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t note;
|
||||
uint8_t inst_nr;
|
||||
uint8_t note;
|
||||
uint8_t inst_nr;
|
||||
uint8_t pos;
|
||||
|
||||
uint16_t phase;
|
||||
uint16_t pulse_width;
|
||||
|
||||
uint8_t level; // envelop level
|
||||
uint8_t level; // envelop level
|
||||
|
||||
} synth_channel_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t pulse_width;
|
||||
uint8_t pulse_sweep;
|
||||
uint8_t wave_table_pos;
|
||||
uint8_t decay;
|
||||
uint16_t pulse_width;
|
||||
uint8_t pulse_sweep;
|
||||
uint8_t wave_table_pos;
|
||||
uint8_t decay;
|
||||
|
||||
} synth_instrument_t;
|
||||
|
||||
|
||||
void synth_init(void);
|
||||
void synth_poll(void);
|
||||
|
||||
|
|
|
@ -23,62 +23,58 @@
|
|||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
//#include "main.h"
|
||||
#include "usart.h"
|
||||
|
||||
#define UART_RXBUFSIZE 32
|
||||
|
||||
static volatile uint8_t rxbuf0[UART_RXBUFSIZE];
|
||||
static volatile uint8_t *volatile rxhead0, *volatile rxtail0;
|
||||
//volatile uint8_t xon = 0;
|
||||
static volatile uint8_t * volatile rxhead0, * volatile rxtail0;
|
||||
|
||||
|
||||
ISR (USART_RX_vect)
|
||||
{
|
||||
ISR (USART_RX_vect) {
|
||||
UCSR0B &= ~(1 << RXCIE0);
|
||||
asm volatile("sei");
|
||||
|
||||
int diff;
|
||||
uint8_t c;
|
||||
c=UDR0;
|
||||
c = UDR0;
|
||||
diff = rxhead0 - rxtail0;
|
||||
if (diff < 0) diff += UART_RXBUFSIZE;
|
||||
if (diff < UART_RXBUFSIZE -1)
|
||||
{
|
||||
if (diff < 0)
|
||||
diff += UART_RXBUFSIZE;
|
||||
if (diff < UART_RXBUFSIZE - 1) {
|
||||
*rxhead0 = c;
|
||||
++rxhead0;
|
||||
if (rxhead0 == (rxbuf0 + UART_RXBUFSIZE)) rxhead0 = rxbuf0;
|
||||
if (rxhead0 == (rxbuf0 + UART_RXBUFSIZE))
|
||||
rxhead0 = rxbuf0;
|
||||
|
||||
}
|
||||
UCSR0B |= (1 << RXCIE0);
|
||||
}
|
||||
|
||||
|
||||
void USART0_Init (void)
|
||||
{
|
||||
void USART0_Init(void) {
|
||||
// set baudrate
|
||||
#define BAUD_TOL 4
|
||||
#undef BAUD
|
||||
#define BAUD 115200
|
||||
#include <util/setbaud.h>
|
||||
UBRR0H = UBRRH_VALUE;
|
||||
UBRR0L = UBRRL_VALUE;
|
||||
|
||||
#if USE_2X
|
||||
UCSR0A |= (1 << U2X0); // enable double speed operation
|
||||
#else
|
||||
UCSR0A &= ~(1 << U2X0); // disable double speed operation
|
||||
#endif
|
||||
#define BAUD_TOL 4
|
||||
#undef BAUD
|
||||
#define BAUD 115200
|
||||
#include <util/setbaud.h>
|
||||
UBRR0H = UBRRH_VALUE;
|
||||
UBRR0L = UBRRL_VALUE;
|
||||
|
||||
#if USE_2X
|
||||
UCSR0A |= (1 << U2X0); // enable double speed operation
|
||||
#else
|
||||
UCSR0A &= ~(1 << U2X0); // disable double speed operation
|
||||
#endif
|
||||
|
||||
// flush receive buffer
|
||||
while ( UCSR0A & (1 << RXC0) ) UDR0;
|
||||
while (UCSR0A & (1 << RXC0))
|
||||
UDR0;
|
||||
|
||||
// set 8N1
|
||||
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
|
||||
UCSR0B &= ~(1 << UCSZ02);
|
||||
|
||||
UCSR0B |= (1 << RXEN0)|(1 << TXEN0); //enable send and receive
|
||||
UCSR0B |= (1 << RXEN0) | (1 << TXEN0); //enable send and receive
|
||||
|
||||
UCSR0B |= (1 << RXCIE0); //enable receive interrup
|
||||
|
||||
|
@ -86,39 +82,37 @@ void USART0_Init (void)
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void USART0_putc (char c)
|
||||
{
|
||||
void USART0_putc(char c) {
|
||||
loop_until_bit_is_set(UCSR0A, UDRE0);
|
||||
UDR0 = c;
|
||||
}
|
||||
|
||||
|
||||
uint8_t USART0_Getc_nb(uint8_t *c)
|
||||
{
|
||||
if (rxhead0==rxtail0) return 0;
|
||||
uint8_t USART0_Getc_nb(uint8_t *c) {
|
||||
if (rxhead0 == rxtail0)
|
||||
return 0;
|
||||
*c = *rxtail0;
|
||||
if (++rxtail0 == (rxbuf0 + UART_RXBUFSIZE)) rxtail0 = rxbuf0;
|
||||
if (++rxtail0 == (rxbuf0 + UART_RXBUFSIZE))
|
||||
rxtail0 = rxbuf0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void USART0_crlf(void){
|
||||
void USART0_crlf(void) {
|
||||
USART0_putc(0x0A); //newline
|
||||
USART0_putc(0x0D); //carriage return
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
void USART0_put_uint8(uint8_t x){
|
||||
uint8_t highchar=((x & 0b11110000)>>4)+0x30;
|
||||
uint8_t lowchar = (x & 0b00001111)+0x30;
|
||||
highchar = highchar>0x39 ? highchar + 0x07 : highchar; //chars A to F start with 0x41 not 0x3A
|
||||
lowchar = lowchar>0x39 ? lowchar + 0x07 : lowchar;
|
||||
void USART0_put_uint8(uint8_t x) {
|
||||
uint8_t highchar = ((x & 0b11110000) >> 4) + 0x30;
|
||||
uint8_t lowchar = (x & 0b00001111) + 0x30;
|
||||
highchar = highchar > 0x39 ? highchar + 0x07 : highchar; //chars A to F start with 0x41 not 0x3A
|
||||
lowchar = lowchar > 0x39 ? lowchar + 0x07 : lowchar;
|
||||
USART0_putc(highchar);
|
||||
USART0_putc(lowchar);
|
||||
|
||||
}
|
||||
void USART0_put_uint16(uint16_t x){
|
||||
USART0_put_uint8 ((x & 0xFF00)>>8);
|
||||
USART0_put_uint8 (x & 0x00FF);
|
||||
void USART0_put_uint16(uint16_t x) {
|
||||
USART0_put_uint8((x & 0xFF00) >> 8);
|
||||
USART0_put_uint8(x & 0x00FF);
|
||||
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#ifndef _USART_H
|
||||
#define _USART_H
|
||||
|
||||
void USART0_Init (void);
|
||||
void USART0_putc (char c);
|
||||
void USART0_Init(void);
|
||||
void USART0_putc(char c);
|
||||
uint8_t USART0_Getc_nb(uint8_t*);
|
||||
void USART0_put_uint8(uint8_t);
|
||||
void USART0_crlf(void);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/common.h>
|
||||
|
@ -7,65 +6,53 @@
|
|||
|
||||
static volatile uint8_t internal_counter;
|
||||
|
||||
void timer_init(void)
|
||||
{
|
||||
/* initialize timer2, CTC at 10ms, prescaler 1024 */
|
||||
OCR2A = F_CPU/1024/100;
|
||||
TCCR2A = _BV(WGM21);
|
||||
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
|
||||
TIMSK2 = _BV(OCIE2A);
|
||||
void timer_init(void) {
|
||||
/* initialize timer2, CTC at 10ms, prescaler 1024 */
|
||||
OCR2A = F_CPU / 1024 / 100;
|
||||
TCCR2A = _BV(WGM21);
|
||||
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
|
||||
TIMSK2 = _BV(OCIE2A);
|
||||
}
|
||||
|
||||
void timer_set(timer_t *t, uint8_t timeout)
|
||||
{
|
||||
t->current = internal_counter;
|
||||
t->timeout = timeout;
|
||||
void timer_set(timer_t *t, uint8_t timeout) {
|
||||
t->current = internal_counter;
|
||||
t->timeout = timeout;
|
||||
}
|
||||
|
||||
void timerL_set(timerL_t *t, uint16_t timeout)
|
||||
{
|
||||
t->current = internal_counter;
|
||||
t->timeout = timeout;
|
||||
void timerL_set(timerL_t *t, uint16_t timeout) {
|
||||
t->current = internal_counter;
|
||||
t->timeout = timeout;
|
||||
}
|
||||
|
||||
bool timer_expired(timer_t *t) {
|
||||
if (t->timeout == 0)
|
||||
return true;
|
||||
|
||||
/* attention: may fail if internal counter is incremented by more than one
|
||||
* between two calls of timer_expired()! (that is if its is called less than every 10ms*/
|
||||
if (t->current != internal_counter) {
|
||||
t->timeout--;
|
||||
t->current = internal_counter;
|
||||
}
|
||||
|
||||
|
||||
bool timer_expired(timer_t *t)
|
||||
{
|
||||
if (t->timeout == 0)
|
||||
return true;
|
||||
|
||||
/* attention: may fail if internal counter is incremented by more than one
|
||||
* between two calls of timer_expired()! (that is if its is called less than every 10ms*/
|
||||
if (t->current != internal_counter) {
|
||||
t->timeout--;
|
||||
t->current = internal_counter;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool timerL_expired(timerL_t *t) {
|
||||
if (t->timeout == 0)
|
||||
return true;
|
||||
|
||||
bool timerL_expired(timerL_t *t)
|
||||
{
|
||||
if (t->timeout == 0)
|
||||
return true;
|
||||
/* attention: may fail if internal counter is incremented by more than one
|
||||
* between two calls of timer_expired()! */
|
||||
if (t->current != internal_counter) {
|
||||
t->timeout--;
|
||||
t->current = internal_counter;
|
||||
}
|
||||
|
||||
/* attention: may fail if internal counter is incremented by more than one
|
||||
* between two calls of timer_expired()! */
|
||||
if (t->current != internal_counter) {
|
||||
t->timeout--;
|
||||
t->current = internal_counter;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* timer interrupt function */
|
||||
ISR(TIMER2_COMPA_vect, ISR_NOBLOCK) {
|
||||
internal_counter++;
|
||||
/* timer interrupt function */ISR(TIMER2_COMPA_vect, ISR_NOBLOCK) {
|
||||
internal_counter++;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,16 +8,15 @@
|
|||
|
||||
/* structures */
|
||||
typedef struct {
|
||||
uint8_t current;
|
||||
uint8_t timeout;
|
||||
uint8_t current;
|
||||
uint8_t timeout;
|
||||
} timer_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t current;
|
||||
uint16_t timeout;
|
||||
uint16_t current;
|
||||
uint16_t timeout;
|
||||
} timerL_t;
|
||||
|
||||
|
||||
/* functions */
|
||||
void timer_init(void);
|
||||
void timer_set(timer_t *t, uint8_t timeout);
|
||||
|
|
Loading…
Reference in New Issue
Block a user