mixer-slider/firmware/slider/main.c

120 lines
2.1 KiB
C

#include <avr/io.h>
#include <avr/interrupt.h>
#include "adc.h"
#include "led.h"
#include "button.h"
#include "main.h"
/* Communication driver */
#define SLAVE_ENABLE_DDR DDRA
#define SLAVE_ENABLE_REG PINA
#define SLAVE_ENABLE_PIN 1
#include <interface.h>
typedef struct {
iface_t iface;
} comm_t;
comm_t comm;
void comm_write(iface_t * iface, byte_t byte) {
// disable interrupt (temporarily)
uint8_t temp = USICR;
USICR &= ~(1<<USIOIE);
// write data register
USIDR = byte;
// wait for buffer overflow
while(!(USICR&(1<<USIOIE))) {}
// restore control register
USICR = temp;
}
void comm_init() {
// TODO: setup pins
// TODO: setup USART in synchronous mode
USICR = (1<<USIWM0)|(1<<USICS1);
// init interface
comm.iface.write = comm_write;
}
void comm_start() {
// don't start without interrupt handler
if (!comm.iface.on_read)
return;
// TODO: activate USART
USICR |= (1<<USIOIE);
}
ISR(USI_OVF_vect) {
// call interrupt handler
comm.iface.on_read(&comm.iface, USIBR, comm.iface.callback_data);
}
void on_read(iface_t * sender, byte_t b) {
if (!IS_EOM(b)) {
sender->write(sender, b);
return;
}
// strip EOM message
sender->write(sender, b&0x7F);
}
#include "main.h"
// the public instance of the app buffer
struct app app = {};
// initalizes the application modules
void init() {
// init button module (making the button light up on press)
// module also updates app.buffer.button for us
button_init();
// init adc module
// will sample 0x8F (CHANNEL 8 and 0-3)
// this module also updates app.buffer.poti and slider for us
adc_init((adc_buffer_t){
.ptr = app.adc_buffer,
.size = 5,
}, 0x8F);
// init communication module
comm_init();
// bind state encoder to communication module
slave_init(&app.state, &comm.iface);
// start all modules
adc_start();
comm_start();
// activate interrupts (effectivly starting the application)
sei();
}
// little debug helper function
// FIXME: remove when not needed
void delay(uint16_t d) {
while(d--) {
__asm("nop");
}
}
int main() {
init();
// start relevant periphials
adc_start();
while(1) {
// nothing to do here, the application is interrupt-driven
}
}