peliminary communication support
This commit is contained in:
parent
635e55e6b0
commit
f84a135ace
@ -7,5 +7,5 @@ project(slider_firmware C)
|
|||||||
|
|
||||||
add_subdirectory(SliderCommunication)
|
add_subdirectory(SliderCommunication)
|
||||||
|
|
||||||
add_avr_executable(slider_firmware led.c main.c adc.c )
|
add_avr_executable(slider_firmware led.c main.c adc.c button.c)
|
||||||
target_link_libraries(slider_firmware DSPLAB_SliderCommunication)
|
target_link_libraries(slider_firmware DSPLAB_SliderCommunication)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 36d759d94c6fa9166de35624989858811a73861f
|
Subproject commit 3141a62e62012dee60192e6ad1c95ee5b63fc8ce
|
@ -6,11 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
#include "led.h"
|
|
||||||
|
|
||||||
// global adc instance
|
// global adc instance
|
||||||
volatile adc_t adc;
|
volatile adc_t adc;
|
||||||
|
|
||||||
@ -21,8 +21,12 @@ static inline void adc_next() {
|
|||||||
if (!adc.current_channel) {
|
if (!adc.current_channel) {
|
||||||
adc.current_sample = adc.buffer.ptr-1;
|
adc.current_sample = adc.buffer.ptr-1;
|
||||||
|
|
||||||
if (adc.interrupt)
|
// update app state (remap channels)
|
||||||
adc.interrupt(&adc.buffer);
|
app.state.state.slider = adc.buffer.ptr[4];
|
||||||
|
app.state.state.poti[0] = adc.buffer.ptr[3];
|
||||||
|
app.state.state.poti[1] = adc.buffer.ptr[2];
|
||||||
|
app.state.state.poti[2] = adc.buffer.ptr[0];
|
||||||
|
app.state.state.poti[3] = adc.buffer.ptr[1];
|
||||||
}
|
}
|
||||||
} while(!(adc.channel_mask & (1<<adc.current_channel)));
|
} while(!(adc.channel_mask & (1<<adc.current_channel)));
|
||||||
|
|
||||||
@ -34,10 +38,6 @@ static inline void adc_next() {
|
|||||||
ADMUX = adc.current_channel;
|
ADMUX = adc.current_channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_on_done(adc_interrupt_t interrupt) {
|
|
||||||
adc.interrupt = interrupt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* adc driver */
|
/* adc driver */
|
||||||
void adc_init(adc_buffer_t buffer, uint8_t mask) {
|
void adc_init(adc_buffer_t buffer, uint8_t mask) {
|
||||||
if (!mask) {
|
if (!mask) {
|
||||||
@ -54,8 +54,6 @@ void adc_init(adc_buffer_t buffer, uint8_t mask) {
|
|||||||
adc.current_channel++;
|
adc.current_channel++;
|
||||||
}
|
}
|
||||||
|
|
||||||
adc.interrupt = 0;
|
|
||||||
|
|
||||||
ADMUX = 0;
|
ADMUX = 0;
|
||||||
ADCSRA = (1<<ADATE) | (1<<ADEN) ; // enable adc, maximum prescaler value
|
ADCSRA = (1<<ADATE) | (1<<ADEN) ; // enable adc, maximum prescaler value
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,12 @@ typedef struct {
|
|||||||
uint8_t size;
|
uint8_t size;
|
||||||
} adc_buffer_t;
|
} adc_buffer_t;
|
||||||
|
|
||||||
typedef void (*adc_interrupt_t)(volatile adc_buffer_t * buf);
|
|
||||||
|
|
||||||
typedef struct adc {
|
typedef struct adc {
|
||||||
adc_buffer_t buffer;
|
adc_buffer_t buffer;
|
||||||
|
|
||||||
uint8_t current_channel;
|
uint8_t current_channel;
|
||||||
adc_sample_t * current_sample;
|
adc_sample_t * current_sample;
|
||||||
uint8_t channel_mask;
|
uint8_t channel_mask;
|
||||||
|
|
||||||
adc_interrupt_t interrupt;
|
|
||||||
} adc_t;
|
} adc_t;
|
||||||
|
|
||||||
// the adc instance
|
// the adc instance
|
||||||
@ -47,8 +43,6 @@ enum {
|
|||||||
|
|
||||||
void adc_init(adc_buffer_t buffer, uint8_t channel_mask);
|
void adc_init(adc_buffer_t buffer, uint8_t channel_mask);
|
||||||
|
|
||||||
void adc_on_done(adc_interrupt_t interrupt);
|
|
||||||
|
|
||||||
void adc_start();
|
void adc_start();
|
||||||
void adc_stop();
|
void adc_stop();
|
||||||
|
|
||||||
|
31
firmware/slider/button.c
Normal file
31
firmware/slider/button.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "button.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
void button_init()
|
||||||
|
{
|
||||||
|
led_init();
|
||||||
|
|
||||||
|
// enable pullup on button pin
|
||||||
|
BUTTON_DDR &= ~(1<<BUTTON_PIN);
|
||||||
|
BUTTON_PORT |= (1<<BUTTON_PIN);
|
||||||
|
|
||||||
|
// activate pin change interrupt
|
||||||
|
// PCINT9
|
||||||
|
PCMSK1 |= (1<<PCINT9);
|
||||||
|
GIMSK |= (1<<PCIE1); // enable PCINT1
|
||||||
|
}
|
||||||
|
|
||||||
|
button_state_t button_is_pressed()
|
||||||
|
{
|
||||||
|
return (BUTTON_REG&(1<<BUTTON_PIN)) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PCINT1_vect) {
|
||||||
|
if(!(BUTTON_REG&(1<<BUTTON_PIN))) {
|
||||||
|
app.state.state.button = !app.state.state.button;
|
||||||
|
led_toggle();
|
||||||
|
}
|
||||||
|
}
|
22
firmware/slider/button.h
Normal file
22
firmware/slider/button.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
#ifndef BUTTON_H_
|
||||||
|
#define BUTTON_H_
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
/* button driver */
|
||||||
|
#define BUTTON_DDR DDRB
|
||||||
|
#define BUTTON_PORT PORTB
|
||||||
|
#define BUTTON_REG PINB
|
||||||
|
#define BUTTON_PIN 1
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BUTTON_RELEASED = 0,
|
||||||
|
BUTTON_PRESSED = 1
|
||||||
|
} button_state_t;
|
||||||
|
|
||||||
|
void button_init();
|
||||||
|
button_state_t button_is_pressed();
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BUTTON_H_
|
@ -2,36 +2,8 @@
|
|||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
|
#include "button.h"
|
||||||
|
#include "main.h"
|
||||||
/* button driver */
|
|
||||||
// TODO: make interrupt driven
|
|
||||||
#define BUTTON_DDR DDRB
|
|
||||||
#define BUTTON_PORT PORTB
|
|
||||||
#define BUTTON_REG PINB
|
|
||||||
#define BUTTON_PIN 1
|
|
||||||
|
|
||||||
enum {
|
|
||||||
BUTTON_RELEASED,
|
|
||||||
BUTTON_PRESSED
|
|
||||||
} button_state;
|
|
||||||
|
|
||||||
void button_init() {
|
|
||||||
led_init();
|
|
||||||
|
|
||||||
BUTTON_DDR &= ~(1<<BUTTON_PIN);
|
|
||||||
BUTTON_PORT |= (1<<BUTTON_PIN);
|
|
||||||
// activate pin change interrupt
|
|
||||||
// PCINT9
|
|
||||||
PCMSK1 |= (1<<PCINT9);
|
|
||||||
GIMSK |= (1<<PCIE1); // enable PCINT1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int button_is_pressed() {
|
|
||||||
return BUTTON_REG&(1<<BUTTON_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Communication driver */
|
/* Communication driver */
|
||||||
#define SLAVE_ENABLE_DDR DDRA
|
#define SLAVE_ENABLE_DDR DDRA
|
||||||
@ -40,8 +12,13 @@ int button_is_pressed() {
|
|||||||
|
|
||||||
#include <interface.h>
|
#include <interface.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
iface_t iface;
|
||||||
|
} comm_t;
|
||||||
|
|
||||||
|
comm_t comm;
|
||||||
void comm_write(iface_t * iface, byte_t byte) {
|
void comm_write(iface_t * iface, byte_t byte) {
|
||||||
// disable interrupt
|
// disable interrupt (temporarily)
|
||||||
uint8_t temp = USICR;
|
uint8_t temp = USICR;
|
||||||
USICR &= ~(1<<USIOIE);
|
USICR &= ~(1<<USIOIE);
|
||||||
|
|
||||||
@ -55,18 +32,18 @@ void comm_write(iface_t * iface, byte_t byte) {
|
|||||||
USICR = temp;
|
USICR = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
iface_t comm_iface;
|
|
||||||
|
|
||||||
void comm_init() {
|
void comm_init() {
|
||||||
// TODO: setup pins
|
// TODO: setup pins
|
||||||
// TODO: setup USART in synchronous mode
|
// TODO: setup USART in synchronous mode
|
||||||
USICR = (1<<USIWM0)|(1<<USICS1);
|
USICR = (1<<USIWM0)|(1<<USICS1);
|
||||||
|
|
||||||
comm_iface.write = comm_write;
|
// init interface
|
||||||
|
comm.iface.write = comm_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
void comm_start() {
|
void comm_start() {
|
||||||
if (!comm_iface.on_read)
|
// don't start without interrupt handler
|
||||||
|
if (!comm.iface.on_read)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: activate USART
|
// TODO: activate USART
|
||||||
@ -74,20 +51,10 @@ void comm_start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ISR(USI_OVF_vect) {
|
ISR(USI_OVF_vect) {
|
||||||
byte_t byte = USIBR;
|
// call interrupt handler
|
||||||
|
comm.iface.on_read(&comm.iface, USIBR, comm.iface.callback_data);
|
||||||
// only operate when enabled
|
|
||||||
if (SLAVE_ENABLE_REG & (1<<SLAVE_ENABLE_PIN)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comm_iface.on_read) {
|
|
||||||
comm_iface.on_read(&comm_iface, byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <communication.h>
|
|
||||||
|
|
||||||
void on_read(iface_t * sender, byte_t b) {
|
void on_read(iface_t * sender, byte_t b) {
|
||||||
if (!IS_EOM(b)) {
|
if (!IS_EOM(b)) {
|
||||||
sender->write(sender, b);
|
sender->write(sender, b);
|
||||||
@ -98,56 +65,55 @@ void on_read(iface_t * sender, byte_t b) {
|
|||||||
sender->write(sender, b&0x7F);
|
sender->write(sender, b&0x7F);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
#include "main.h"
|
||||||
volatile message_t buffer;
|
|
||||||
adc_sample_t adc_buffer[5];
|
|
||||||
} app = {};
|
|
||||||
|
|
||||||
|
// the public instance of the app buffer
|
||||||
|
struct app app = {};
|
||||||
|
|
||||||
ISR(PCINT1_vect) {
|
// initalizes the application modules
|
||||||
if(BUTTON_REG&(1<<BUTTON_PIN)) {
|
|
||||||
app.buffer.button = !app.buffer.button;
|
|
||||||
led_toggle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* main application code */
|
|
||||||
void init() {
|
void init() {
|
||||||
|
// init button module (making the button light up on press)
|
||||||
|
// module also updates app.buffer.button for us
|
||||||
button_init();
|
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){
|
adc_init((adc_buffer_t){
|
||||||
.ptr = app.adc_buffer,
|
.ptr = app.adc_buffer,
|
||||||
.size = 5,
|
.size = 5,
|
||||||
}, 0x8F);
|
}, 0x8F);
|
||||||
|
|
||||||
// activate interrupts
|
// 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();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// little debug helper function
|
||||||
|
// FIXME: remove when not needed
|
||||||
void delay(uint16_t d) {
|
void delay(uint16_t d) {
|
||||||
while(d--) {
|
while(d--) {
|
||||||
__asm("nop");
|
__asm("nop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_int(volatile adc_buffer_t * buf)
|
|
||||||
{
|
|
||||||
app.buffer.slider = buf->ptr[4];
|
|
||||||
|
|
||||||
app.buffer.poti[0] = buf->ptr[3];
|
|
||||||
app.buffer.poti[1] = buf->ptr[2];
|
|
||||||
app.buffer.poti[2] = buf->ptr[0];
|
|
||||||
app.buffer.poti[3] = buf->ptr[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
init();
|
init();
|
||||||
adc_on_done(adc_int);
|
|
||||||
|
|
||||||
// start relevant perephials
|
// start relevant periphials
|
||||||
adc_start();
|
adc_start();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
delay(app.buffer.poti[0]>>4);
|
// nothing to do here, the application is interrupt-driven
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
firmware/slider/main.h
Normal file
16
firmware/slider/main.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
#ifndef APP_H__
|
||||||
|
#define APP_H__
|
||||||
|
|
||||||
|
#include <communication.h>
|
||||||
|
#include "adc.h"
|
||||||
|
#include <slave/slave.h>
|
||||||
|
|
||||||
|
struct app {
|
||||||
|
slave_t state;
|
||||||
|
adc_sample_t adc_buffer[5];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct app app;
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user