working code (small crashes in communication still)
This commit is contained in:
parent
b7d4cbaa27
commit
8ea404c3fa
@ -1 +1 @@
|
|||||||
Subproject commit 3141a62e62012dee60192e6ad1c95ee5b63fc8ce
|
Subproject commit 362c65440c49e09e06e89299d51a25003e9724a0
|
@ -12,56 +12,25 @@
|
|||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
// global adc instance
|
// global adc instance
|
||||||
volatile adc_t adc;
|
adc_t adc;
|
||||||
|
|
||||||
static inline void adc_next() {
|
|
||||||
do {
|
|
||||||
adc.current_channel = (adc.current_channel+1)%8;
|
|
||||||
|
|
||||||
if (!adc.current_channel) {
|
|
||||||
adc.current_sample = adc.buffer.ptr-1;
|
|
||||||
}
|
|
||||||
} while(!(adc.channel_mask & (1<<adc.current_channel)));
|
|
||||||
|
|
||||||
if (adc.current_sample < (adc.buffer.ptr + adc.buffer.size)) {
|
|
||||||
adc.current_sample++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set mux input
|
|
||||||
ADMUX = adc.current_channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* adc driver */
|
/* adc driver */
|
||||||
void adc_init(adc_buffer_t buffer, uint8_t mask) {
|
void adc_init(uint8_t * channels) {
|
||||||
if (!mask) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
adc.buffer = buffer;
|
|
||||||
adc.current_sample = adc.buffer.ptr;
|
|
||||||
adc.channel_mask = mask;
|
|
||||||
adc.current_channel = 0;
|
adc.current_channel = 0;
|
||||||
|
adc.channel_map = channels;
|
||||||
|
|
||||||
// find first channel
|
ADMUX = channels[0];
|
||||||
while(!((1<<adc.current_channel) & mask)) {
|
ADCSRA = (1<<ADATE) | (1<<ADEN) | 7; // enable adc, maximum prescaler value
|
||||||
adc.current_channel++;
|
}
|
||||||
|
|
||||||
|
ISR(ADC_vect) {
|
||||||
|
adc.buffer[adc.current_channel] = ADC;
|
||||||
|
adc.current_channel++;
|
||||||
|
|
||||||
|
if (adc.current_channel == ADC_BUFFER_SIZE) {
|
||||||
|
adc.current_channel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADMUX = 0;
|
ADMUX = adc.channel_map[adc.current_channel];
|
||||||
ADCSRA = (1<<ADATE) | (1<<ADEN) | 5 ; // enable adc, maximum prescaler value
|
|
||||||
}
|
|
||||||
|
|
||||||
void adc_start() {
|
|
||||||
ADCSRA |= (1<<ADIE) | (1<<ADSC); // enable adc interrupt
|
|
||||||
}
|
|
||||||
|
|
||||||
void adc_stop( ){
|
|
||||||
ADCSRA &= ~(1<<ADIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "led.h"
|
|
||||||
ISR(ADC_vect) {
|
|
||||||
**adc.current_sample = ADC;
|
|
||||||
adc_next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,38 +12,25 @@
|
|||||||
|
|
||||||
typedef uint16_t adc_sample_t;
|
typedef uint16_t adc_sample_t;
|
||||||
|
|
||||||
|
#define ADC_BUFFER_SIZE 5
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
adc_sample_t ** ptr;
|
|
||||||
uint8_t size;
|
|
||||||
} adc_buffer_t;
|
} adc_buffer_t;
|
||||||
|
|
||||||
typedef struct adc {
|
typedef struct adc {
|
||||||
adc_buffer_t buffer;
|
adc_sample_t buffer[ADC_BUFFER_SIZE];
|
||||||
|
|
||||||
uint8_t current_channel;
|
volatile uint8_t current_channel;
|
||||||
adc_sample_t ** current_sample;
|
uint8_t * channel_map;
|
||||||
uint8_t channel_mask;
|
|
||||||
} adc_t;
|
} adc_t;
|
||||||
|
|
||||||
// the adc instance
|
// the adc instance
|
||||||
extern volatile adc_t adc;
|
extern adc_t adc;
|
||||||
|
|
||||||
enum {
|
void adc_init(uint8_t * channels);
|
||||||
ADC_CHANNEL_0 = 0x01,
|
|
||||||
ADC_CHANNEL_1 = 0x02,
|
|
||||||
ADC_CHANNEL_2 = 0x04,
|
|
||||||
ADC_CHANNEL_3 = 0x08,
|
|
||||||
ADC_CHANNEL_4 = 0x10,
|
|
||||||
ADC_CHANNEL_5 = 0x20,
|
|
||||||
ADC_CHANNEL_6 = 0x40,
|
|
||||||
ADC_CHANNEL_7 = 0x80,
|
|
||||||
ADC_CHANNEL_ALL = 0xFF,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#define adc_start() ADCSRA |= (1<<ADIE) | (1<<ADSC)
|
||||||
void adc_init(adc_buffer_t buffer, uint8_t channel_mask);
|
#define adc_stop() ADCSRA &= ~(1<<ADIE)
|
||||||
|
|
||||||
void adc_start();
|
|
||||||
void adc_stop();
|
|
||||||
|
|
||||||
#endif /* ADC_H_ */
|
#endif /* ADC_H_ */
|
||||||
|
@ -15,17 +15,17 @@
|
|||||||
#define LED_REG PORTB
|
#define LED_REG PORTB
|
||||||
#define LED_PIN 0
|
#define LED_PIN 0
|
||||||
|
|
||||||
static inline void led_toggle() {
|
#define led_toggle() do { \
|
||||||
LED_REG ^= (1<<LED_PIN);
|
LED_REG ^= (1<<LED_PIN); \
|
||||||
}
|
} while(0)
|
||||||
|
|
||||||
static inline void led_off() {
|
#define led_off() do { \
|
||||||
LED_REG |= (1<<LED_PIN);
|
LED_REG |= (1<<LED_PIN); \
|
||||||
}
|
} while(0)
|
||||||
|
|
||||||
static inline void led_on() {
|
#define led_on() do { \
|
||||||
LED_REG &= ~(1<<LED_PIN);
|
LED_REG &= ~(1<<LED_PIN); \
|
||||||
}
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
void led_init();
|
void led_init();
|
||||||
|
@ -12,106 +12,19 @@
|
|||||||
|
|
||||||
#include <interface.h>
|
#include <interface.h>
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
byte_t * buffer_start, * buffer_end;
|
|
||||||
|
|
||||||
volatile byte_t * read;
|
|
||||||
volatile byte_t * write;
|
|
||||||
volatile byte_t count;
|
|
||||||
|
|
||||||
iface_t iface;
|
|
||||||
} comm_t;
|
|
||||||
|
|
||||||
comm_t comm;
|
|
||||||
|
|
||||||
void comm_write(iface_t * iface, byte_t byte) {
|
|
||||||
if ((comm.write == comm.read) && comm.count) {
|
|
||||||
// write overflow
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*comm.write = byte;
|
|
||||||
++comm.count;
|
|
||||||
|
|
||||||
// advance write pointer
|
|
||||||
if ((++comm.write) >= comm.buffer_end) {
|
|
||||||
comm.write = comm.buffer_start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline byte_t comm_read() {
|
|
||||||
if (!comm.count)
|
|
||||||
return 0x00;
|
|
||||||
|
|
||||||
byte_t result = *comm.read;
|
|
||||||
|
|
||||||
--comm.count;
|
|
||||||
if ((++comm.read) >= comm.buffer_end) {
|
|
||||||
comm.read = comm.buffer_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_t comm_buffer[10];
|
|
||||||
|
|
||||||
void comm_init()
|
|
||||||
{
|
|
||||||
comm.buffer_start = comm_buffer;
|
|
||||||
comm.buffer_end = comm_buffer + sizeof(comm_buffer);
|
|
||||||
|
|
||||||
// reset buffer
|
|
||||||
comm.write = comm.buffer_start;
|
|
||||||
comm.read = comm.buffer_start;
|
|
||||||
comm.count = 0;
|
|
||||||
|
|
||||||
// TODO: setup pins
|
|
||||||
DDRA |= (1<<PA5); // setup MOSI as output
|
|
||||||
|
|
||||||
// TODO: setup USART in synchronous mode
|
|
||||||
USICR = (1<<USIWM0)|(1<<USICS1);
|
|
||||||
|
|
||||||
// init interface
|
|
||||||
comm.iface.write = comm_write;
|
|
||||||
comm.iface.on_read = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
// write buffer out if there is data to be written
|
|
||||||
//if (!comm.count) {
|
|
||||||
// call interrupt handler
|
|
||||||
//comm.iface.on_read(&comm.iface, USIDR, comm.iface.callback_data);
|
|
||||||
//}
|
|
||||||
|
|
||||||
USIDR = 0x02;
|
|
||||||
sei();
|
|
||||||
//USIDR = comm_read();
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
void comm_init();
|
||||||
|
|
||||||
// the public instance of the app buffer
|
// the public instance of the app buffer
|
||||||
struct app app = {};
|
struct app app = {};
|
||||||
|
|
||||||
adc_sample_t * channel_map[] = {
|
uint8_t channel_map[ADC_BUFFER_SIZE] = {
|
||||||
// update app state (remap channels)
|
0,
|
||||||
&app.state.state.poti[2],
|
1,
|
||||||
&app.state.state.poti[3],
|
2,
|
||||||
&app.state.state.poti[1],
|
3,
|
||||||
&app.state.state.poti[0],
|
7
|
||||||
&app.state.state.slider
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// initalizes the application modules
|
// initalizes the application modules
|
||||||
@ -124,25 +37,80 @@ void init()
|
|||||||
// init adc module
|
// init adc module
|
||||||
// will sample 0x8F (CHANNEL 8 and 0-3)
|
// will sample 0x8F (CHANNEL 8 and 0-3)
|
||||||
// this module also updates app.buffer.poti and slider for us
|
// this module also updates app.buffer.poti and slider for us
|
||||||
adc_init((adc_buffer_t){
|
adc_init(channel_map);
|
||||||
.ptr = channel_map,
|
|
||||||
.size = sizeof(channel_map),
|
|
||||||
}, 0x8F);
|
|
||||||
|
|
||||||
// init communication module
|
// init communication module
|
||||||
comm_init();
|
comm_init();
|
||||||
|
|
||||||
// bind state encoder to communication module
|
|
||||||
slave_init(&app.state, &comm.iface);
|
|
||||||
|
|
||||||
// start all modules
|
// start all modules
|
||||||
adc_start();
|
adc_start();
|
||||||
comm_start();
|
|
||||||
|
|
||||||
// activate interrupts (effectivly starting the application)
|
// activate interrupts (effectivly starting the application)
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void comm_init()
|
||||||
|
{
|
||||||
|
DDRA |= (1<<PA5); // setup MOSI as output
|
||||||
|
USICR = (1<<USIWM0)|(1<<USICS1);
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile enum {
|
||||||
|
COMM_WAIT = 0,
|
||||||
|
COMM_SEND_START ,
|
||||||
|
COMM_SEND_WAIT ,
|
||||||
|
COMM_SEND_END ,
|
||||||
|
} comm_state;
|
||||||
|
|
||||||
|
static inline void comm_service()
|
||||||
|
{
|
||||||
|
static uint8_t count = 0;
|
||||||
|
static uint16_t temp = 0xFF;
|
||||||
|
|
||||||
|
if (USISR & (1<<USIOIF))
|
||||||
|
{
|
||||||
|
led_on();
|
||||||
|
cli();
|
||||||
|
|
||||||
|
switch(comm_state)
|
||||||
|
{
|
||||||
|
case COMM_WAIT:
|
||||||
|
if (IS_EOM(USIDR)) {
|
||||||
|
// pass package through
|
||||||
|
USIDR &= ~0x80;
|
||||||
|
comm_state = COMM_SEND_START;
|
||||||
|
adc_stop();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMM_SEND_START:
|
||||||
|
temp = adc.buffer[count];
|
||||||
|
USIDR = temp & 0x7F;
|
||||||
|
comm_state = COMM_SEND_WAIT;
|
||||||
|
break;
|
||||||
|
case COMM_SEND_WAIT:
|
||||||
|
USIDR = (temp>>7)&0x7F;
|
||||||
|
|
||||||
|
if (++count == ADC_BUFFER_SIZE) {
|
||||||
|
comm_state = COMM_SEND_END;
|
||||||
|
} else {
|
||||||
|
comm_state = COMM_SEND_START;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMM_SEND_END:
|
||||||
|
count = 0;
|
||||||
|
USIDR = app.state.state.button | 0x80;
|
||||||
|
default:
|
||||||
|
comm_state = COMM_WAIT;
|
||||||
|
adc_start();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
USISR |= (1<<USIOIF);
|
||||||
|
|
||||||
|
sei();
|
||||||
|
led_off();
|
||||||
|
}
|
||||||
|
}
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
// little debug helper function
|
// little debug helper function
|
||||||
@ -160,6 +128,8 @@ int main()
|
|||||||
init();
|
init();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
// nothing to do here, the application is interrupt-driven
|
// service serial interface
|
||||||
|
// slightly more stable then interrupt
|
||||||
|
comm_service();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user