diff --git a/firmware/Makefile b/firmware/Makefile index a11f549..8e6338b 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -35,7 +35,7 @@ OPT = s ########################################################################################################## # List C source files here. (C dependencies are automatically generated.) -SRC = main.c synth.c usart.c +SRC = main.c lib/synth.c lib/usart.c ########################################################################################################## diff --git a/firmware/main.c b/firmware/main.c index 74d57b2..146cbdb 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -5,8 +5,8 @@ #include #include "main.h" -#include "synth.h" -#include "usart.h" +#include "lib/synth.h" +#include "lib/usart.h" uint16_t sw_v = 0; diff --git a/firmware/synth.c b/firmware/synth.c deleted file mode 100644 index e991e05..0000000 --- a/firmware/synth.c +++ /dev/null @@ -1,324 +0,0 @@ -#include -#include "synth.h" -#include "freq_table.h" -#include -#include - -// sample rate is 8M / (3 * 64) - -enum { - channel_count = 3, - //tick_length = 400, -// tick_length = 256, - row_length = 4, - pattern_length = 16 -}; - - - -static const synth_instrument_t instruments[] = { - { 1<<15, 100, 12 }, - { 0, 100, 12 }, - { 0, 200, 10 }, - { 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 }, - - { 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 }, - -}; - - -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 }, - }, - - - - -}; - -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); - -static uint8_t timeslots[SYNTH_BUFSIZE]; -static uint8_t timeslots_write; // current write head -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) -{ - sample = 0; - tick = 0; - row = 0; - seq = 0; - timeslots_fill = 0; -} - -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; - - chan->pulse_width += inst->pulse_sweep; - - chan->pos++; - if(wave_table[chan->pos][1] == 0xff) chan->pos += wave_table[chan->pos][0]; - - - // enter new rol - // w - 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) { - chan->level = 0; - } else { - chan->level = 80; // TODO: less? - chan->note = note; - 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(++sample == 0){ - if(++tick == row_length) { - tick = 0; - if(++row == pattern_length) { - row = 0; - if(++seq == pattern_table_length) { - seq = 0; - } - } - } - } - - - uint8_t output = 0; - for(int i = 0; i < channel_count; i++) { - synth_channel_t* chan = &channels[i]; - // 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])]); - - uint8_t amp; - switch(wave_table[chan->pos][1]) { - case WAVE_PULSE: - amp = -(chan->phase < chan->pulse_width); - break; - - case WAVE_SAW: - amp = (chan->phase >> 8); - break; - - case WAVE_NOISE: // shitty noise - chan->phase = (chan->phase >> 1) ^ (-(chan->phase & 1) & 0xb400); - amp = (chan->phase >> 8); - break; - - default: - amp = 0; - break; - } - - output += (((amp & 0xff) * chan->level) >> 8); - } - - 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)) - enqueue_timeslot(synth_mix()); -} - -/* timeslot queue handling */ -static inline void enqueue_timeslot(uint8_t synthval) { - timeslots[timeslots_write & SYNTH_BUFMASK] = synthval; - timeslots_fill++; - timeslots_write++; -} - -static inline uint8_t dequeue_timeslot() { - uint8_t t = timeslots[timeslots_read & SYNTH_BUFMASK]; - if(timeslots_fill){ - /* buffer not underrun... move forward in readbuffer */ - - timeslots_fill --; - timeslots_read ++; - } - - return t; -} - - -ISR(TIMER0_COMPA_vect) -{ - /* calculate next analog sample value in synth mixer:*/ - OCR1B = dequeue_timeslot(); -} - - diff --git a/firmware/synth.h b/firmware/synth.h deleted file mode 100644 index 920d419..0000000 --- a/firmware/synth.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef SYNTH_H -#define SYNTH_H - -#define SYNTH_BUFSIZE (16) -#define SYNTH_BUFMASK (0b00001111) - -enum { WAVE_OFF, WAVE_PULSE, WAVE_SAW, WAVE_NOISE }; - -typedef struct { - uint8_t note; - uint8_t inst_nr; - uint8_t pos; - - uint16_t phase; - uint16_t pulse_width; - - 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; - -} synth_instrument_t; - - -void synth_init(void); -void synth_poll(void); - -#endif diff --git a/firmware/usart.c b/firmware/usart.c deleted file mode 100644 index 0f738f5..0000000 --- a/firmware/usart.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * PentaFnord Firmware - * - * by Alexander Lorz - * - * - * The USART control code is derived by code from the 4CHLED project - * by sebseb7: https://github.com/sebseb7/eagle/tree/master/4CHLED/firmware - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include -#include - -//#include "main.h" -#include "usart.h" - -#define UART_RXBUFSIZE 32 - -volatile static uint8_t rxbuf0[UART_RXBUFSIZE]; -volatile static uint8_t *volatile rxhead0, *volatile rxtail0; -//volatile uint8_t xon = 0; - - -ISR (USART_RX_vect) -{ - UCSR0B &= ~(1 << RXCIE0); - asm volatile("sei"); - - int diff; - uint8_t c; - c=UDR0; - diff = rxhead0 - rxtail0; - if (diff < 0) diff += UART_RXBUFSIZE; - if (diff < UART_RXBUFSIZE -1) - { - *rxhead0 = c; - ++rxhead0; - if (rxhead0 == (rxbuf0 + UART_RXBUFSIZE)) rxhead0 = rxbuf0; -// if((diff > 100)&&(xon==0)) -// { -// xon=1; -// //set the CTS pin -// } - } - UCSR0B |= (1 << RXCIE0); -} - - -void USART0_Init (void) -{ - // set baudrate - #undef BAUD - #define BAUD 115200 - #include - 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; - - // set 8N1 - UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); - UCSR0B &= ~(1 << UCSZ02); - - UCSR0B |= (1 << RXEN0)|(1 << TXEN0); //enable send and receive - - UCSR0B |= (1 << RXCIE0); //enable receive interrup - - rxhead0 = rxtail0 = rxbuf0; - -} - - - -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; - *c = *rxtail0; - if (++rxtail0 == (rxbuf0 + UART_RXBUFSIZE)) rxtail0 = rxbuf0; - -// uint8_t diff = rxhead0 - rxtail0; -// if((diff < 10)&&(xon==1)) -// { -// xon=0; -// //set the CTS pin -// } - - return 1; -} - -void USART0_crlf(){ - 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; - USART0_putc(highchar); - USART0_putc(lowchar); - -} -void USART0_put_uint16(uint16_t x){ - USART0_put_uint8 ((x & 0xFF00)>>8); - USART0_put_uint8 (x & 0x00FF); - -} diff --git a/firmware/usart.h b/firmware/usart.h deleted file mode 100644 index d0ddebc..0000000 --- a/firmware/usart.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * PentaFnord Firmware - * - * by Alexander Lorz - * - * - * The USART control code is derived by code from the 4CHLED project - * by sebseb7: https://github.com/sebseb7/eagle/tree/master/4CHLED/firmware - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef _USART_H -#define _USART_H - -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 USART0_put_uint16(uint16_t); - -#endif -