diff --git a/Bootloader/.gitignore b/Bootloader/.gitignore new file mode 100644 index 0000000..bdb41b7 --- /dev/null +++ b/Bootloader/.gitignore @@ -0,0 +1,3 @@ +*.o +*.hex +*.elf \ No newline at end of file diff --git a/Bootloader/Makefile b/Bootloader/Makefile new file mode 100644 index 0000000..72cf373 --- /dev/null +++ b/Bootloader/Makefile @@ -0,0 +1,66 @@ +PROJECT = MyOtaBootloader +INCLUDES = ../libraries/MySensors + +MCU = atmega328p +CLK = 16000000L + +ISP_PORT = com5 +ISP_SPEED = 115200 +ISP_PROTOCOL = stk500v2 +ISP_MCU = m328p +# HFUSE = D8 - 4096 byte boot +ISP_HFUSE = D8 +# LFUSE = 4E - Low power resonator (16MHz), fast start, clkdiv/8 +ISP_LFUSE = FF +# EFUSE = 06 - 1.8V brownout +ISP_EFUSE = 06 +ISP_ARGS = -c$(ISP_PROTOCOL) -P$(ISP_PORT) -b$(ISP_SPEED) -p$(ISP_MCU) + +ifeq ($(OS),Windows_NT) + BINPATH = C:/Program Files (x86)/Arduino/hardware/tools/avr/bin/ + JAVAPATH = C:/Program Files/Java/jdk1.7.0_40/bin/ + JAVAC = $(JAVAPATH)javac.exe + JAVA = $(JAVAPATH)java.exe +else + UNAME_S := $(shell uname -s) + UNAME_P := $(shell uname -p) + UNAME_M := $(shell uname -m) + ifeq ($(UNAME_S),Linux) + ifeq ($(UNAME_P),x86_64) + BINPATH = ../arduino/bin-linux64/bin/ + else ifneq ($(filter %86,$(UNAME_P)),) + BINPATH = ../arduino/bin-linux32/bin/ + else ifneq ($(filter arm%,$(UNAME_M)),) + BINPATH = /usr/bin/ + endif + endif +endif + +CFLAGS = -c -g -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -Wall -mmcu=$(MCU) -DF_CPU=$(CLK) -std=gnu99 +LDFLAGS = -Os -Wl,--section-start=.text=0x7000 -nostartfiles -mmcu=$(MCU) + +all: clean out + +clean: + - rm *.o + - rm *.elf + - rm *.hex + +$(PROJECT).o: $(PROJECT).c + "$(BINPATH)avr-gcc" $(CFLAGS) -I$(INCLUDES) $< -o $@ + +$(PROJECT).elf: $(PROJECT).o + "$(BINPATH)avr-gcc" $(LDFLAGS) -o $@ $< -lm + +$(PROJECT).hex: $(PROJECT).elf + "$(BINPATH)avr-objcopy" -O ihex -R .eeprom $< $@ + +out: $(PROJECT).hex + "$(BINPATH)avr-size" $(PROJECT).elf + +load: clean out isp + +isp: $(PROJECT).hex + "$(BINPATH)avrdude" $(ISP_ARGS) -e -u -Ulock:w:0x3f:m -qq -Uefuse:w:0x$(ISP_EFUSE):m -Uhfuse:w:0x$(ISP_HFUSE):m -Ulfuse:w:0x$(ISP_LFUSE):m -Ulock:w:0x0f:m + "$(BINPATH)avrdude" $(ISP_ARGS) -V -q -s -Uflash:w:$(PROJECT).hex + "$(BINPATH)avrdude" $(ISP_ARGS) diff --git a/Bootloader/MyOtaBootloader.c b/Bootloader/MyOtaBootloader.c new file mode 100644 index 0000000..a601075 --- /dev/null +++ b/Bootloader/MyOtaBootloader.c @@ -0,0 +1,207 @@ +#include "MyOtaBootloader.h" + +int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9"))); + +volatile char dummy; + +EMPTY_INTERRUPT(WDT_vect); + +static uint16_t calcCRCrom (const void* ptr, uint16_t len) { + uint16_t crc = ~0; + for (uint16_t i = 0; i < len; ++i) + crc = _crc16_update(crc, pgm_read_byte((uint16_t) ptr + i)); + return crc; +} + +static uint8_t validFirmware () { + return calcCRCrom(0, fc.blocks * FIRMWARE_BLOCK_SIZE) == fc.crc; +} + +static void reboot() { + wdt_enable(WDTO_15MS); + for (;;); +} + +static void startup() { + if (validFirmware()) { + wdt_disable(); + clock_prescale_set(orgClockDiv); + ((void(*)()) 0)(); + } else + reboot(); +} + +static void boot_program_page(uint32_t page, uint8_t *buf) { + uint8_t sreg = SREG; + cli(); + eeprom_busy_wait(); + boot_page_erase(page); + boot_spm_busy_wait(); + for (uint16_t i = 0; i < SPM_PAGESIZE; i += 2) { + uint16_t w = *buf++; + w += (*buf++) << 8; + boot_page_fill(page + i, w); + } + boot_page_write(page); + boot_spm_busy_wait(); + boot_rww_enable(); + SREG = sreg; +} + +static boolean sendWrite(MyMessage message) { + return write(nc.parentNodeId, message.array, HEADER_SIZE + mGetLength(message), (message.destination == BROADCAST_ADDRESS)); +} + +static uint8_t sendAndWait(uint8_t reqType, uint8_t resType) { + msg.type = reqType; + for (uint8_t i = 0; i < 10; i++) { + sendWrite(msg); + for (uint16_t j = 0; j < 20; j++) { + wdt_reset(); + for (uint16_t j = 0; j < 100; j++) { + wdt_reset(); + uint8_t pipe; + boolean avail = available(&pipe); + if (avail && pipe<=6) { + read(rmsg.array,pipe); + if(!(mGetVersion(rmsg) == PROTOCOL_VERSION)) + continue; + if (rmsg.destination == nc.nodeId) { + if (mGetCommand(rmsg) == C_INTERNAL) { + if (rmsg.type == I_PING_ACK) { + if (rmsg.data[0] < nc.distance - 1) { + nc.distance = rmsg.data[0] + 1; + nc.parentNodeId = rmsg.sender; + eeprom_write_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId); + eeprom_write_byte((uint8_t*)EEPROM_DISTANCE_ADDRESS, nc.distance); + } + } + } + if ((mGetCommand(rmsg) == mGetCommand(msg)) && (rmsg.type == resType)) + return 1; + } + } + delaym(1); + } + } + } + return 0; +} + +int main () { + asm volatile ("clr __zero_reg__"); + // switch to 4 MHz + orgClockDiv = clock_prescale_get(); + clock_prescale_set(F_CPU_DIV); + MCUSR = 0; + // enable watchdog to avoid deadlock + wdt_enable(WDTO_8S); + +#ifdef LED_DEBUG + // enable LEDs for debugging and blink once as visual "bootloader started" sign + led_init(); + blink(LED_MBOTH, 250); +#endif +#ifdef UART_DEBUG + // enable UART for debugging and send start message + uart_init(); + uart_puts("Go\n"); +#endif + + wdt_reset(); + // initialize RF module + begin(); + wdt_reset(); + // Read settings from EEPROM + eeprom_read_block((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(struct NodeConfig)); + wdt_reset(); + + msg.sender = nc.nodeId; + msg.last = nc.nodeId; + address(nc.nodeId); + + msg.sensor = NODE_SENSOR_ID; + mSetLength(msg, 0); + mSetPayloadType(msg, P_STRING); + mSetAck(msg,false); + mSetVersion(msg, PROTOCOL_VERSION); + + nc.distance = 255; + mSetCommand(msg, C_INTERNAL); + msg.destination = BROADCAST_ADDRESS; + if (!sendAndWait(I_PING, I_PING_ACK)) +// starting existing firmware if no ping response (if firmware is valid) +// reboot(); + startup(); + + msg.destination = GATEWAY_ADDRESS; + + if (nc.nodeId == AUTO) { + openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(nc.nodeId)); + if (!sendAndWait(I_ID_REQUEST, I_ID_RESPONSE)) + reboot(); + if (mGetPayloadType(rmsg) == P_BYTE) + nc.nodeId = rmsg.data[0]; + else if (mGetPayloadType(rmsg) == P_STRING) + nc.nodeId = atoi(rmsg.data); + if (nc.nodeId == AUTO) + reboot(); + eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, nc.nodeId); + msg.sender = nc.nodeId; + msg.last = nc.nodeId; + address(nc.nodeId); + } + + // Read settings from EEPROM + eeprom_read_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig)); + + mSetPayloadType(msg,P_CUSTOM); + + FirmwareConfigRequest *firmwareConfigRequest = (FirmwareConfigRequest *)msg.data; + mSetLength(msg, sizeof(FirmwareConfigRequest)); + mSetCommand(msg, C_STREAM); + firmwareConfigRequest->type = fc.type; + firmwareConfigRequest->version = fc.version; + if (!sendAndWait(ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE)) +// starting existing firmware if no firmware config response (if firmware is valid) +// reboot(); + startup(); + FirmwareConfigResponse *firmwareConfigResponse = (FirmwareConfigResponse *)rmsg.data; + if (firmwareConfigResponse->version == fc.version) + if (firmwareConfigResponse->blocks == fc.blocks) + if (firmwareConfigResponse->crc == fc.crc) + if (validFirmware()) + startup(); + fc.type = firmwareConfigResponse->type; + fc.version = firmwareConfigResponse->version; + fc.blocks = firmwareConfigResponse->blocks; + fc.crc = firmwareConfigResponse->crc; + + FirmwareRequest *firmwareRequest = (FirmwareRequest *)msg.data; + mSetLength(msg, sizeof(FirmwareRequest)); + firmwareRequest->type = fc.type; + firmwareRequest->version = fc.version; + for (uint16_t block = 0; block < fc.blocks; block++) { + firmwareRequest->block = block; + if (!sendAndWait(ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE)) + reboot(); + FirmwareResponse *firmwareResponse = (FirmwareResponse *)rmsg.data; + uint8_t offset = (block * FIRMWARE_BLOCK_SIZE) % SPM_PAGESIZE; + memcpy(progBuf + offset, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); + if (offset == SPM_PAGESIZE - FIRMWARE_BLOCK_SIZE) + boot_program_page((block * FIRMWARE_BLOCK_SIZE) - offset, progBuf); + } + + wdt_reset(); + + if (validFirmware()) { + eeprom_write_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig)); +#ifdef UART_DEBUG + uart_puts("fw ok\n"); + } else { + uart_puts("fw nok\n"); +#endif + } + + reboot(); +} diff --git a/Bootloader/MyOtaBootloader.h b/Bootloader/MyOtaBootloader.h new file mode 100644 index 0000000..d906370 --- /dev/null +++ b/Bootloader/MyOtaBootloader.h @@ -0,0 +1,67 @@ +#ifndef MyOtaBootloader_H +#define MyOtaBootloader_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MyMessage.h" +#include "MySensor.h" +#include "MyOtaBootloaderRF24.h" + +#define FIRMWARE_BLOCK_SIZE 16 + +struct FirmwareConfig +{ + uint16_t type; + uint16_t version; + uint16_t blocks; + uint16_t crc; +}; + +typedef struct +{ + uint16_t type; + uint16_t version; +} FirmwareConfigRequest; + +typedef struct +{ + uint16_t type; + uint16_t version; + uint16_t blocks; + uint16_t crc; +} FirmwareConfigResponse; + +typedef struct +{ + uint16_t type; + uint16_t version; + uint16_t block; +} FirmwareRequest; + +typedef struct +{ + uint16_t type; + uint16_t version; + uint16_t block; + uint8_t data[FIRMWARE_BLOCK_SIZE]; +} FirmwareResponse; + +static struct NodeConfig nc; +static struct FirmwareConfig fc; +static MyMessage msg; +static MyMessage rmsg; + +static clock_div_t orgClockDiv = 0; + +static uint8_t progBuf[SPM_PAGESIZE]; + +#endif // MyOtaBootloader_H diff --git a/Bootloader/MyOtaBootloaderHW.h b/Bootloader/MyOtaBootloaderHW.h new file mode 100644 index 0000000..2eec57b --- /dev/null +++ b/Bootloader/MyOtaBootloaderHW.h @@ -0,0 +1,154 @@ +#ifndef MyOtaBootloaderHW_H +#define MyOtaBootloaderHW_H + +#include +#include + +//#define LED_DEBUG +//#define UART_DEBUG + +// hardware +// ******** + +#define F_CPU_DIV clock_div_4 +#define F_CPU_REAL F_CPU / (1 << F_CPU_DIV) +#define UART_BAUD 9600UL +#define DELAY_M 125 * (1 << F_CPU_DIV) + +// boolean definition +// ****************** + +typedef uint8_t bool; +typedef uint8_t boolean; +#define false 0x0 +#define true 0x1 +#define LOW 0x0 +#define HIGH 0x1 + +// delay +// ***** + +static void delayu() { + asm("nop"); +} + +static void delaym(uint16_t t) { + uint16_t d, a; + for (d = 0; d < t; d++) + for (a = 0; a < DELAY_M; a++) + asm("nop"); +} + +// LED debug +// ********* + +#ifdef LED_DEBUG +#define LED_DDR DDRD +#define LED_PORT PORTD +#define LED_RED 6 // Arduino Pin 6 <-> Bit 6 of port D +#define LED_GREEN 7 // Arduino Pin 7 <-> Bit 7 of port D +#define LED_MRED (1 << LED_RED) +#define LED_MGREEN (1 << LED_GREEN) +#define LED_MBOTH (LED_MRED | LED_MGREEN) + +static void led_init() { + LED_DDR |= LED_MBOTH; + LED_PORT &= ~LED_MBOTH; +} + +static void blink(uint8_t mask, uint16_t time) { + LED_PORT |= mask; + if (time > 0) + { + delaym(time); + LED_PORT &= ~mask; + delaym(time); + } +} +#endif + +// UART debug +// ********** + +#ifdef UART_DEBUG +static void uart_init() +{ + UCSR0A = _BV(U2X0); //Double speed mode USART0 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + UBRR0L = (uint8_t)( (F_CPU_REAL + UART_BAUD * 4L) / (UART_BAUD * 8L) - 1 ); +} + +static void uart_putc(char ch) { + while (!(UCSR0A & _BV(UDRE0))); + UDR0 = ch; +} + +static void uart_puts(char *s) +{ + while (*s) + uart_putc(*s++); +} + +static void uart_puti(uint8_t i) +{ + char s[5]; + itoa( i, s, 10 ); + uart_puts( s ); +} +#endif + +// SPI communication +// ***************** + +#define SPI_DDR DDRB +#define SPI_PORT PORTB +#define SPI_PIN PINB +#define SPI_SCLK 5 // Arduino Pin 13 <-> Bit 5 of port B +#define SPI_MISO 4 // Arduino Pin 12 <-> Bit 4 of port B +#define SPI_MOSI 3 // Arduino Pin 11 <-> Bit 3 of port B +#define SPI_CSN 2 // Arduino Pin 10 <-> Bit 2 of port B +#define SPI_CE 1 // Arduino Pin 9 <-> Bit 1 of port B + +#define csnlow() SPI_PORT &= ~(1<> SPI_MISO) & 0x01); // capture current MISO bit + delayu(); + SPI_PORT &= ~(1 << SPI_SCLK); + delayu(); + } + return value; +} + +static uint8_t spiTrans(uint8_t cmd){ + uint8_t status; + csnlow(); + status = SPItransfer( cmd ); + csnhigh(); + return status; +} + +#endif // MyOtaBootloaderHW_H diff --git a/Bootloader/MyOtaBootloaderRF24.h b/Bootloader/MyOtaBootloaderRF24.h new file mode 100644 index 0000000..fa2495c --- /dev/null +++ b/Bootloader/MyOtaBootloaderRF24.h @@ -0,0 +1,253 @@ +#ifndef MyOtaBootloaderRF24_H +#define MyOtaBootloaderRF24_H + +#include "MyOtaBootloaderHW.h" +#include "../libraries/MySensors/utility/nRF24L01.h" + +#include + +// hardware-agnostic interface to transceiver +// ****************************************** +// static void begin() +// static void address(uint8_t addr) +// static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast) +// static bool available(uint8_t* pipe_num) +// static void read(uint8_t* buf, uint8_t pipe) + +typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ; +typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e; + +uint64_t pipe0_reading_address; /**< Last address set on pipe 0 for reading. */ + +static uint8_t read_register(uint8_t reg) +{ + csnlow(); + SPItransfer( R_REGISTER | ( REGISTER_MASK & reg ) ); + uint8_t result = SPItransfer(0xff); + csnhigh(); + return result; +} + +static uint8_t write_registers(uint8_t reg, const uint8_t* buf, uint8_t len) +{ + uint8_t status; + csnlow(); + status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ) + SPItransfer(*buf++); + csnhigh(); + return status; +} + +static uint8_t write_register(uint8_t reg, uint8_t value) +{ + uint8_t status; + csnlow(); + status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + SPItransfer(value); + csnhigh(); + return status; +} + +static uint8_t read_payload(uint8_t* buf, uint8_t data_len) +{ +#ifdef UART_DEBUG + uart_puts("-> "); +#endif + uint8_t status; + uint8_t* current = buf; + csnlow(); + status = SPItransfer( R_RX_PAYLOAD ); + while ( data_len-- ) { + *current = SPItransfer(0xFF); +#ifdef UART_DEBUG + uart_puti(*current); + uart_putc(','); +#endif + current++; + } + csnhigh(); +#ifdef UART_DEBUG + uart_putc('\n'); +#endif + return status; +} + +#define get_status() spiTrans(NOP) + +static void powerUp(void) +{ + if (!(read_register(CONFIG) & _BV(PWR_UP))){ + write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP)); + delaym(5); + } +} + +#define convert_64_bit_to_byte_array(value, data) ((*(uint64_t *)(data)) = (uint64_t)(value)) + +static void startListening(void) +{ + powerUp(); + write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX)); + write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + if (pipe0_reading_address){ + uint8_t addressa[8]; + convert_64_bit_to_byte_array(pipe0_reading_address, addressa); + write_registers(RX_ADDR_P0, addressa, 5); + } + spiTrans(FLUSH_RX); + spiTrans(FLUSH_TX); + cehigh(); +} + +static void stopListening(void) +{ + celow(); + spiTrans(FLUSH_TX); + spiTrans(FLUSH_RX); + write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX)); +} + +static void write_payload(const uint8_t* buf, uint8_t data_len, const uint8_t writeType) +{ +#ifdef UART_DEBUG + uart_puts("<- "); +#endif + const uint8_t* current = buf; + csnlow(); + SPItransfer(writeType); + while ( data_len-- ) { +#ifdef UART_DEBUG + uart_puti(*current); + uart_putc(','); +#endif + SPItransfer(*current++); + } + csnhigh(); +#ifdef UART_DEBUG + uart_putc('\n'); +#endif +} + +static bool writem( const uint8_t* buf, uint8_t len, const bool multicast ) +{ + write_payload( buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD) ; + cehigh(); + celow(); + while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { } + uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + if( status & _BV(MAX_RT)){ + spiTrans(FLUSH_TX); + return 0; + } + return 1; +} + +static uint8_t getDynamicPayloadSize(void) +{ + uint8_t result = 0; + csnlow(); + SPItransfer( R_RX_PL_WID ); + result = SPItransfer(0xff); + csnhigh(); + if(result > 32) { + spiTrans(FLUSH_RX); + return 0; + } + return result; +} + +static bool available(uint8_t* pipe_num) +{ + if (!(read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){ + if (pipe_num) { + uint8_t status = get_status(); + *pipe_num = ( status >> RX_P_NO ) & 0b111; + } + return 1; + } + return 0; +} + +static void writeAckPayload(uint8_t pipe, const uint8_t* buf, uint8_t len) +{ + const uint8_t* current = buf; + uint8_t data_len = len; + csnlow(); + SPItransfer(W_ACK_PAYLOAD | ( pipe & 0b111 ) ); + while ( data_len-- ) + SPItransfer(*current++); + csnhigh(); +} + +static void read( uint8_t* buf, uint8_t pipe ){ + read_payload(buf, getDynamicPayloadSize()); + write_register(STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS)); + writeAckPayload(pipe,&pipe, 1 ); +} + +static void openWritingPipe(uint64_t value) +{ + uint8_t valuea[8]; + convert_64_bit_to_byte_array(value, valuea); + write_registers(RX_ADDR_P0, valuea, 5); + write_registers(TX_ADDR, valuea, 5); +} + +static void openReadingPipe(uint8_t child, uint64_t address) +{ + if (child == 0) + pipe0_reading_address = address; + uint8_t addressa[8]; + convert_64_bit_to_byte_array(address, addressa); + if ( child < 2 ) + write_registers(RX_ADDR_P0 + child, addressa, 5); + write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(ERX_P0 + child)); +} + +static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast) { + powerUp(); + stopListening(); + openWritingPipe(TO_ADDR(next)); + bool ok = writem(packet, length, multicast); + startListening(); + return ok; +} + +static void address(uint8_t addr) +{ + if (addr != BROADCAST_ADDRESS) { + openReadingPipe(WRITE_PIPE, TO_ADDR(addr)); + openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(addr)); + } +} + +static void begin(void) +{ + pipe0_reading_address = 0; + + SPIinit(); + delaym( 10 ) ; + + write_register(SETUP_RETR, 5 << ARD | 15 << ARC); + write_register(EN_AA, 0b00111111 & ~_BV(BROADCAST_PIPE)) ; + write_register(RF_CH, RF24_CHANNEL); + write_register(RF_SETUP, (read_register(RF_SETUP) & 0b11010000) | ((RF24_PA_LEVEL << 1) + 1) | ((RF24_DATARATE & 0b00000010 ) << 4) | ((RF24_DATARATE & 0b00000001 ) << 3)); + write_register(CONFIG, read_register(CONFIG) | _BV(CRCO) | _BV(EN_CRC)) ; + write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT)); + + csnlow(); + SPItransfer(ACTIVATE); + SPItransfer(0x73); + csnhigh(); + write_register(FEATURE, read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) ); + write_register(DYNPD, read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0)); + + spiTrans(FLUSH_RX); + spiTrans(FLUSH_TX); + + powerUp(); //Power up by default when begin() is called + write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX)); + openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); +} +#endif // MyOtaBootloaderRF24_H diff --git a/libraries/MySensors/MyMessage.h b/libraries/MySensors/MyMessage.h index d8df627..ae52f46 100644 --- a/libraries/MySensors/MyMessage.h +++ b/libraries/MySensors/MyMessage.h @@ -12,9 +12,11 @@ #ifndef MyMessage_h #define MyMessage_h -#include +#ifdef __cplusplus +#include #include #include +#endif #define PROTOCOL_VERSION 2 #define MAX_MESSAGE_LENGTH 32 @@ -56,7 +58,8 @@ typedef enum { // Type of data stream (for streamed message) typedef enum { - ST_FIRMWARE, ST_SOUND, ST_IMAGE + ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE, ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE, + ST_SOUND, ST_IMAGE } stream; typedef enum { @@ -101,7 +104,7 @@ typedef enum { #define miSetLength(_length) BF_SET(version_length, _length, 3, 5) #define miSetPayloadType(_pt) BF_SET(command_ack_payload, _pt, 4, 4) - +#ifdef __cplusplus class MyMessage { public: @@ -144,6 +147,13 @@ public: MyMessage& set(unsigned int value); MyMessage& set(int value); +#else + +typedef union { +struct +{ + +#endif uint8_t version_length; // 3 bit - Protocol version // 5 bit - Length of payload @@ -167,6 +177,12 @@ public: int iValue; char data[MAX_PAYLOAD + 1]; } __attribute__((packed)); +#ifdef __cplusplus } __attribute__((packed)); +#else +}; +uint8_t array[HEADER_SIZE + MAX_PAYLOAD + 1]; +} __attribute__((packed)) MyMessage; +#endif #endif diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 5f81727..b11d787 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -15,16 +15,19 @@ #include "Version.h" // Auto generated by bot #include "MyConfig.h" #include "MyMessage.h" -#include #include -#include #include #include #include #include + +#ifdef __cplusplus +#include +#include #include "utility/LowPower.h" #include "utility/RF24.h" #include "utility/RF24_config.h" +#endif #ifdef DEBUG #define debug(x,...) debugPrint(x, ##__VA_ARGS__) @@ -47,7 +50,11 @@ #define EEPROM_DISTANCE_ADDRESS (EEPROM_PARENT_NODE_ID_ADDRESS+1) #define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS+1) // Where to start storing routing information in EEPROM. Will allocate 256 bytes. #define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS+256) // Location of controller sent configuration (we allow one payload of config data from controller) -#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24) // First free address for sketch static configuration +#define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24) +#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS+2) +#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2) +#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2) +#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) // First free address for sketch static configuration // This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data). // This is also act as base value for sensor nodeId @@ -74,8 +81,7 @@ struct ControllerConfig { uint8_t isMetric; }; - - +#ifdef __cplusplus class MySensor : public RF24 { public: @@ -267,5 +273,6 @@ class MySensor : public RF24 void removeChildRoute(uint8_t childId); void internalSleep(int ms); }; +#endif #endif