Adapted poweriface firmware to use new specs
This commit is contained in:
parent
42726c06c2
commit
0dc044e43f
1 changed files with 91 additions and 162 deletions
|
@ -4,65 +4,40 @@
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#include <can.h>
|
#include <can.h>
|
||||||
|
|
||||||
#if ENABLE_SLEEP
|
static void init() {
|
||||||
#include <avr/sleep.h>
|
// Enable GPIO: PB2, PB3, PB4 output, low; PB5 input, pull-up on
|
||||||
#endif
|
PORTB = (PORTB & ~(_BV(PB2) | _BV(PB3) | _BV(PB4))) | _BV(PB5);
|
||||||
#if ENABLE_WATCHDOG
|
DDRB = (DDRB & ~_BV(PB5)) | (_BV(PB2) | _BV(PB3) | _BV(PB4));
|
||||||
#include <avr/watchdog.h>
|
|
||||||
#endif
|
// Initialize CAN interface
|
||||||
|
can_init(BITRATE_125_KBPS);
|
||||||
|
// Regular receive/transmit mode
|
||||||
|
can_set_mode(NORMAL_MODE);
|
||||||
|
|
||||||
// Global state
|
// Filter for status requests and dispense commands
|
||||||
struct {
|
can_filter_t filter = {
|
||||||
#if ENABLE_SHUTDOWN
|
.id = 0x11,
|
||||||
// Main loop run state (1 = running, 0 = shutdown)
|
.mask = 0x7ff,
|
||||||
uint8_t run;
|
.flags = {
|
||||||
#endif
|
.rtr = 1,
|
||||||
// Message ready?
|
.extended = 0,
|
||||||
uint8_t ready;
|
},
|
||||||
// Receive buffer
|
};
|
||||||
uint8_t buffer[8];
|
can_set_filter(0, &filter);
|
||||||
// Message address
|
can_filter_t disp = {
|
||||||
uint32_t address;
|
.id = 0x21,
|
||||||
} state; //__attribute__ ((section (".noinit")));
|
.mask = 0x7ff,
|
||||||
|
.flags = {
|
||||||
|
.rtr = 0,
|
||||||
|
.extended = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
can_set_filter(1, &disp);
|
||||||
|
|
||||||
inline void init(); // __attribute__((always_inline));
|
// Enable interrupts to start reception
|
||||||
inline void shutdown(); // __attribute__((always_inline));
|
sei();
|
||||||
|
|
||||||
inline void init() {
|
|
||||||
// Disable interrupts before init
|
|
||||||
cli();
|
|
||||||
|
|
||||||
// Set state
|
|
||||||
//state.run = 0;
|
|
||||||
|
|
||||||
#if ENABLE_WATCHDOG
|
|
||||||
// Enable watchdog timer
|
|
||||||
wdt_enable(WDTO_500MS);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set clock divider to 1 after startup
|
|
||||||
// This is an alternative to clearing the CLKDIV8 fuse
|
|
||||||
// CLKPR = _BV(CLKPCE);
|
|
||||||
// CLKPR = 0x00;
|
|
||||||
|
|
||||||
// Enable GPIO and set low
|
|
||||||
// PORTB |= _BV(PB5);
|
|
||||||
PORTB &= ~(_BV(PB2) | _BV(PB3) | _BV(PB4));
|
|
||||||
DDRB |= (_BV(PB2) | _BV(PB3) | _BV(PB4));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void shutdown() {
|
|
||||||
// Disable interrupts
|
|
||||||
// Not needed when not using sleep, the compiler will generate a cli+busy loop
|
|
||||||
#if ENABLE_SLEEP
|
|
||||||
cli();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_WATCHDOG
|
|
||||||
// Disable watchdog
|
|
||||||
wdt_disable();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// UART bit-uart_bang 8 bits on the debug port, LSB first, 1 stop bit, no parity, 9600 baud
|
// UART bit-uart_bang 8 bits on the debug port, LSB first, 1 stop bit, no parity, 9600 baud
|
||||||
void uart_bang(uint8_t data) {
|
void uart_bang(uint8_t data) {
|
||||||
|
@ -83,7 +58,7 @@ void uart_bang(uint8_t data) {
|
||||||
_delay_us(102);
|
_delay_us(102);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bit-bang pattern (LSB first) out the data line and strobe
|
// Bit-bang pattern (LSB first) out the data line
|
||||||
uint16_t bang(uint16_t data) {
|
uint16_t bang(uint16_t data) {
|
||||||
uint16_t in = 0;
|
uint16_t in = 0;
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
|
@ -93,9 +68,10 @@ uint16_t bang(uint16_t data) {
|
||||||
} else {
|
} else {
|
||||||
PORTB &= ~_BV(PB4);
|
PORTB &= ~_BV(PB4);
|
||||||
}
|
}
|
||||||
// Clock
|
// Clock up
|
||||||
PORTB |= _BV(PB2);
|
PORTB |= _BV(PB2);
|
||||||
_delay_us(4);
|
_delay_us(4);
|
||||||
|
// Clock down
|
||||||
PORTB &= ~_BV(PB2);
|
PORTB &= ~_BV(PB2);
|
||||||
_delay_us(4);
|
_delay_us(4);
|
||||||
// Read
|
// Read
|
||||||
|
@ -106,114 +82,67 @@ uint16_t bang(uint16_t data) {
|
||||||
data >>= 1;
|
data >>= 1;
|
||||||
in <<= 1;
|
in <<= 1;
|
||||||
}
|
}
|
||||||
// Strobe
|
// Clear data
|
||||||
PORTB |= _BV(PB3);
|
|
||||||
_delay_us(4);
|
|
||||||
PORTB &= ~_BV(PB3);
|
|
||||||
// Clear
|
|
||||||
PORTB &= ~_BV(PB4);
|
PORTB &= ~_BV(PB4);
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
// Strobe output
|
||||||
// Initialize hardware
|
void strobe() {
|
||||||
init();
|
// Strobe
|
||||||
// Initialize CAN interface
|
PORTB |= _BV(PB3);
|
||||||
can_init(BITRATE_125_KBPS);
|
_delay_us(4);
|
||||||
// Set up command filter
|
PORTB &= ~_BV(PB3);
|
||||||
can_set_mode(NORMAL_MODE);
|
|
||||||
can_filter_t filter = {
|
|
||||||
.id = 0x100,
|
|
||||||
.mask = 0x1ff,
|
|
||||||
.flags = {
|
|
||||||
.rtr = 0,
|
|
||||||
.extended = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
can_set_filter(0, &filter);
|
|
||||||
// wait before start
|
|
||||||
//_delay_ms(10000);
|
|
||||||
|
|
||||||
// Enable interrupts to start reception
|
|
||||||
sei();
|
|
||||||
|
|
||||||
// Main loop
|
|
||||||
#if ENABLE_SHUTDOWN
|
|
||||||
state.run = 1;
|
|
||||||
while (state.run) {
|
|
||||||
#else
|
|
||||||
while (1) {
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
// Test pattern
|
|
||||||
for (uint8_t i = 0; i < 5; i++) {
|
|
||||||
bang(0x0080 >> i);
|
|
||||||
_delay_ms(1000);
|
|
||||||
bang(0x0000);
|
|
||||||
_delay_ms(1000);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Check for new messages
|
|
||||||
if (can_check_message()) {
|
|
||||||
can_t msg = { 0 };
|
|
||||||
uint8_t status = can_get_message(&msg);
|
|
||||||
// uart_bang(status);
|
|
||||||
uint16_t in = 0;
|
|
||||||
if (status != 0 && msg.id == 0x100 && msg.length == 1) {
|
|
||||||
// uart_bang(msg.id & 0xff);
|
|
||||||
// uart_bang((msg.id >> 8) & 0xff);
|
|
||||||
// uart_bang((msg.id >> 16) & 0xff);
|
|
||||||
// uart_bang((msg.id >> 24) & 0xff);
|
|
||||||
// uart_bang(msg.flags.rtr);
|
|
||||||
// uart_bang(msg.flags.extended);
|
|
||||||
// uart_bang(msg.length);
|
|
||||||
// for (uint8_t i = 0; i < msg.length; i++) {
|
|
||||||
// uart_bang(msg.data[i]);
|
|
||||||
// }
|
|
||||||
//uint16_t out = msg.data[0] | ((uint16_t) msg.data[1] << 8);
|
|
||||||
if (msg.data[0] < 5) {
|
|
||||||
uint16_t out = 0x0080 >> msg.data[0];
|
|
||||||
bang(out);
|
|
||||||
_delay_ms(3000);
|
|
||||||
in = bang(0x0000);
|
|
||||||
}
|
|
||||||
//in = bang(0xffff);
|
|
||||||
}
|
|
||||||
if (can_check_free_buffer()) {
|
|
||||||
can_t msg = {
|
|
||||||
.id = 0x11,
|
|
||||||
.flags = {
|
|
||||||
.rtr = 0,
|
|
||||||
.extended = 0,
|
|
||||||
},
|
|
||||||
.length = 5,
|
|
||||||
.data = { 0xc0, 0xff, 0xee, in & 0xff, (in >> 8) & 0xff, },
|
|
||||||
};
|
|
||||||
uint8_t status = can_send_message(&msg);
|
|
||||||
// uart_bang(status);
|
|
||||||
} else {
|
|
||||||
// uart_bang(0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_SLEEP
|
|
||||||
// Let the MCU take a nap
|
|
||||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
|
||||||
sleep_mode();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable all peripherals and interrupts
|
|
||||||
shutdown();
|
|
||||||
|
|
||||||
// Power the MCU down
|
|
||||||
#if ENABLE_SLEEP
|
|
||||||
while (1) {
|
|
||||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
|
||||||
sleep_mode();
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_status() {
|
||||||
|
// Bit-bang register contents in (also send out zeros, but don't strobe)
|
||||||
|
uint16_t status = bang(0);
|
||||||
|
|
||||||
|
if (can_check_free_buffer()) {
|
||||||
|
can_t msg = {
|
||||||
|
.id = 0x11,
|
||||||
|
.flags = {
|
||||||
|
.rtr = 0,
|
||||||
|
},
|
||||||
|
.length = 2,
|
||||||
|
.data = { (uint8_t) (status >> 8), (uint8_t) status, },
|
||||||
|
};
|
||||||
|
can_send_message(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fire_relay(uint8_t num) {
|
||||||
|
if (num < 5) {
|
||||||
|
uint16_t out = 0x0080 >> num;
|
||||||
|
bang(out);
|
||||||
|
strobe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loop() {
|
||||||
|
// Check for new messages
|
||||||
|
if (can_check_message()) {
|
||||||
|
can_t msg = { 0 };
|
||||||
|
uint8_t status = can_get_message(&msg);
|
||||||
|
if (status != 0) {
|
||||||
|
switch (msg.id) {
|
||||||
|
case 0x11:
|
||||||
|
if (msg.flags.rtr) {
|
||||||
|
send_status();
|
||||||
|
}
|
||||||
|
case 0x21:
|
||||||
|
if (msg.length == 1) {
|
||||||
|
fire_relay(msg.data[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
init();
|
||||||
|
while (1) {
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue