170 lines
4.9 KiB
C
170 lines
4.9 KiB
C
|
/***************************************************************************
|
||
|
* mpm comms *
|
||
|
* *
|
||
|
* Copyright (C) 2011 - 2012 by Olaf Rempel *
|
||
|
* razzor AT kopf MINUS tisch DOT de *
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; version 2 of the License, *
|
||
|
* *
|
||
|
* This program is distributed in the hope that it will be useful, *
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||
|
* GNU General Public License for more details. *
|
||
|
* *
|
||
|
* You should have received a copy of the GNU General Public License *
|
||
|
* along with this program; if not, write to the *
|
||
|
* Free Software Foundation, Inc., *
|
||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
|
***************************************************************************/
|
||
|
#include <avr/io.h>
|
||
|
#include <avr/interrupt.h>
|
||
|
#include <avr/wdt.h>
|
||
|
|
||
|
#include "rgb16mpm.h"
|
||
|
|
||
|
#define CMD_WAIT 0x00
|
||
|
#define CMD_SWITCH_MODE 0x01
|
||
|
#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
|
||
|
|
||
|
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
|
||
|
|
||
|
const static uint8_t versioninfo[16] = "rgb16mpm v0.99";
|
||
|
|
||
|
static uint8_t rx_cmd;
|
||
|
static uint16_t rx_bcnt = 0xFF;
|
||
|
static uint16_t rx_length;
|
||
|
|
||
|
static uint8_t tx_cmd;
|
||
|
static uint8_t tx_cause;
|
||
|
static uint16_t tx_length;
|
||
|
static uint16_t tx_bcnt;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
if (rx_bcnt == 0) {
|
||
|
rx_cmd = data;
|
||
|
|
||
|
} else if ((rx_bcnt == 1) || (rx_bcnt == 2)) {
|
||
|
rx_length = (rx_length << 8) | data;
|
||
|
|
||
|
} else if ((rx_bcnt -3) < rx_length) {
|
||
|
// TODO: get data
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
/* enable interrupt */
|
||
|
UCSRB |= (1<<UDRIE);
|
||
|
}
|
||
|
rx_bcnt++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ISR(USART_UDRE_vect)
|
||
|
{
|
||
|
/* enable IRQs again, but prevent multiple UDRE IRQs */
|
||
|
UCSRB &= ~(1<<UDRIE);
|
||
|
sei();
|
||
|
|
||
|
if ((tx_bcnt < 4) || (tx_bcnt -4) < tx_length) {
|
||
|
uint16_t pos = (tx_bcnt -4);
|
||
|
uint8_t data = 0xFF;
|
||
|
|
||
|
if (tx_bcnt == 1) {
|
||
|
data = tx_cause;
|
||
|
|
||
|
} else if (tx_bcnt == 2) {
|
||
|
data = (tx_length >> 8);
|
||
|
|
||
|
} else if (tx_bcnt == 3) {
|
||
|
data = (tx_length & 0xFF);
|
||
|
|
||
|
} else if (tx_cmd == CMD_GET_VERSION) {
|
||
|
data = versioninfo[pos];
|
||
|
|
||
|
} else {
|
||
|
data = 0xAA;
|
||
|
}
|
||
|
|
||
|
UDR = data;
|
||
|
|
||
|
/* re-enable for next round */
|
||
|
UCSRB |= (1<<UDRIE);
|
||
|
}
|
||
|
|
||
|
tx_bcnt++;
|
||
|
}
|
||
|
|
||
|
ISR(USART_TXC_vect, ISR_NOBLOCK)
|
||
|
{
|
||
|
/* disable RS485 TX */
|
||
|
PORTD &= ~(1<<RXTX);
|
||
|
|
||
|
/* enable MP mode again */
|
||
|
UCSRA |= (1<<MPCM);
|
||
|
rx_bcnt = 0xFF; // FIXME: cli?
|
||
|
|
||
|
#if !(STANDALONE)
|
||
|
if (tx_cmd == CMD_SWITCH_MODE) { // FIXME: check mode
|
||
|
wdt_enable(WDTO_15MS);
|
||
|
}
|
||
|
#endif /* !(STANDALONE) */
|
||
|
}
|
||
|
|
||
|
void mpm_init(void)
|
||
|
{
|
||
|
PORTD &= ~(1<<RXTX);
|
||
|
DDRD |= (1<<RXTX);
|
||
|
|
||
|
/* USART config */
|
||
|
/* Multi Drop Mode, 9n1 */
|
||
|
UCSRA = (1<<MPCM);
|
||
|
UCSRB = (1<<RXEN) | (1<<TXEN) | (1<<RXCIE) | (1<<TXCIE) | (1<<UCSZ2);
|
||
|
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
|
||
|
|
||
|
#if (STANDALONE)
|
||
|
OSCCAL = OSCCAL_VALUE;
|
||
|
|
||
|
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
|
||
|
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
|
||
|
|
||
|
/* MPM address stored in TWI address register */
|
||
|
TWAR = MPM_ADDRESS;
|
||
|
#endif /* (STANDALONE) */
|
||
|
}
|