moved synth.c and usart.c to lib dir
This commit is contained in:
parent
cbcd30609d
commit
71d27f92af
|
@ -35,7 +35,7 @@ OPT = s
|
||||||
|
|
||||||
##########################################################################################################
|
##########################################################################################################
|
||||||
# List C source files here. (C dependencies are automatically generated.)
|
# 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
|
||||||
##########################################################################################################
|
##########################################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "synth.h"
|
#include "lib/synth.h"
|
||||||
#include "usart.h"
|
#include "lib/usart.h"
|
||||||
|
|
||||||
|
|
||||||
uint16_t sw_v = 0;
|
uint16_t sw_v = 0;
|
||||||
|
|
324
firmware/synth.c
324
firmware/synth.c
|
@ -1,324 +0,0 @@
|
||||||
#include <inttypes.h>
|
|
||||||
#include "synth.h"
|
|
||||||
#include "freq_table.h"
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
136
firmware/usart.c
136
firmware/usart.c
|
@ -1,136 +0,0 @@
|
||||||
/*
|
|
||||||
* PentaFnord Firmware
|
|
||||||
*
|
|
||||||
* by Alexander Lorz <bigalex@gmx.de>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
//#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 <util/setbaud.h><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;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* PentaFnord Firmware
|
|
||||||
*
|
|
||||||
* by Alexander Lorz <bigalex@gmx.de>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user