|
|
@ -21,44 +21,83 @@ |
|
|
|
#include <avr/io.h> |
|
|
|
#include <avr/interrupt.h> |
|
|
|
#include <avr/wdt.h> |
|
|
|
#include <stdio.h> /* NULL */ |
|
|
|
|
|
|
|
#include "rgb16mpm.h" |
|
|
|
|
|
|
|
/* Dummy Wait: |
|
|
|
* req: <cmd:0x00> <len[2]:0x0000> |
|
|
|
* rsp: <cmd:0x00 <cause:0x00> <len[2]:0x0000> |
|
|
|
*/ |
|
|
|
#define CMD_WAIT 0x00 |
|
|
|
|
|
|
|
/* Switch Run Mode: |
|
|
|
* req: <cmd:0x01> <len[2]:0x0001> <mode> |
|
|
|
* rsp: <cmd:0x01> <cause> <len[2]:0x0000> |
|
|
|
*/ |
|
|
|
#define CMD_SWITCH_MODE 0x01 |
|
|
|
|
|
|
|
/* Get Software Version: |
|
|
|
* req: <cmd:0x02> <len[2]:0x0000> |
|
|
|
* rsp: <cmd:0x02> <cause> <len[2]> <version> |
|
|
|
*/ |
|
|
|
#define CMD_GET_VERSION 0x02 |
|
|
|
#define CMD_GET_CHIPINFO 0x03 /* bootloader / mpmboot */ |
|
|
|
#define CMD_READ_MEMORY 0x11 /* bootloader / mpmboot */ |
|
|
|
#define CMD_WRITE_MEMORY 0x12 /* bootloader / mpmboot */ |
|
|
|
#define CMD_WRITE_COLOR 0x81 |
|
|
|
#define CMD_WRITE_RAW_COLOR 0x82 |
|
|
|
#define CMD_READ_RAW_COLOR 0x83 |
|
|
|
#define CMD_WRITE_CONFIG 0x81 |
|
|
|
|
|
|
|
/* Write RAW color: |
|
|
|
* req: <cmd:0x80> <len[2]> <firstchannel> <RGB[x][3]> |
|
|
|
* rsp: <cmd:0x80> <cause>,<len[2]:0x0000> |
|
|
|
*/ |
|
|
|
#define CMD_WRITE_RAW_COLOR 0x80 |
|
|
|
#define CMD_WRITE_INIT_COLOR 0x82 |
|
|
|
|
|
|
|
/* Read RAW color: |
|
|
|
* req: <cmd:0x80> <len[2]> <firstchannel> <count> |
|
|
|
* rsp: <cmd:0x80> <cause>,<len[2]> <RGB[x][3]> |
|
|
|
*/ |
|
|
|
#define CMD_READ_RAW_COLOR 0x81 |
|
|
|
#define CMD_READ_INIT_COLOR 0x83 |
|
|
|
|
|
|
|
/* response causes */ |
|
|
|
#define CAUSE_SUCCESS 0x00 |
|
|
|
#define CAUSE_NOT_SUPPORTED 0xF0 |
|
|
|
#define CAUSE_INVALID_PARAMETER 0xF1 |
|
|
|
#define CAUSE_UNSPECIFIED_ERROR 0xFF |
|
|
|
|
|
|
|
/* parameter for CMD_SWITCH_MODE */ |
|
|
|
#define BOOTMODE_BOOTLOADER 0x00 |
|
|
|
#define BOOTMODE_APPLICATION 0x80 |
|
|
|
|
|
|
|
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1) |
|
|
|
|
|
|
|
const static uint8_t versioninfo[16] = "rgb16mpm v0.99"; |
|
|
|
static void mpm_reply(uint8_t cmd, uint8_t cause, uint16_t length, uint8_t *data); |
|
|
|
|
|
|
|
const static uint8_t versioninfo[16] = VERSION_STRING; |
|
|
|
|
|
|
|
#define MPM_MAX_DATA_SIZE 64 |
|
|
|
|
|
|
|
static uint8_t mpm_data[MPM_MAX_DATA_SIZE]; |
|
|
|
|
|
|
|
static uint8_t rx_cmd; |
|
|
|
static uint16_t rx_bcnt = 0xFF; |
|
|
|
static uint8_t rx_cmd; |
|
|
|
static uint16_t rx_bcnt; |
|
|
|
static uint16_t rx_length; |
|
|
|
static volatile uint8_t rx_ready; |
|
|
|
|
|
|
|
static uint8_t tx_cmd; |
|
|
|
static uint8_t tx_cause; |
|
|
|
static uint16_t tx_length; |
|
|
|
static uint8_t tx_cmd; |
|
|
|
static uint8_t tx_cause; |
|
|
|
static uint16_t tx_bcnt; |
|
|
|
static uint16_t tx_length; |
|
|
|
static uint8_t *tx_data; |
|
|
|
|
|
|
|
|
|
|
|
ISR(USART_RXC_vect) |
|
|
|
{ |
|
|
|
uint8_t data = UDR; |
|
|
|
sei(); |
|
|
|
|
|
|
|
if (rx_bcnt == 0xFF) { |
|
|
|
/* MPM address stored in TWI address register by bootloader */ |
|
|
|
if (data == TWAR) { |
|
|
|
UCSRA &= ~(1<<MPCM); |
|
|
|
rx_bcnt = 0; |
|
|
|
} |
|
|
|
/* MPM address stored in TWI address register by bootloader */ |
|
|
|
if ((UCSRA & (1<<MPCM)) && (data == TWAR)) { |
|
|
|
UCSRA &= ~(1<<MPCM); |
|
|
|
rx_bcnt = 0; |
|
|
|
|
|
|
|
} else { |
|
|
|
if (rx_bcnt == 0) { |
|
|
@ -67,29 +106,33 @@ ISR(USART_RXC_vect) |
|
|
|
} else if ((rx_bcnt == 1) || (rx_bcnt == 2)) { |
|
|
|
rx_length = (rx_length << 8) | data; |
|
|
|
|
|
|
|
} else if ((rx_bcnt -3) < rx_length) { |
|
|
|
// TODO: get data |
|
|
|
} else if ((rx_bcnt -3) < MPM_MAX_DATA_SIZE) { |
|
|
|
mpm_data[rx_bcnt -3] = data; |
|
|
|
} |
|
|
|
|
|
|
|
/* message complete */ |
|
|
|
if ((rx_bcnt -2) == rx_length) { |
|
|
|
/* enable RS485 TX */ |
|
|
|
PORTD |= (1<<RXTX); |
|
|
|
|
|
|
|
/* first byte */ |
|
|
|
tx_cmd = rx_cmd; |
|
|
|
UDR = rx_cmd; |
|
|
|
|
|
|
|
/* prepare header */ |
|
|
|
tx_bcnt = 1; |
|
|
|
tx_cause = 0; |
|
|
|
tx_length = 0; |
|
|
|
|
|
|
|
if (tx_cmd == CMD_GET_VERSION) { |
|
|
|
tx_length = sizeof(versioninfo); |
|
|
|
switch (rx_cmd) { |
|
|
|
case CMD_WAIT: |
|
|
|
case CMD_SWITCH_MODE: |
|
|
|
mpm_reply(rx_cmd, CAUSE_SUCCESS, 0, NULL); |
|
|
|
break; |
|
|
|
|
|
|
|
case CMD_GET_VERSION: |
|
|
|
mpm_reply(rx_cmd, CAUSE_SUCCESS, sizeof(versioninfo), (uint8_t *)versioninfo); |
|
|
|
break; |
|
|
|
|
|
|
|
case CMD_WRITE_RAW_COLOR: |
|
|
|
case CMD_WRITE_INIT_COLOR: |
|
|
|
case CMD_READ_RAW_COLOR: |
|
|
|
case CMD_READ_INIT_COLOR: |
|
|
|
rx_ready = 1; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
mpm_reply(rx_cmd, CAUSE_NOT_SUPPORTED, 0, NULL); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* enable interrupt */ |
|
|
|
UCSRB |= (1<<UDRIE); |
|
|
|
} |
|
|
|
rx_bcnt++; |
|
|
|
} |
|
|
@ -102,9 +145,8 @@ ISR(USART_UDRE_vect) |
|
|
|
sei(); |
|
|
|
|
|
|
|
if ((tx_bcnt < 4) || (tx_bcnt -4) < tx_length) { |
|
|
|
uint16_t pos = (tx_bcnt -4); |
|
|
|
uint8_t data = 0xFF; |
|
|
|
|
|
|
|
uint8_t data = 0xAA; |
|
|
|
if (tx_bcnt == 1) { |
|
|
|
data = tx_cause; |
|
|
|
|
|
|
@ -114,11 +156,8 @@ ISR(USART_UDRE_vect) |
|
|
|
} else if (tx_bcnt == 3) { |
|
|
|
data = (tx_length & 0xFF); |
|
|
|
|
|
|
|
} else if (tx_cmd == CMD_GET_VERSION) { |
|
|
|
data = versioninfo[pos]; |
|
|
|
|
|
|
|
} else { |
|
|
|
data = 0xAA; |
|
|
|
} else if ((tx_bcnt -4) < tx_length) { |
|
|
|
data = tx_data[tx_bcnt -4]; |
|
|
|
} |
|
|
|
|
|
|
|
UDR = data; |
|
|
@ -136,16 +175,105 @@ ISR(USART_TXC_vect, ISR_NOBLOCK) |
|
|
|
PORTD &= ~(1<<RXTX); |
|
|
|
|
|
|
|
/* enable MP mode again */ |
|
|
|
UCSRA |= (1<<MPCM); |
|
|
|
rx_bcnt = 0xFF; // FIXME: cli? |
|
|
|
UCSRA |= (1<<MPCM); |
|
|
|
|
|
|
|
#if !(STANDALONE) |
|
|
|
if (tx_cmd == CMD_SWITCH_MODE) { // FIXME: check mode |
|
|
|
/* reset MCU -> enter bootloader */ |
|
|
|
if ((tx_cmd == CMD_SWITCH_MODE) && (mpm_data[0] == BOOTMODE_BOOTLOADER)) { |
|
|
|
wdt_enable(WDTO_15MS); |
|
|
|
} |
|
|
|
#endif /* !(STANDALONE) */ |
|
|
|
} |
|
|
|
|
|
|
|
static void mpm_reply(uint8_t cmd, uint8_t cause, uint16_t length, uint8_t *data) |
|
|
|
{ |
|
|
|
/* prepare header */ |
|
|
|
tx_cmd = cmd; |
|
|
|
tx_bcnt = 1; |
|
|
|
tx_cause = cause; |
|
|
|
tx_length = length; |
|
|
|
tx_data = data; |
|
|
|
|
|
|
|
/* enable RS485 TX */ |
|
|
|
PORTD |= (1<<RXTX); |
|
|
|
|
|
|
|
/* first byte and enable interrupt */ |
|
|
|
UDR = tx_cmd; |
|
|
|
UCSRB |= (1<<UDRIE); |
|
|
|
} |
|
|
|
|
|
|
|
void mpm_check_transfer(void) |
|
|
|
{ |
|
|
|
if (rx_ready == 0) |
|
|
|
return; |
|
|
|
|
|
|
|
rx_ready = 0; |
|
|
|
|
|
|
|
switch (rx_cmd) { |
|
|
|
case CMD_WRITE_RAW_COLOR: |
|
|
|
case CMD_WRITE_INIT_COLOR: |
|
|
|
{ |
|
|
|
uint8_t chan = mpm_data[0]; |
|
|
|
uint8_t pos = 1; |
|
|
|
uint8_t cause = CAUSE_SUCCESS; |
|
|
|
|
|
|
|
uint8_t (*baseptr)[3][16] = (rx_cmd == CMD_WRITE_RAW_COLOR) ? &chan_value : &nvram_data.initialRGB; |
|
|
|
|
|
|
|
while ((pos < rx_length)) { |
|
|
|
if ((chan >= 16) || ((pos +2) >= MPM_MAX_DATA_SIZE)) { |
|
|
|
cause = CAUSE_INVALID_PARAMETER; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
baseptr[0][COLOR_RED][chan] = mpm_data[pos++]; |
|
|
|
baseptr[0][COLOR_GREEN][chan] = mpm_data[pos++]; |
|
|
|
baseptr[0][COLOR_BLUE][chan] = mpm_data[pos++]; |
|
|
|
chan++; |
|
|
|
} |
|
|
|
|
|
|
|
mpm_reply(rx_cmd, cause, 0, NULL); |
|
|
|
|
|
|
|
if (rx_cmd == CMD_WRITE_RAW_COLOR) { |
|
|
|
rgb_update(COLOR_MASK, 1); |
|
|
|
|
|
|
|
} else { |
|
|
|
eeprom_write(); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case CMD_READ_RAW_COLOR: |
|
|
|
case CMD_READ_INIT_COLOR: |
|
|
|
{ |
|
|
|
uint8_t chan = mpm_data[0]; |
|
|
|
uint8_t count = mpm_data[1]; |
|
|
|
uint8_t pos = 0; |
|
|
|
uint8_t cause = CAUSE_SUCCESS; |
|
|
|
|
|
|
|
uint8_t (*baseptr)[3][16] = (rx_cmd == CMD_READ_RAW_COLOR) ? &chan_value : &nvram_data.initialRGB; |
|
|
|
|
|
|
|
while (count--) { |
|
|
|
if ((chan >= 16) || ((pos +2) >= MPM_MAX_DATA_SIZE)) { |
|
|
|
cause = CAUSE_INVALID_PARAMETER; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
mpm_data[pos++] = baseptr[0][COLOR_RED][chan]; |
|
|
|
mpm_data[pos++] = baseptr[0][COLOR_GREEN][chan]; |
|
|
|
mpm_data[pos++] = baseptr[0][COLOR_BLUE][chan]; |
|
|
|
chan++; |
|
|
|
} |
|
|
|
|
|
|
|
mpm_reply(rx_cmd, cause, pos, mpm_data); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
mpm_reply(rx_cmd, CAUSE_UNSPECIFIED_ERROR, 0, NULL); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void mpm_init(void) |
|
|
|
{ |
|
|
|
PORTD &= ~(1<<RXTX); |
|
|
|