avr: implement the gp [get phy-to-logical] command
This commit is contained in:
parent
d0dfd67d30
commit
6f377bdc53
|
@ -22,6 +22,7 @@
|
|||
#include "global.h"
|
||||
#include "buffer.h"
|
||||
#include "ctrl.h"
|
||||
#include "encode.h"
|
||||
|
||||
cBuffer ctrlRxBuffer; // ctrl receive buffer
|
||||
cBuffer ctrlTxBuffer; // ctrl transmit buffer
|
||||
|
@ -29,6 +30,8 @@ cBuffer ctrlTxBuffer; // ctrl transmit buffer
|
|||
static char ctrlRxData[CTRL_RX_BUFFER_SIZE];
|
||||
static char ctrlTxData[CTRL_TX_BUFFER_SIZE];
|
||||
|
||||
extern uint8_t phy_to_log[];
|
||||
|
||||
void ctrlInit(void)
|
||||
{
|
||||
// initialize the CTRL receive buffer
|
||||
|
@ -94,6 +97,11 @@ uint8_t ctrlGetFromRxBuffer(uint8_t* data)
|
|||
}
|
||||
}
|
||||
|
||||
void ctrlFlushReceiveBuffer(void)
|
||||
{
|
||||
ctrlRxBuffer.datalength = 0;
|
||||
}
|
||||
|
||||
void ctrlRxToTxLoop(void)
|
||||
{
|
||||
uint8_t data;
|
||||
|
@ -102,3 +110,55 @@ void ctrlRxToTxLoop(void)
|
|||
ctrlAddToTxBuffer(data);
|
||||
}
|
||||
}
|
||||
|
||||
void ctrlDecode(void)
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
if (ctrlGetFromRxBuffer(cmd) && ctrlGetFromRxBuffer(cmd+1)) {
|
||||
ctrlAddToTxBuffer(cmd[0]);
|
||||
ctrlAddToTxBuffer(cmd[1]);
|
||||
|
||||
switch (cmd[0]) {
|
||||
case 'g':
|
||||
ctrlCmdGet(cmd[1]);
|
||||
break;
|
||||
case 's':
|
||||
ctrlCmdSet(cmd[1]);
|
||||
break;
|
||||
case 'c':
|
||||
if (cmd[1] == 't') ctrlCmdCommit();
|
||||
break;
|
||||
}
|
||||
|
||||
ctrlAddToTxBuffer('.');
|
||||
}
|
||||
|
||||
ctrlFlushReceiveBuffer();
|
||||
}
|
||||
|
||||
void ctrlCmdGet(uint8_t cmd)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t hex;
|
||||
|
||||
switch (cmd) {
|
||||
case 'p':
|
||||
for (i = 0 ; i < MAX_SENSORS; i++) {
|
||||
hex = btoh(phy_to_log[i]);
|
||||
ctrlAddToTxBuffer((uint8_t)(hex >> 8));
|
||||
ctrlAddToTxBuffer((uint8_t)hex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ctrlCmdSet(uint8_t cmd)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void ctrlCmdCommit(void)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
|
|
@ -86,8 +86,19 @@ uint8_t ctrlAddToRxBuffer(uint8_t data);
|
|||
*/
|
||||
uint8_t ctrlGetFromRxBuffer(uint8_t* data);
|
||||
|
||||
/**
|
||||
* Flush the ctrl Rx buffer.
|
||||
*
|
||||
*/
|
||||
void ctrlFlushReceiveBuffer(void);
|
||||
|
||||
/**
|
||||
* Loop all bytes from the ctrl Rx to Tx buffer.
|
||||
*
|
||||
*/
|
||||
void ctrlRxToTxLoop(void);
|
||||
|
||||
void ctrlDecode(void);
|
||||
void ctrlCmdGet(uint8_t cmd);
|
||||
void ctrlCmdSet(uint8_t cmd);
|
||||
void ctrlCmdCommit(void);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#include <stdint.h>
|
||||
|
||||
// hex to binary/byte decoding
|
||||
uint8_t htob(uint16_t hex)
|
||||
{
|
||||
uint8_t low_hex = (uint8_t) hex;
|
||||
uint8_t high_hex = (uint8_t) (hex >> 8);
|
||||
uint8_t byte;
|
||||
|
||||
byte = (high_hex > 0x40) ? (high_hex & 0x0F) + 9 : high_hex & 0x0F;
|
||||
byte = byte << 4;
|
||||
byte |= (low_hex > 0x40) ? (low_hex & 0x0F) + 9 : low_hex & 0x0F;
|
||||
return byte;
|
||||
}
|
||||
|
||||
// binary/byte to hex encoding
|
||||
uint16_t btoh(uint8_t byte)
|
||||
{
|
||||
uint8_t low_nibble = (byte & 0x0F);
|
||||
uint8_t high_nibble = (byte & 0xF0) >> 4;
|
||||
uint16_t hex;
|
||||
|
||||
hex = (high_nibble > 0x09) ? high_nibble - 9 + 0x60 : high_nibble + 0x30;
|
||||
hex = hex << 8;
|
||||
hex |= (low_nibble > 0x09) ? low_nibble - 9 + 0x60 : low_nibble + 0x30;
|
||||
return hex;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
uint8_t htob(uint16_t hex);
|
||||
uint16_t btoh(uint8_t byte);
|
|
@ -39,4 +39,6 @@
|
|||
|
||||
#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond
|
||||
|
||||
#define MAX_SENSORS 6
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
//
|
||||
// basiciotest.c : test code for the io and buffer ops of the UART and SPI ports
|
||||
//
|
||||
// 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$
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "uart.h"
|
||||
#include "spi.h"
|
||||
#include "ctrl.h"
|
||||
#include "global.h"
|
||||
#include "encode.h"
|
||||
|
||||
#define NO_OP_1 1
|
||||
#define NO_OP_2 2
|
||||
#define START_TX 4
|
||||
#define TRANSMIT 8
|
||||
#define HIGH_HEX 16
|
||||
#define TO_FROM_UART 32
|
||||
#define NEW_CTRL_MSG 64
|
||||
|
||||
#define SPI_END_OF_TX 0x00
|
||||
#define SPI_END_OF_MESSAGE '.'
|
||||
#define SPI_FORWARD_TO_UART_PORT 'u'
|
||||
#define SPI_FORWARD_TO_CTRL_PORT 'l' // 'l'ocal port
|
||||
|
||||
volatile uint8_t spi_status, high_hex;
|
||||
|
||||
uint8_t EEMEM first_EEPROM_byte_not_used_to_protect_from_brownout_corruption = 0x00;
|
||||
|
||||
volatile struct event_struct EEMEM EEPROM_event = {0, 0};
|
||||
volatile struct event_struct event;
|
||||
|
||||
uint8_t EEMEM EEPROM_phy_to_log[MAX_SENSORS] = {0, 1, 2, 3, 4, 5};
|
||||
uint8_t phy_to_log[MAX_SENSORS];
|
||||
|
||||
volatile struct sensor_struct EEMEM EEPROM_sensor[MAX_SENSORS];
|
||||
volatile struct sensor_struct sensor[MAX_SENSORS];
|
||||
|
||||
ISR(SPI_STC_vect)
|
||||
{
|
||||
uint8_t spi_rx, rx, tx;
|
||||
uint16_t spi_tx;
|
||||
|
||||
// the SPI is double-buffered, requiring two NO_OPs when switching from Tx to Rx
|
||||
if (spi_status & (NO_OP_1 | NO_OP_2)) {
|
||||
spi_status--;
|
||||
return;
|
||||
}
|
||||
|
||||
// do we have to transmit the first byte?
|
||||
if (spi_status & START_TX) {
|
||||
received_from_spi(SPI_FORWARD_TO_CTRL_PORT);
|
||||
spi_status &= ~START_TX;
|
||||
return;
|
||||
}
|
||||
|
||||
// are we in Tx mode?
|
||||
if (spi_status & TRANSMIT) {
|
||||
if (spi_status & HIGH_HEX) {
|
||||
received_from_spi(high_hex);
|
||||
spi_status &= ~HIGH_HEX;
|
||||
return;
|
||||
}
|
||||
|
||||
if (spi_status & TO_FROM_UART) {
|
||||
if (!uartReceiveByte(&tx)) {
|
||||
received_from_spi(SPI_END_OF_TX);
|
||||
spi_status &= ~TRANSMIT;
|
||||
spi_status |= NO_OP_2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ctrlGetFromTxBuffer(&tx)) {
|
||||
if (tx == SPI_END_OF_MESSAGE) {
|
||||
received_from_spi(tx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
received_from_spi(SPI_FORWARD_TO_UART_PORT);
|
||||
spi_status |= TO_FROM_UART;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spi_tx = btoh(tx);
|
||||
high_hex = (uint8_t)spi_tx;
|
||||
spi_status |= HIGH_HEX;
|
||||
received_from_spi((uint8_t)(spi_tx >> 8));
|
||||
return;
|
||||
}
|
||||
|
||||
// we're in Rx mode
|
||||
switch (spi_rx = received_from_spi(0x00)) {
|
||||
case SPI_END_OF_TX:
|
||||
spi_status |= TRANSMIT | START_TX;
|
||||
spi_status &= ~(HIGH_HEX | TO_FROM_UART);
|
||||
break;
|
||||
case SPI_END_OF_MESSAGE:
|
||||
if (!(spi_status & TO_FROM_UART)) {
|
||||
ctrlAddToRxBuffer(spi_rx);
|
||||
spi_status |= NEW_CTRL_MSG;
|
||||
}
|
||||
break;
|
||||
case SPI_FORWARD_TO_UART_PORT:
|
||||
spi_status |= TO_FROM_UART;
|
||||
break;
|
||||
case SPI_FORWARD_TO_CTRL_PORT:
|
||||
spi_status &= ~TO_FROM_UART;
|
||||
break;
|
||||
default:
|
||||
if (spi_status & HIGH_HEX) {
|
||||
rx = htob(((uint16_t)high_hex << 8) + spi_rx);
|
||||
|
||||
if (spi_status & TO_FROM_UART) {
|
||||
uartAddToTxBuffer(rx);
|
||||
}
|
||||
else {
|
||||
ctrlAddToRxBuffer(rx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
high_hex = spi_rx;
|
||||
}
|
||||
// toggle the HEX bit in spi_status
|
||||
spi_status ^= HIGH_HEX;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
/* void */
|
||||
}
|
||||
|
||||
ISR(ANALOG_COMP_vect)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
PORTB |= (1<<PB0);
|
||||
|
||||
//disable uC sections to consume less power while writing to EEPROM
|
||||
//disable UART Tx and Rx:
|
||||
UCSR0B &= ~((1<<RXEN0) | (1<<TXEN0));
|
||||
//disable ADC:
|
||||
ADCSRA &= ~(1<<ADEN);
|
||||
|
||||
for (i=0; i<128; i++)
|
||||
eeprom_write_byte((uint8_t *)i, i);
|
||||
|
||||
//enable UART Tx and Rx:
|
||||
UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
|
||||
// enable ADC and start a first ADC conversion
|
||||
ADCSRA |= (1<<ADEN) | (1<<ADSC);
|
||||
|
||||
PORTB &= ~(1<<PB0);
|
||||
}
|
||||
|
||||
void setup_datastructs(void)
|
||||
{
|
||||
eeprom_read_block((void*)&event, (const void*)&EEPROM_event, sizeof(event));
|
||||
eeprom_read_block((void*)&phy_to_log, (const void*)&EEPROM_phy_to_log, sizeof(phy_to_log));
|
||||
eeprom_read_block((void*)&sensor, (const void*)&EEPROM_sensor, sizeof(sensor));
|
||||
}
|
||||
|
||||
void setup_pulse_input(void)
|
||||
{
|
||||
// PD2=INT0 and PD3=INT1 configuration
|
||||
// set as input pin with 20k pull-up enabled
|
||||
PORTD |= (1<<PD2) | (1<<PD3);
|
||||
// INT0 and INT1 to trigger an interrupt on a falling edge
|
||||
EICRA = (1<<ISC01) | (1<<ISC11);
|
||||
// enable INT0 and INT1 interrupts
|
||||
EIMSK = (1<<INT0) | (1<<INT1);
|
||||
}
|
||||
|
||||
|
||||
void setup_timer1(void)
|
||||
{
|
||||
// Timer1 clock prescaler set to 1 => fTOV1 = 3686.4kHz / 65536 = 56.25Hz (DS p.134)
|
||||
TCCR1B |= (1<<CS10);
|
||||
// Increase sampling frequency to 2kHz (= 667Hz per channel) with an error of 0.01% (DS p.122)
|
||||
OCR1A = 0x0732;
|
||||
// Timer1 set to CTC mode (DS p.133)
|
||||
TCCR1B |= 1<<WGM12;
|
||||
// Enable output compare match interrupt for timer1 (DS p.136)
|
||||
TIMSK1 |= (1<<OCIE1A);
|
||||
#if DBG > 0
|
||||
// Set PB1=OC1A as output pin
|
||||
DDRB |= (1<<DDB1);
|
||||
// Toggle pin OC1A=PB1 on compare match
|
||||
TCCR1A |= 1<<COM1A0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setup_analog_comparator(void)
|
||||
{
|
||||
// analog comparator setup for brown-out detection
|
||||
// PD7=AIN1 configured by default as input to obtain high impedance
|
||||
|
||||
// disable digital input cicuitry on AIN0 and AIN1 pins to reduce leakage current
|
||||
DIDR1 |= (1<<AIN1D) | (1<<AIN0D);
|
||||
|
||||
// comparing AIN1 (Vcc/4.4) to bandgap reference (1.1V)
|
||||
// bandgap select | AC interrupt enable | AC interrupt on rising edge (DS p.243)
|
||||
ACSR |= (1<<ACBG) | (1<<ACIE) | (1<<ACIS1) | (1<<ACIS0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// RS-485: Configure PD5=DE as output pin with low as default
|
||||
DDRD |= (1<<DDD5);
|
||||
// set high to transmit
|
||||
//PORTD |= (1<<PD5);
|
||||
|
||||
setup_datastructs();
|
||||
setup_timer1();
|
||||
setup_pulse_input();
|
||||
setup_analog_comparator();
|
||||
|
||||
// initialize the CTRL buffers
|
||||
ctrlInit();
|
||||
// initialize the UART hardware and buffers
|
||||
uartInit();
|
||||
// initialize the SPI in slave mode
|
||||
setup_spi(SPI_MODE_0, SPI_MSB, SPI_INTERRUPT, SPI_SLAVE);
|
||||
|
||||
|
||||
for(;;) {
|
||||
if (spi_status & NEW_CTRL_MSG) {
|
||||
//ctrlRxToTxLoop();
|
||||
ctrlDecode();
|
||||
spi_status &= ~NEW_CTRL_MSG;
|
||||
}
|
||||
|
||||
// toggle the LED=PB0 pin
|
||||
_delay_ms(50);
|
||||
DDRB ^= (1<<PB0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
struct event_struct {
|
||||
uint16_t wdt;
|
||||
uint16_t brown_out;
|
||||
};
|
||||
|
||||
struct sensor_struct {
|
||||
uint32_t value;
|
||||
uint16_t meterconst;
|
||||
};
|
||||
|
|
@ -67,11 +67,11 @@ FORMAT = ihex
|
|||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = basiciotest
|
||||
TARGET = main
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c buffer.c uart.c spi.c ctrl.c
|
||||
SRC = $(TARGET).c buffer.c uart.c spi.c ctrl.c encode.c
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
|
|
Loading…
Reference in New Issue