2010-07-07 15:32:02 +00:00
|
|
|
//
|
|
|
|
// ctrl.c : AVR uC code for ctrl buffer initialisation and put/get ops
|
|
|
|
//
|
|
|
|
// Copyright (c) 2010 flukso.net
|
|
|
|
//
|
|
|
|
// 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; either version 2
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
2010-12-26 21:30:51 +00:00
|
|
|
#include <avr/eeprom.h>
|
2011-01-15 22:03:16 +00:00
|
|
|
#include <util/crc16.h>
|
2010-12-26 21:30:51 +00:00
|
|
|
|
2010-07-07 15:32:02 +00:00
|
|
|
#include "global.h"
|
2010-12-26 21:30:51 +00:00
|
|
|
#include "main.h"
|
2010-07-07 15:32:02 +00:00
|
|
|
#include "buffer.h"
|
|
|
|
#include "ctrl.h"
|
2010-12-26 18:03:22 +00:00
|
|
|
#include "encode.h"
|
2010-07-07 15:32:02 +00:00
|
|
|
|
|
|
|
cBuffer ctrlRxBuffer; // ctrl receive buffer
|
|
|
|
cBuffer ctrlTxBuffer; // ctrl transmit buffer
|
|
|
|
|
|
|
|
static char ctrlRxData[CTRL_RX_BUFFER_SIZE];
|
|
|
|
static char ctrlTxData[CTRL_TX_BUFFER_SIZE];
|
|
|
|
|
2011-01-16 22:25:11 +00:00
|
|
|
extern struct version_struct EEMEM EEPROM_version;
|
|
|
|
extern struct version_struct version;
|
2010-12-29 20:45:41 +00:00
|
|
|
|
2011-01-16 16:30:55 +00:00
|
|
|
extern struct event_struct EEMEM EEPROM_event;
|
|
|
|
extern struct event_struct event;
|
2010-12-26 21:30:51 +00:00
|
|
|
|
|
|
|
extern uint8_t EEMEM EEPROM_phy_to_log[MAX_SENSORS];
|
|
|
|
extern uint8_t phy_to_log[MAX_SENSORS];
|
|
|
|
|
2011-01-16 16:30:55 +00:00
|
|
|
extern struct sensor_struct EEMEM EEPROM_sensor[MAX_SENSORS];
|
|
|
|
extern struct sensor_struct sensor[MAX_SENSORS];
|
2010-12-26 18:03:22 +00:00
|
|
|
|
2011-01-16 16:30:55 +00:00
|
|
|
extern struct state_struct state[MAX_SENSORS];
|
2010-12-28 22:23:16 +00:00
|
|
|
|
2010-10-16 19:25:57 +00:00
|
|
|
void ctrlInit(void)
|
|
|
|
{
|
2010-07-07 15:32:02 +00:00
|
|
|
// initialize the CTRL receive buffer
|
|
|
|
bufferInit(&ctrlRxBuffer, (u08*) ctrlRxData, CTRL_RX_BUFFER_SIZE);
|
|
|
|
// initialize the CTRL transmit buffer
|
|
|
|
bufferInit(&ctrlTxBuffer, (u08*) ctrlTxData, CTRL_TX_BUFFER_SIZE);
|
|
|
|
}
|
|
|
|
|
2010-10-16 19:25:57 +00:00
|
|
|
uint8_t ctrlTxBufferIsEmpty(void)
|
|
|
|
{
|
|
|
|
if(ctrlTxBuffer.datalength == 0) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlAddToTxBuffer(uint8_t data)
|
|
|
|
{
|
|
|
|
return bufferAddToEnd(&ctrlTxBuffer, data);
|
2010-07-07 15:32:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlGetFromTxBuffer(uint8_t* data) {
|
|
|
|
// make sure we have data in the Tx buffer
|
|
|
|
if(ctrlTxBuffer.datalength) {
|
|
|
|
// get byte from beginning of buffer
|
|
|
|
*data = bufferGetFromFront(&ctrlTxBuffer);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// no data
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-16 19:25:57 +00:00
|
|
|
uint8_t ctrlRxBufferIsEmpty(void)
|
|
|
|
{
|
|
|
|
if(ctrlRxBuffer.datalength == 0) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlAddToRxBuffer(uint8_t data)
|
|
|
|
{
|
|
|
|
return bufferAddToEnd(&ctrlRxBuffer, data);
|
|
|
|
}
|
|
|
|
|
2010-12-27 20:39:55 +00:00
|
|
|
uint8_t ctrlGetFromRxBuffer(uint8_t* pdata)
|
2010-10-16 19:25:57 +00:00
|
|
|
{
|
|
|
|
// make sure we have data in the Rx buffer
|
|
|
|
if(ctrlRxBuffer.datalength) {
|
|
|
|
// get byte from beginning of buffer
|
2010-12-27 20:39:55 +00:00
|
|
|
*pdata = bufferGetFromFront(&ctrlRxBuffer);
|
2010-10-16 19:25:57 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// no data
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-07-07 15:32:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-29 14:29:31 +00:00
|
|
|
void ctrlFlushRxBuffer(void)
|
2010-12-26 18:03:22 +00:00
|
|
|
{
|
|
|
|
ctrlRxBuffer.datalength = 0;
|
|
|
|
}
|
|
|
|
|
2010-12-29 14:29:31 +00:00
|
|
|
void ctrlFlushTxBuffer(void)
|
|
|
|
{
|
|
|
|
ctrlTxBuffer.datalength = 0;
|
|
|
|
}
|
|
|
|
|
2010-12-27 20:39:55 +00:00
|
|
|
uint8_t ctrlReadCharFromRxBuffer(uint8_t* pdata)
|
|
|
|
{
|
|
|
|
uint8_t high_hex, low_hex;
|
|
|
|
|
|
|
|
if (ctrlGetFromRxBuffer(&high_hex) && ctrlGetFromRxBuffer(&low_hex)) {
|
2011-01-16 11:00:41 +00:00
|
|
|
htob(high_hex, low_hex, pdata);
|
2010-12-27 20:39:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlReadShortFromRxBuffer(uint16_t* pdata)
|
|
|
|
{
|
|
|
|
uint8_t high_char, low_char;
|
|
|
|
|
|
|
|
if(ctrlReadCharFromRxBuffer(&high_char) && ctrlReadCharFromRxBuffer(&low_char)) {
|
|
|
|
*pdata = ((uint16_t)high_char << 8) + low_char;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlReadLongFromRxBuffer(uint32_t* pdata)
|
|
|
|
{
|
|
|
|
uint16_t high_short, low_short;
|
|
|
|
|
|
|
|
if(ctrlReadShortFromRxBuffer(&high_short) && ctrlReadShortFromRxBuffer(&low_short)) {
|
|
|
|
*pdata = ((uint32_t)high_short << 16) + low_short;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlWriteCharToTxBuffer(uint8_t data)
|
|
|
|
{
|
2011-01-16 11:00:41 +00:00
|
|
|
uint8_t high_hex, low_hex;
|
2010-12-27 20:39:55 +00:00
|
|
|
|
2011-01-16 11:00:41 +00:00
|
|
|
btoh(data, &high_hex, &low_hex);
|
|
|
|
if (ctrlAddToTxBuffer(high_hex) && ctrlAddToTxBuffer(low_hex)) {
|
2010-12-27 20:39:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlWriteShortToTxBuffer(uint16_t data)
|
|
|
|
{
|
|
|
|
if (ctrlWriteCharToTxBuffer((uint8_t)(data >> 8)) && ctrlWriteCharToTxBuffer((uint8_t)data)) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ctrlWriteLongToTxBuffer(uint32_t data)
|
|
|
|
{
|
|
|
|
if (ctrlWriteShortToTxBuffer((uint16_t)(data >> 16)) && ctrlWriteShortToTxBuffer((uint16_t)data)) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-16 19:25:57 +00:00
|
|
|
void ctrlRxToTxLoop(void)
|
|
|
|
{
|
|
|
|
uint8_t data;
|
2010-08-07 21:29:15 +00:00
|
|
|
|
2010-10-16 19:25:57 +00:00
|
|
|
while (ctrlGetFromRxBuffer(&data)) {
|
|
|
|
ctrlAddToTxBuffer(data);
|
2010-07-07 15:32:02 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-26 18:03:22 +00:00
|
|
|
|
2011-01-15 22:03:16 +00:00
|
|
|
uint8_t ctrlCalcCrc8(cBuffer* buffer)
|
|
|
|
{
|
|
|
|
uint8_t i, crc = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < buffer->datalength; i++) {
|
|
|
|
crc = _crc_ibutton_update(crc, bufferGetAtIndex(buffer, i));
|
|
|
|
}
|
|
|
|
return crc;
|
|
|
|
}
|
|
|
|
|
2010-12-26 18:03:22 +00:00
|
|
|
void ctrlDecode(void)
|
|
|
|
{
|
2011-01-15 22:03:16 +00:00
|
|
|
uint8_t cmd[2], crc;
|
2010-12-26 18:03:22 +00:00
|
|
|
|
2010-12-29 14:29:31 +00:00
|
|
|
ctrlFlushTxBuffer();
|
|
|
|
|
2010-12-26 18:03:22 +00:00
|
|
|
if (ctrlGetFromRxBuffer(cmd) && ctrlGetFromRxBuffer(cmd+1)) {
|
|
|
|
ctrlAddToTxBuffer(cmd[0]);
|
|
|
|
ctrlAddToTxBuffer(cmd[1]);
|
|
|
|
|
|
|
|
switch (cmd[0]) {
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'g': /* get */
|
2010-12-26 18:03:22 +00:00
|
|
|
ctrlCmdGet(cmd[1]);
|
|
|
|
break;
|
2010-12-29 15:22:01 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 's': /* set */
|
2010-12-26 18:03:22 +00:00
|
|
|
ctrlCmdSet(cmd[1]);
|
|
|
|
break;
|
2010-12-29 15:22:01 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'c': /* commit */
|
2010-12-26 18:03:22 +00:00
|
|
|
if (cmd[1] == 't') ctrlCmdCommit();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-01-15 22:03:16 +00:00
|
|
|
crc = ctrlCalcCrc8(&ctrlTxBuffer);
|
|
|
|
ctrlWriteCharToTxBuffer(crc);
|
|
|
|
|
2010-12-26 18:03:22 +00:00
|
|
|
ctrlAddToTxBuffer('.');
|
|
|
|
}
|
|
|
|
|
2010-12-29 14:29:31 +00:00
|
|
|
ctrlFlushRxBuffer();
|
2010-12-26 18:03:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ctrlCmdGet(uint8_t cmd)
|
|
|
|
{
|
2011-01-16 16:30:55 +00:00
|
|
|
uint8_t i = 0;
|
2010-12-28 22:23:16 +00:00
|
|
|
uint32_t tmp32, tmp32_bis;
|
2010-12-26 18:03:22 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'h': /* hardware {major,minor} version */
|
2011-01-16 22:25:11 +00:00
|
|
|
ctrlWriteShortToTxBuffer(version.hw_major);
|
|
|
|
ctrlWriteCharToTxBuffer(version.hw_minor);
|
|
|
|
break;
|
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 's': /* software {major,minor} version */
|
2011-01-16 22:25:11 +00:00
|
|
|
ctrlWriteCharToTxBuffer(version.sw_major);
|
|
|
|
ctrlWriteCharToTxBuffer(version.sw_minor);
|
2010-12-29 20:45:41 +00:00
|
|
|
break;
|
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'p': /* phy-to-logical mapping */
|
2010-12-26 18:03:22 +00:00
|
|
|
for (i = 0 ; i < MAX_SENSORS; i++) {
|
2010-12-27 20:39:55 +00:00
|
|
|
ctrlWriteCharToTxBuffer(phy_to_log[i]);
|
2010-12-26 18:03:22 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-12-27 22:04:55 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'c': /* sensor counter value */
|
2010-12-27 22:04:55 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&i);
|
2010-12-27 23:34:50 +00:00
|
|
|
|
|
|
|
cli();
|
2010-12-28 13:34:56 +00:00
|
|
|
tmp32 = sensor[i].counter;
|
2010-12-27 23:34:50 +00:00
|
|
|
sei();
|
|
|
|
|
|
|
|
ctrlWriteLongToTxBuffer(tmp32);
|
2010-12-27 22:04:55 +00:00
|
|
|
break;
|
2010-12-27 22:12:52 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'm': /* sensor meterconstant */
|
2010-12-27 22:12:52 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&i);
|
|
|
|
ctrlWriteShortToTxBuffer(sensor[i].meterconst);
|
|
|
|
break;
|
2010-12-27 22:23:15 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'w': /* watchdog counter */
|
2010-12-27 22:23:15 +00:00
|
|
|
ctrlWriteShortToTxBuffer(event.wdt);
|
|
|
|
break;
|
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'b': /* brown-out counter */
|
2010-12-27 22:23:15 +00:00
|
|
|
ctrlWriteShortToTxBuffer(event.brown_out);
|
|
|
|
break;
|
2010-12-28 22:23:16 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'd': /* delta: all changes since last gd */
|
2010-12-28 22:23:16 +00:00
|
|
|
for (i = 0 ; i < MAX_SENSORS; i++) {
|
|
|
|
if (state[i].flags & (STATE_PULSE | STATE_POWER)) {
|
|
|
|
ctrlWriteCharToTxBuffer(i);
|
|
|
|
|
|
|
|
cli();
|
|
|
|
tmp32 = sensor[i].counter;
|
|
|
|
tmp32_bis = (i < 3) ? state[i].power : state[i].timestamp;
|
|
|
|
sei();
|
|
|
|
|
|
|
|
ctrlWriteLongToTxBuffer(tmp32);
|
|
|
|
ctrlWriteLongToTxBuffer(tmp32_bis);
|
|
|
|
|
|
|
|
state[i].flags &= ~(STATE_PULSE | STATE_POWER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2010-12-26 18:03:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ctrlCmdSet(uint8_t cmd)
|
|
|
|
{
|
2011-01-16 22:25:11 +00:00
|
|
|
uint8_t i = 0, tmp8 = 0, tmp8_bis = 0;
|
2011-01-16 16:30:55 +00:00
|
|
|
uint16_t tmp16 = 0;
|
|
|
|
uint32_t tmp32 = 0;
|
2010-12-26 18:54:15 +00:00
|
|
|
|
|
|
|
switch (cmd) {
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'h': /* hardware {major,minor} version */
|
2010-12-29 20:45:41 +00:00
|
|
|
ctrlReadShortFromRxBuffer(&tmp16);
|
2011-01-16 22:25:11 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&tmp8);
|
2010-12-29 20:45:41 +00:00
|
|
|
|
|
|
|
cli();
|
2011-01-16 22:25:11 +00:00
|
|
|
version.hw_major = tmp16;
|
|
|
|
version.hw_minor = tmp8;
|
2010-12-29 20:45:41 +00:00
|
|
|
sei();
|
|
|
|
break;
|
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 's': /* software {major,minor} version */
|
2011-01-16 22:25:11 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&tmp8);
|
|
|
|
ctrlReadCharFromRxBuffer(&tmp8_bis);
|
|
|
|
|
|
|
|
cli();
|
|
|
|
version.sw_major = tmp8;
|
|
|
|
version.sw_minor = tmp8_bis;
|
|
|
|
sei();
|
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'p': /* phy-to-logical mapping */
|
2010-12-26 18:54:15 +00:00
|
|
|
for (i = 0 ; i < MAX_SENSORS; i++) {
|
2010-12-27 23:34:50 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&tmp8);
|
|
|
|
|
|
|
|
cli();
|
|
|
|
phy_to_log[i] = tmp8;
|
|
|
|
sei();
|
2010-12-26 18:54:15 +00:00
|
|
|
}
|
|
|
|
break;
|
2010-12-27 22:23:15 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'c': /* sensor counter value */
|
2010-12-27 22:04:55 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&i);
|
2010-12-27 23:34:50 +00:00
|
|
|
ctrlReadLongFromRxBuffer(&tmp32);
|
|
|
|
|
|
|
|
cli();
|
2010-12-28 13:34:56 +00:00
|
|
|
sensor[i].counter = tmp32;
|
2010-12-27 23:34:50 +00:00
|
|
|
sei();
|
2010-12-27 22:04:55 +00:00
|
|
|
break;
|
2010-12-27 22:23:15 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'm': /* sensor meterconstant */
|
2010-12-27 22:12:52 +00:00
|
|
|
ctrlReadCharFromRxBuffer(&i);
|
2010-12-27 23:34:50 +00:00
|
|
|
ctrlReadShortFromRxBuffer(&tmp16);
|
|
|
|
|
|
|
|
cli();
|
|
|
|
sensor[i].meterconst = tmp16;
|
|
|
|
sei();
|
2010-12-27 22:12:52 +00:00
|
|
|
break;
|
2010-12-27 22:23:15 +00:00
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'w': /* watchdog counter */
|
2010-12-27 23:34:50 +00:00
|
|
|
ctrlReadShortFromRxBuffer(&tmp16);
|
|
|
|
|
|
|
|
cli();
|
|
|
|
event.wdt = tmp16;
|
|
|
|
sei();
|
2010-12-27 22:23:15 +00:00
|
|
|
break;
|
|
|
|
|
2011-01-16 22:41:53 +00:00
|
|
|
case 'b': /* brown-out counter */
|
2010-12-27 23:34:50 +00:00
|
|
|
ctrlReadShortFromRxBuffer(&tmp16);
|
|
|
|
|
|
|
|
cli();
|
|
|
|
event.brown_out = tmp16;
|
|
|
|
sei();
|
2010-12-27 22:23:15 +00:00
|
|
|
break;
|
2010-12-26 18:54:15 +00:00
|
|
|
}
|
2010-12-26 18:03:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ctrlCmdCommit(void)
|
|
|
|
{
|
2010-12-26 21:30:51 +00:00
|
|
|
cli();
|
2010-12-29 20:45:41 +00:00
|
|
|
eeprom_write_block((const void*)&version, (void*)&EEPROM_version, sizeof(version));
|
2010-12-26 21:30:51 +00:00
|
|
|
eeprom_write_block((const void*)&event, (void*)&EEPROM_event, sizeof(event));
|
|
|
|
eeprom_write_block((const void*)&phy_to_log, (void*)&EEPROM_phy_to_log, sizeof(phy_to_log));
|
|
|
|
eeprom_write_block((const void*)&sensor, (void*)&EEPROM_sensor, sizeof(sensor));
|
|
|
|
sei();
|
2010-12-26 18:03:22 +00:00
|
|
|
}
|