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
 | 
				
			||||||
@ -158,8 +126,10 @@ void delay(uint16_t d)
 | 
				
			|||||||
int main() 
 | 
					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