Added project
This commit is contained in:
parent
fe9aa14dfd
commit
2d73cc8845
186 changed files with 21174 additions and 0 deletions
248
lib/isp-repair/MegaIspRepair.cpp
Normal file
248
lib/isp-repair/MegaIspRepair.cpp
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Reflash a boot loader and a sketch an a second ATmega.
|
||||
* MegaIspRepair
|
||||
* 2014, Jan 21 <w.cazander@gmail.com> Rewrote to class and converted to boot pair with lcd.
|
||||
* IspRepair
|
||||
* 2010-05-29 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
|
||||
* BootCloner
|
||||
* adapted from http://www.arduino.cc/playground/BootCloner/BootCloner
|
||||
* original copyright notice: 2007 by Amplificar <mailto:amplificar@gmail.com>
|
||||
*/
|
||||
|
||||
#include <MegaIspRepair.h>
|
||||
#include <MegaIspRepairConfig.h>
|
||||
|
||||
bool fastSPI = false; // don't start in fast mode right away
|
||||
|
||||
// transfer a byte using software SPI, using a faster mode when possible
|
||||
byte MegaIspRepair::XferByte(byte v) {
|
||||
byte result = 0;
|
||||
if (fastSPI)
|
||||
for (byte i = 0; i < 8; ++i) {
|
||||
bitWrite(PORTC, 3, v & 0x80);
|
||||
v <<= 1;
|
||||
bitClear(PORTC, 0);
|
||||
result <<= 1;
|
||||
bitSet(PORTC, 0);
|
||||
result |= bitRead(PIND, 4);
|
||||
}
|
||||
else
|
||||
for (byte i = 0; i < 8; ++i) {
|
||||
digitalWrite(PIN_MOSI, v & 0x80);
|
||||
digitalWrite(PIN_SCK, 0); // slow pulse, max 60KHz
|
||||
digitalWrite(PIN_SCK, 1);
|
||||
v <<= 1;
|
||||
result = (result << 1) | digitalRead(PIN_MISO);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// send 4 bytes to target microcontroller, returns the fourth MISO byte
|
||||
byte MegaIspRepair::Send_ISP(word v01, byte v2, byte v3) {
|
||||
XferByte(v01 >> 8);
|
||||
XferByte(v01);
|
||||
XferByte(v2);
|
||||
return XferByte(v3);
|
||||
}
|
||||
|
||||
// send 4 bytes to target microcontroller and wait for completion
|
||||
void MegaIspRepair::Send_ISP_wait(word v01, byte v2, byte v3) {
|
||||
Send_ISP(v01, v2, v3);
|
||||
while (Send_ISP(CMD_Poll) & 1)
|
||||
;
|
||||
}
|
||||
|
||||
// reset the target microcontroller
|
||||
void MegaIspRepair::Reset_Target() {
|
||||
digitalWrite(RESET, 1);
|
||||
digitalWrite(PIN_SCK, 0); // has to be set LOW at startup, or PE fails
|
||||
delay(30);
|
||||
digitalWrite(RESET, 0);
|
||||
delay(30); // minimum delay here is 20ms for the ATmega8
|
||||
}
|
||||
|
||||
// print the 16 signature bytes (device codes)
|
||||
void MegaIspRepair::Read_Signature() {
|
||||
Serial.print("Signatures:");
|
||||
for (byte x = 0; x < 8; ++x) {
|
||||
Serial.print(" ");
|
||||
Serial.print(Send_ISP(CMD_Read_Signature, x), HEX);
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
// prints the lock and fuse bits (no leading zeros)
|
||||
byte MegaIspRepair::Read_Fuses(byte flo, byte fhi) {
|
||||
Serial.print("Lock Bits: ");
|
||||
Serial.println(Send_ISP(CMD_Read_Lock), HEX);
|
||||
Serial.print("Fuses: low ");
|
||||
Serial.print(Send_ISP(CMD_Read_Fuse_Low), HEX);
|
||||
Serial.print(", high ");
|
||||
Serial.print(Send_ISP(CMD_Read_Fuse_High), HEX);
|
||||
Serial.print(", extended ");
|
||||
Serial.println(Send_ISP(CMD_Read_Fuse_Extended), HEX);
|
||||
return Send_ISP(CMD_Read_Lock) == LOCK_BITS && Send_ISP(CMD_Read_Fuse_Low) == flo && Send_ISP(CMD_Read_Fuse_High) == fhi && Send_ISP(CMD_Read_Fuse_Extended) == FUSE_EXTENDED;
|
||||
}
|
||||
|
||||
word MegaIspRepair::addr2page(word addr) {
|
||||
return (word)(addr & ~(PAGE_BYTES - 1)) >> 1;
|
||||
}
|
||||
|
||||
void MegaIspRepair::LoadPage(word addr, const byte* ptr) {
|
||||
word cmd = addr & 1 ? CMD_Load_Page_High : CMD_Load_Page_Low;
|
||||
Send_ISP(cmd | (addr >> 9), addr >> 1, pgm_read_byte(ptr));
|
||||
}
|
||||
|
||||
void MegaIspRepair::WritePage(word page) {
|
||||
Send_ISP_wait(CMD_Write_Page | (page >> 8), page);
|
||||
}
|
||||
|
||||
void MegaIspRepair::WriteData(word start, const byte* data, word count) {
|
||||
word page = addr2page(start);
|
||||
for (word i = 0; i < count; i += 2) {
|
||||
if (page != addr2page(start)) {
|
||||
WritePage(page);
|
||||
Serial.print('.');
|
||||
page = addr2page(start);
|
||||
}
|
||||
LoadPage(start++, data + i);
|
||||
LoadPage(start++, data + i + 1);
|
||||
}
|
||||
WritePage(page);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
byte MegaIspRepair::EnableProgramming() {
|
||||
Reset_Target();
|
||||
if (Send_ISP(CMD_Program_Enable, 0x22, 0x22) != 0x22) {
|
||||
Serial.println("Program Enable FAILED");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MegaIspRepair::blink() {
|
||||
pinMode(DONE_LED, OUTPUT);
|
||||
digitalWrite(DONE_LED, 0); // inverted logic
|
||||
delay(100); // blink briefly
|
||||
pinMode(DONE_LED, INPUT);
|
||||
}
|
||||
|
||||
byte MegaIspRepair::readConfig() {
|
||||
static byte pins[] = { CONFIG1, CONFIG2, CONFIG3, CONFIG4 };
|
||||
byte switches = 0;
|
||||
for (byte i = 0; i < 4; ++i) {
|
||||
pinMode(pins[i], INPUT);
|
||||
digitalWrite(pins[i], 1); // enable pull-up
|
||||
bitWrite(switches, i, digitalRead(pins[i]));
|
||||
digitalWrite(pins[i], 0); // disable pull-up
|
||||
}
|
||||
return switches; // a 4-bit value, i.e. 0..15
|
||||
}
|
||||
|
||||
byte MegaIspRepair::programSection(byte index, mega_flash_data_struct sections[]) {
|
||||
Serial.print(index, DEC);
|
||||
byte f = EnableProgramming();
|
||||
if (f) {
|
||||
fastSPI = FAST_SPI && PIN_SCK == 14 && PIN_MISO == 4 && PIN_MOSI == 17;
|
||||
WriteData(sections[index].start, sections[index].progdata + sections[index].off, sections[index].count);
|
||||
fastSPI = false;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void MegaIspRepair::run(const char* typeTitle, mega_flash_data_struct sections[]) {
|
||||
Serial.begin(57600);
|
||||
Serial.println();
|
||||
Serial.println("# Booting mega_isp_repair");
|
||||
Serial.println("# Version=3.0");
|
||||
Serial.print("# Type=");
|
||||
Serial.print(typeTitle);
|
||||
Serial.println();
|
||||
blink();
|
||||
|
||||
digitalWrite(PIN_SCK, 1);
|
||||
digitalWrite(PIN_MOSI, 1);
|
||||
digitalWrite(RESET, 1);
|
||||
|
||||
pinMode(PIN_SCK, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(RESET, OUTPUT);
|
||||
|
||||
byte config = readConfig();
|
||||
byte xspeed = 0;
|
||||
|
||||
// Always burn a boot pair
|
||||
byte bootld = (config * 2) + 0;
|
||||
byte sketch = (config * 2) + 1;
|
||||
|
||||
Serial.print("Configuration: ");
|
||||
Serial.print(config, HEX);
|
||||
Serial.println(xspeed ? " (resonator)" : " (crystal)");
|
||||
Serial.println();
|
||||
Serial.println(sections[sketch].title);
|
||||
Serial.println(sections[bootld].title);
|
||||
Serial.println();
|
||||
|
||||
if (EnableProgramming()) {
|
||||
Serial.println("Erasing Flash");
|
||||
Send_ISP_wait(CMD_Erase_Flash, 0x22, 0x22);
|
||||
|
||||
if (EnableProgramming()) {
|
||||
byte fuseLo = xspeed ? FUSE_LOW_FAST : FUSE_LOW_XTAL;
|
||||
// derive the boot size from its starting address
|
||||
byte fuseHi = FUSE_HIGH_2048;
|
||||
switch (sections[bootld].start & 0x0FFF) {
|
||||
case 0x0E00:
|
||||
fuseHi = FUSE_HIGH_512;
|
||||
break;
|
||||
case 0x0C00:
|
||||
fuseHi = FUSE_HIGH_1024;
|
||||
break;
|
||||
case 0x0800:
|
||||
fuseHi = FUSE_HIGH_2048;
|
||||
break;
|
||||
case 0x0000:
|
||||
fuseHi = FUSE_HIGH_4096;
|
||||
break;
|
||||
}
|
||||
|
||||
// set the fuses and lock bits
|
||||
Serial.println("Setting Fuses");
|
||||
Send_ISP_wait(CMD_Write_Fuse_Low, 0, fuseLo);
|
||||
Send_ISP_wait(CMD_Write_Fuse_High, 0, fuseHi);
|
||||
Send_ISP_wait(CMD_Write_Fuse_Extended, 0, FUSE_EXTENDED);
|
||||
Send_ISP_wait(CMD_Write_Lock, 0, LOCK_BITS);
|
||||
|
||||
// burn the sketch and bootstrap code
|
||||
if (programSection(sketch, sections) && programSection(bootld, sections)) {
|
||||
Read_Signature();
|
||||
if (Read_Fuses(fuseLo, fuseHi)) {
|
||||
Serial.println("\nDone.");
|
||||
blink();
|
||||
} else
|
||||
Serial.println("Fuses NOT OK!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pinMode(PIN_SCK, INPUT);
|
||||
pinMode(PIN_MOSI, INPUT);
|
||||
pinMode(RESET, INPUT);
|
||||
|
||||
digitalWrite(PIN_SCK, 0);
|
||||
digitalWrite(PIN_MOSI, 0);
|
||||
digitalWrite(RESET, 0);
|
||||
|
||||
#if ARDUINO >= 100
|
||||
Serial.flush();
|
||||
#endif
|
||||
delay(10); // let the serial port finish
|
||||
cli(); // stop responding to interrupts
|
||||
ADCSRA &= ~bit(ADEN); // disable the ADC
|
||||
//PRR = 0xFF; // disable all subsystems
|
||||
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
|
||||
sleep_mode();
|
||||
// total power down, can only wake up with a hardware reset
|
||||
}
|
||||
|
||||
39
lib/isp-repair/MegaIspRepair.h
Normal file
39
lib/isp-repair/MegaIspRepair.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef IspRepair_h
|
||||
#define IspRepair_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
const char* title;
|
||||
const char* mdate;
|
||||
const unsigned char* progdata;
|
||||
unsigned start;
|
||||
unsigned off;
|
||||
unsigned count;
|
||||
} mega_flash_data_struct;
|
||||
|
||||
class MegaIspRepair {
|
||||
private:
|
||||
static byte XferByte(byte v);
|
||||
static byte Send_ISP(word v01, byte v2 = 0, byte v3 = 0);
|
||||
static void Send_ISP_wait(word v01, byte v2 = 0, byte v3 = 0);
|
||||
static void Reset_Target();
|
||||
static void Read_Signature();
|
||||
static byte Read_Fuses(byte flo, byte fhi);
|
||||
static word addr2page(word addr);
|
||||
static void LoadPage(word addr, const byte* ptr);
|
||||
static void WritePage(word page);
|
||||
static void WriteData(word start, const byte* data, word count);
|
||||
static byte EnableProgramming();
|
||||
static void blink();
|
||||
static byte readConfig();
|
||||
static byte programSection(byte index, mega_flash_data_struct sections[]);
|
||||
public:
|
||||
void run(const char* typeTitle, mega_flash_data_struct sections[]);
|
||||
};
|
||||
|
||||
#endif
|
||||
49
lib/isp-repair/MegaIspRepairConfig.h
Normal file
49
lib/isp-repair/MegaIspRepairConfig.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#define FAST_SPI 1 // comment out to revert to digitalWrite() calls
|
||||
|
||||
// pin definitions
|
||||
#define PIN_SCK 14 // PC0 - AIO1 - serial clock to target avr
|
||||
#define PIN_MISO 4 // PD4 - DIO1 - input from target avr
|
||||
#define PIN_MOSI 17 // PC3 - AIO4 - output to target avr
|
||||
#define RESET 7 // PD7 - DIO4 - reset pin of the target avr
|
||||
#define DONE_LED 9 // B1 - blue LED on JN USB, blinks on start and when ok
|
||||
|
||||
// pins used for the optional config switches
|
||||
#define CONFIG1 5 // DIO2
|
||||
#define CONFIG2 15 // AIO2
|
||||
#define CONFIG3 16 // AIO3
|
||||
#define CONFIG4 6 // DIO3
|
||||
|
||||
// MPU-specific values
|
||||
#define PAGE_BYTES 128 // ATmega168 and ATmega328
|
||||
#define LOCK_BITS 0xCF
|
||||
#define FUSE_LOW_XTAL 0xFF
|
||||
#define FUSE_LOW_FAST 0xDE
|
||||
#define FUSE_HIGH_512 0xDE
|
||||
#define FUSE_HIGH_1024 0xDC
|
||||
#define FUSE_HIGH_2048 0xDA
|
||||
#define FUSE_HIGH_4096 0xD8 // not in ATmega168
|
||||
#define FUSE_EXTENDED 0xFD
|
||||
|
||||
// ISP Command Words
|
||||
#define CMD_Program_Enable 0xAC53
|
||||
#define CMD_Erase_Flash 0xAC80
|
||||
#define CMD_Poll 0xF000
|
||||
#define CMD_Read_Flash_Low 0x2000
|
||||
#define CMD_Read_Flash_High 0x2800
|
||||
#define CMD_Load_Page_Low 0x4000
|
||||
#define CMD_Load_Page_High 0x4800
|
||||
#define CMD_Write_Page 0x4C00
|
||||
#define CMD_Read_EEPROM 0xA000
|
||||
#define CMD_Write_EEPROM 0xC000
|
||||
#define CMD_Read_Lock 0x5800
|
||||
#define CMD_Write_Lock 0xACE0
|
||||
#define CMD_Read_Signature 0x3000
|
||||
#define CMD_Write_Fuse_Low 0xACA0
|
||||
#define CMD_Write_Fuse_High 0xACA8
|
||||
#define CMD_Write_Fuse_Extended 0xACA4
|
||||
#define CMD_Read_Fuse_Low 0x5000
|
||||
#define CMD_Read_Fuse_High 0x5808
|
||||
#define CMD_Read_Fuse_Extended 0x5008
|
||||
#define CMD_Read_Fuse_High 0x5808
|
||||
#define CMD_Read_Calibration 0x3800
|
||||
|
||||
44
lib/isp-repair/readme.txt
Normal file
44
lib/isp-repair/readme.txt
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
// This code is adapted from isp_prepare. It omits the button and run LED,
|
||||
// and starts right away. To use, open a serial console and wait until done.
|
||||
//
|
||||
// The 6 ISP pins of the target board need to be connected to the board running
|
||||
// this sketch as follows (using Arduino pin naming):
|
||||
//
|
||||
// ISP pin 1 <-> digital 4 (MISO) ISP CONNECTOR
|
||||
// ISP pin 2 <-> VCC +---+---+
|
||||
// ISP pin 3 <-> analog 0 (SCK) | 1 | 2 |
|
||||
// ISP pin 4 <-> analog 3 (MOSI) | 3 | 4 |
|
||||
// ISP pin 5 <-> digital 7 (RESET) | 5 | 6 |
|
||||
// ISP pin 6 <-> ground +---+---+
|
||||
//
|
||||
// The same hookup, using JeeNode port/pin names:
|
||||
//
|
||||
// ISP pin 1 <-> DIO1
|
||||
// ISP pin 2 <-> +3V
|
||||
// ISP pin 3 <-> AIO1
|
||||
// ISP pin 4 <-> AIO4
|
||||
// ISP pin 5 <-> DIO4
|
||||
// ISP pin 6 <-> GND
|
||||
//
|
||||
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
/* Include code using a file generated in isp_prepare/ dir with this cmd:
|
||||
|
||||
./hex2c.tcl Blink.cpp.hex \
|
||||
RF12demo.cpp.hex \
|
||||
optiboot_atmega328.hex \
|
||||
ATmegaBOOT_168_atmega328.hex \
|
||||
optiboot_atmega328_1s.hex \
|
||||
optiboot_atmega328.hex >../isp_repair2/data.h
|
||||
|
||||
Code choices are fixed: section 0 is RF12demo, section 1 is blink
|
||||
Boot choices are entries 2..5 in the sections[] array in data.h
|
||||
*/
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
77
lib/xnode-shared/XnodeConstants.h
Normal file
77
lib/xnode-shared/XnodeConstants.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#ifndef XnodeBaseConstants_h
|
||||
#define XnodeBaseConstants_h
|
||||
|
||||
// Temp version here, todo move to makefile and use git --version
|
||||
#define XNODE_VERSION "1.3"
|
||||
|
||||
// Default serial baudrate for all devices
|
||||
#define SERIAL_SPEED 115200
|
||||
|
||||
// Default watchdog timeout
|
||||
#define WDT_TIMEOUT WDTO_8S
|
||||
|
||||
// RF Settings
|
||||
#define RF_BASE_NODE_ID 1
|
||||
#define RF_NETWORK_ID 98
|
||||
#define RF_FREQUENCY RF69_868MHZ
|
||||
#define RF_KEY_SIZE 16
|
||||
#define RF_KEY_FETCH_TIME 1000*5
|
||||
#define RF_KEY_ENCRYPT_TIME 1000*60*2
|
||||
#define RF_NO_DATA_FAIL_TIME RF_KEY_ENCRYPT_TIME*2
|
||||
|
||||
// Needed for total magic number free code
|
||||
#define ZERO 0
|
||||
#define ONE 1
|
||||
|
||||
// Net related sizes
|
||||
#define NET_BYTE_IP_SIZE 4
|
||||
#define NET_BYTE_MAC_SIZE 6
|
||||
#define NET_BYTE_NET_KEY_SIZE 16
|
||||
#define NET_BYTE_NET_ID_SIZE 6
|
||||
|
||||
// Net Xensit config
|
||||
//define NET_XNODE_HOST "xng.xensit.com" // XNodeGateway
|
||||
#define NET_XNODE_HOST "www.forwardfire.net"
|
||||
#define NET_XNODE_MAC_DEFAULT {0x74,0x69,0x69,0x4D,0x33,0xB1}
|
||||
#define NET_PING_BOOT_TIME 1000*3
|
||||
#define NET_PING_HOST_TIME 1000*60*90
|
||||
#define NET_DHCP_RETRY_TIME 1000*60*3
|
||||
#define NET_DNS_LOOKUP_TIME 1000*3600*1
|
||||
// TODO: make net time to secs as 1h is ~max for dns
|
||||
|
||||
// Net config for url; Input Xensit Node Version A
|
||||
#define NET_URL_POST "_a"
|
||||
#define NET_URL_PARA_POST_TYPE "pt="
|
||||
#define NET_URL_PARA_REQ_CNT "&rc="
|
||||
#define NET_URL_PARA_NET_ID "&ni="
|
||||
#define NET_URL_PARA_NODE_DATA "&nd="
|
||||
#define NET_URL_PARA_NODE_NUMBER "&nn="
|
||||
|
||||
// The different post types of the url
|
||||
#define NET_URL_PT_PING 'p'
|
||||
#define NET_URL_PT_INIT 'i'
|
||||
#define NET_URL_PT_DATA 'd'
|
||||
#define NET_URL_RESULT_OK 'X'
|
||||
|
||||
// Some characters for printing.
|
||||
#define CHAR_NEWLINE '\n'
|
||||
#define CHAR_SPACE ' '
|
||||
#define CHAR_DOT '.'
|
||||
#define CHAR_PROMT '$'
|
||||
#define CHAR_COMMENT '#'
|
||||
#define CHAR_EQUALS '='
|
||||
|
||||
// Full ascii messages
|
||||
#define MSG_RF_CHIP_INIT "Init radio"
|
||||
#define MSG_RF_CHIP_ERROR "ERR: No chip"
|
||||
#define MSG_RF_INFO_FREQ "rf_freq"
|
||||
#define MSG_RF_INFO_NETWORK "rf_network"
|
||||
#define MSG_RF_INFO_NODE "rf_node"
|
||||
#define MSG_RF_INFO_KEY "rf_key"
|
||||
#define MSG_RF_INFO_TX "rf_tx"
|
||||
#define MSG_RF_INFO_RX "rf_rx"
|
||||
#define MSG_RF_INFO_TXE "rf_txe"
|
||||
#define MSG_RF_INFO "rf_info"
|
||||
#define MSG_RF_ENCRYPT "rf_encrypt"
|
||||
|
||||
#endif
|
||||
38
lib/xnode-shared/XnodeProtocol.h
Normal file
38
lib/xnode-shared/XnodeProtocol.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef XnodeProtocol_h
|
||||
#define XnodeProtocol_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <XnodeConstants.h>
|
||||
|
||||
#define RF_STRUCT_SUPER_SIZE 52
|
||||
#define RF_STRUCT_FLASH_SIZE 32
|
||||
#define RF_STRUCT_CHAR_SIZE 48
|
||||
|
||||
enum RFMessageType {
|
||||
RF_MSG_NODE_INIT, // sat tx+rx init_t
|
||||
RF_MSG_NODE_FLASH, // sat tx+rx flash_t
|
||||
RF_MSG_NODE_COMMAND, // sat rx char_t
|
||||
RF_MSG_NODE_DATA // sat tx char_t
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
byte msg_type;
|
||||
byte msg_data[RF_STRUCT_SUPER_SIZE];
|
||||
} xp_super_t;
|
||||
|
||||
typedef struct {
|
||||
byte rf_key[RF_KEY_SIZE];
|
||||
byte node_id;
|
||||
} xp_msg_init_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t offset;
|
||||
byte flash_data[RF_STRUCT_FLASH_SIZE];
|
||||
} xp_msg_flash_t;
|
||||
|
||||
typedef struct {
|
||||
char char_data[RF_STRUCT_CHAR_SIZE];
|
||||
} xp_msg_char_t;
|
||||
|
||||
#endif
|
||||
|
||||
14
lib/xnode-shared/XnodeSatelliteConfig.h
Normal file
14
lib/xnode-shared/XnodeSatelliteConfig.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef XnodeSatelliteConfig_h
|
||||
#define XnodeSatelliteConfig_h
|
||||
|
||||
// Config data
|
||||
typedef struct {
|
||||
uint16_t eeprom_struct_size; // Config size changes it data defaults to zeros
|
||||
byte rf_key[RF_KEY_SIZE]; // rf key to encrypt radio
|
||||
byte node_id; // this node id to transmit to base
|
||||
unsigned long sys_boot; // boot counter
|
||||
|
||||
} xnode_satellite_config_t;
|
||||
|
||||
#endif
|
||||
|
||||
104
lib/xnode-shared/XnodeSerial.cpp
Normal file
104
lib/xnode-shared/XnodeSerial.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#include <XnodeSerial.h>
|
||||
|
||||
char cmd_buff[CMD_BUFF_SIZE];
|
||||
volatile uint8_t cmd_process = ONE;
|
||||
volatile uint8_t cmd_buff_idx = ZERO;
|
||||
XnodeSerial XSerial;
|
||||
|
||||
void XnodeSerial::begin() {
|
||||
Serial.begin(SERIAL_SPEED);
|
||||
print(CHAR_NEWLINE);
|
||||
}
|
||||
|
||||
void XnodeSerial::loop() {
|
||||
if (cmd_process == ZERO) {
|
||||
executeCommand(cmd_buff);
|
||||
cmd_process = ONE;
|
||||
}
|
||||
while (Serial.available() > ZERO) {
|
||||
processSerialByte(Serial.read());
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the cmd from a buffer
|
||||
void XnodeSerial::executeCommand(char* buff,bool echoBuff,bool echoPromt) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
Serial.print(F("#D XSerial.processCommand buff="));
|
||||
Serial.print(buff);
|
||||
Serial.print(F(",echoBuff="));
|
||||
Serial.print(echoBuff);
|
||||
Serial.print(F(",echoPromt="));
|
||||
Serial.print(echoPromt);
|
||||
Serial.println();
|
||||
#endif
|
||||
if (echoBuff) {
|
||||
printChar(buff);
|
||||
print(CHAR_NEWLINE);
|
||||
}
|
||||
if (buff[ZERO] > ZERO) {
|
||||
XSystem.executeCommand(buff); // exe cmd
|
||||
printChar(XSystem.replyBuffer); // print result or error
|
||||
}
|
||||
if (echoPromt) {
|
||||
printPromt();
|
||||
}
|
||||
}
|
||||
|
||||
void XnodeSerial::processSerialByte(uint8_t c) {
|
||||
if (c < 0x07 || c > 0x7E) {
|
||||
return; // only process ascii chars
|
||||
}
|
||||
if (cmd_process == ZERO) {
|
||||
return; // skip serial data
|
||||
}
|
||||
if (cmd_buff_idx > CMD_BUFF_SIZE) {
|
||||
cmd_buff_idx = ZERO; // protect against to long input
|
||||
}
|
||||
if (c == '\b') {
|
||||
cmd_buff[cmd_buff_idx] = '\0'; // backspace
|
||||
cmd_buff_idx--;
|
||||
print(' ');
|
||||
print(c); // reply the backspace char for console like experience
|
||||
} else if (c == '\n') {
|
||||
cmd_buff[cmd_buff_idx] = '\0'; // newline
|
||||
cmd_buff_idx = ZERO;
|
||||
cmd_process = ZERO; // Start processing line
|
||||
} else {
|
||||
cmd_buff[cmd_buff_idx] = c; // store in buffer
|
||||
cmd_buff_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void XnodeSerial::executeCommandP(const char* cmd) {
|
||||
strcpy(cmd_buff, XUtil.UNPSTR(cmd)); // free buffer as gets used in strcmpP again..
|
||||
cmd_buff_idx = ZERO;
|
||||
executeCommand(cmd_buff,false,false);
|
||||
}
|
||||
|
||||
void XnodeSerial::printPromt() {
|
||||
printCharP(XSystem.hardware->getSystemHardwareTypeP());
|
||||
print(CHAR_PROMT);
|
||||
print(CHAR_SPACE);
|
||||
}
|
||||
|
||||
void XnodeSerial::printCommentLineP(const char* argu) {
|
||||
print(CHAR_COMMENT);
|
||||
print(CHAR_SPACE);
|
||||
printCharP(argu);
|
||||
print(CHAR_NEWLINE);
|
||||
}
|
||||
|
||||
void XnodeSerial::printCharP(const char* argu) {
|
||||
printChar(XUtil.UNPSTR(argu));
|
||||
}
|
||||
|
||||
void XnodeSerial::printChar(char* dstring) {
|
||||
while (*dstring != ZERO) {
|
||||
print(*dstring);
|
||||
dstring++;
|
||||
}
|
||||
}
|
||||
|
||||
void XnodeSerial::print(char value) {
|
||||
Serial.print(value);
|
||||
}
|
||||
32
lib/xnode-shared/XnodeSerial.h
Normal file
32
lib/xnode-shared/XnodeSerial.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef XnodeSerial_h
|
||||
#define XnodeSerial_h
|
||||
|
||||
#define CMD_BUFF_SIZE 40 // max command length (40 is rf_key=9A2EE3A293486E9FE73D77EFC8087D2F)
|
||||
|
||||
#include <XnodeSystemModule.h>
|
||||
#include <XnodeSystemHardware.h>
|
||||
#include <XnodeConstants.h>
|
||||
#include <XnodeUtil.h>
|
||||
#include <XnodeSystem.h>
|
||||
|
||||
class XnodeSerial {
|
||||
private:
|
||||
void executeCommand(char* buff,bool echoBuff = true,bool echoPromt = true);
|
||||
void processSerialByte(uint8_t c);
|
||||
|
||||
public:
|
||||
void begin();
|
||||
void loop();
|
||||
|
||||
void executeCommandP(const char* cmd);
|
||||
void printPromt();
|
||||
void printCommentLineP(const char* argu);
|
||||
void printCharP(const char* argu);
|
||||
void printChar(char* argu);
|
||||
void print(char value);
|
||||
};
|
||||
|
||||
extern XnodeSerial XSerial;
|
||||
|
||||
#endif
|
||||
|
||||
323
lib/xnode-shared/XnodeSystem.cpp
Normal file
323
lib/xnode-shared/XnodeSystem.cpp
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
#include <XnodeSystem.h>
|
||||
|
||||
#define CMD_MAX_ARGS 8 // max 8 arguments to command
|
||||
#define CMD_WHITE_SPACE " \r\t\n" // All diffent white space chars to split commands on
|
||||
|
||||
const char pmCmdHelp[] PROGMEM = "help";
|
||||
const char pmCmdReboot[] PROGMEM = "reboot";
|
||||
const char pmCmdSysCnfRst[] PROGMEM = "sys__cnf__rst"; // (internal)
|
||||
const char pmCmdSysInfo[] PROGMEM = "sys_info";
|
||||
|
||||
const char pmSysConfigSave[] PROGMEM = "Config saved";
|
||||
const char pmSysConfigLoad[] PROGMEM = "Config loaded";
|
||||
const char pmSysConfigReset[] PROGMEM = "Config reset";
|
||||
|
||||
const char pmSysInfoVNumber[] PROGMEM = "sys_vnum";
|
||||
const char pmSysInfoVDate[] PROGMEM = "sys_vdate";
|
||||
const char pmSysInfoVDateValue[] PROGMEM = __DATE__" "__TIME__; // Print compile date like; "Apr 22 2012 16:36:10"
|
||||
const char pmSysInfoType[] PROGMEM = "sys_type";
|
||||
const char pmSysInfoBoot[] PROGMEM = "sys_boot";
|
||||
const char pmSysInfoDebugLevel[] PROGMEM = "sys_debug";
|
||||
const char pmSysInfoFreeRam[] PROGMEM = "sys_sram";
|
||||
|
||||
const char pmSysBootDebugHeader[] PROGMEM = "==== DEBUGGING ENABLED ====";
|
||||
const char pmSysBootStart[] PROGMEM = "Booting ";
|
||||
const char pmSysBootDone[] PROGMEM = "boot done";
|
||||
const char pmSysBootDoneHelp[] PROGMEM = "Available commands;";
|
||||
|
||||
const char pmCmdErrArgument[] PROGMEM = "#ERR Missing argument: ";
|
||||
const char pmCmdErrUnknown[] PROGMEM = "#ERR Unknown command: ";
|
||||
|
||||
const char pmRemoteExecutePrefix[] PROGMEM = "remote@";
|
||||
|
||||
uint8_t reboot_requested = ZERO;
|
||||
uint8_t debug_level = ZERO;
|
||||
uint8_t replyBufferIndex = ZERO;
|
||||
uint8_t systemModuleIndex = ZERO;
|
||||
XnodeSystemModule* systemModules[SYSTEM_MODULE_ARRAY_SIZE];
|
||||
XnodeSystemHardware* hardware;
|
||||
XnodeSystem XSystem;
|
||||
|
||||
void XnodeSystem::begin(XnodeSystemHardware* hardwareNode) {
|
||||
hardware = hardwareNode;
|
||||
|
||||
// Print first line of boot process
|
||||
XSerial.print(CHAR_COMMENT);
|
||||
XSerial.print(CHAR_SPACE);
|
||||
XSerial.printCharP (pmSysBootStart); // has space
|
||||
XSerial.printCharP(hardware->getSystemHardwareTypeP());
|
||||
XSerial.print(CHAR_NEWLINE);
|
||||
|
||||
// Start debug asp
|
||||
beginDebug();
|
||||
|
||||
// Fixup config
|
||||
XSerial.printCommentLineP(pmSysConfigLoad);
|
||||
if (hardware->systemHardwareConfigBegin()) {
|
||||
hardware->systemHardwareConfigReset();
|
||||
XSerial.printCommentLineP(pmSysConfigReset);
|
||||
}
|
||||
hardware->systemHardwareConfigSave();
|
||||
|
||||
// Print system info
|
||||
XSerial.executeCommandP(pmCmdSysInfo);
|
||||
|
||||
// Enable the watchdog
|
||||
wdt_enable(WDT_TIMEOUT);
|
||||
}
|
||||
|
||||
void XnodeSystem::loop() {
|
||||
// Tickle the watchdog
|
||||
wdt_reset();
|
||||
|
||||
// Reboot countdown and action so reply can be send.
|
||||
if (reboot_requested > ONE) {
|
||||
reboot_requested--;
|
||||
} else if (reboot_requested > ZERO) {
|
||||
wdt_enable (WDTO_15MS); // reboot in 15ms.
|
||||
delay(30);
|
||||
}
|
||||
}
|
||||
|
||||
void XnodeSystem::beginDebug() {
|
||||
// Make sure human and machine are notified when debugging is turned on.
|
||||
#ifdef DEBUG_NETWORK
|
||||
// shift every flag on its on bit so machine can readout which flags is enabled.
|
||||
debug_level+=ONE << 0; // 1
|
||||
#endif
|
||||
#ifdef DEBUG_RADIO
|
||||
debug_level+=ONE << 1; // 2
|
||||
#endif
|
||||
#ifdef DEBUG_SYSTEM
|
||||
debug_level+=ONE << 2; // 4
|
||||
#endif
|
||||
#ifdef DEBUG_SERIAL
|
||||
debug_level+=ONE << 3; // 8
|
||||
#endif
|
||||
#ifdef DEBUG_SENSOR
|
||||
debug_level+=ONE << 4; // 16, all = 31
|
||||
#endif
|
||||
if (debug_level > ZERO) {
|
||||
XSerial.printCommentLineP(pmSysBootDebugHeader); // print line for human,machine version is in serialPrintInfo.
|
||||
}
|
||||
}
|
||||
|
||||
void XnodeSystem::bootDone() {
|
||||
XSerial.printCommentLineP(pmSysBootDoneHelp);
|
||||
XSerial.executeCommandP(pmCmdHelp);
|
||||
XSerial.printCommentLineP(pmSysBootDone);
|
||||
XSerial.printPromt();
|
||||
}
|
||||
|
||||
void XnodeSystem::configSave() {
|
||||
#ifdef DEBUG_SYSTEM
|
||||
Serial.println(F("#D XSystem.configSave"));
|
||||
#endif
|
||||
wdt_disable();
|
||||
hardware->systemHardwareConfigSave();
|
||||
wdt_enable (WDT_TIMEOUT);
|
||||
}
|
||||
|
||||
void XnodeSystem::cmdSysInfo() {
|
||||
buildReplyPValueP(pmSysInfoVNumber,hardware->getSystemHardwareVersionP());
|
||||
buildReplyPValueP(pmSysInfoVDate,pmSysInfoVDateValue);
|
||||
buildReplyPValue(pmSysInfoBoot,hardware->getSystemHardwareRebootCount());
|
||||
buildReplyPValueP(pmSysInfoType,hardware->getSystemHardwareTypeP());
|
||||
buildReplyPValue(pmSysInfoDebugLevel,debug_level);
|
||||
buildReplyPValue(pmSysInfoFreeRam,XUtil.freeRam());
|
||||
}
|
||||
|
||||
void XnodeSystem::cmdHelp() {
|
||||
for (uint8_t i = ZERO; i < SYSTEM_MODULE_ARRAY_SIZE; i++) {
|
||||
if (systemModules[i] == ZERO) {
|
||||
continue;
|
||||
}
|
||||
systemModules[i]->systemModuleCommandList();
|
||||
}
|
||||
buildReplyCommandListP(pmCmdSysInfo);
|
||||
buildReplyCommandListP(pmCmdReboot);
|
||||
buildReplyCommandListP(pmCmdHelp);
|
||||
}
|
||||
|
||||
void XnodeSystem::registrateSystemModule(XnodeSystemModule* module) {
|
||||
systemModules[systemModuleIndex++] = module;
|
||||
}
|
||||
|
||||
// execute cmd with the supplied argument
|
||||
bool XnodeSystem::executeCommandModule(char* cmd, char** args) {
|
||||
|
||||
// Check for system build in commands.
|
||||
if (XUtil.strcmpP(cmd, pmCmdHelp) == ZERO) {
|
||||
cmdHelp();
|
||||
return true;
|
||||
}
|
||||
if (XUtil.strcmpP(cmd, pmCmdReboot) == ZERO) {
|
||||
buildReplyPValue(pmCmdReboot,ONE);
|
||||
reboot_requested = 100; // let reply be send out/back
|
||||
return true;
|
||||
}
|
||||
if (XUtil.strcmpP(cmd, pmCmdSysInfo) == ZERO) {
|
||||
cmdSysInfo();
|
||||
return true;
|
||||
}
|
||||
if (XUtil.strcmpP(cmd, pmCmdSysCnfRst) == ZERO) {
|
||||
hardware->systemHardwareConfigReset();
|
||||
buildReplyPValue(pmCmdSysCnfRst,ONE);
|
||||
configSave();
|
||||
buildReplyPValue(pmCmdReboot,ONE);
|
||||
reboot_requested = 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check registated parses.
|
||||
for (uint8_t i = ZERO; i < SYSTEM_MODULE_ARRAY_SIZE; i++) {
|
||||
if (systemModules[i] == ZERO) {
|
||||
continue;
|
||||
}
|
||||
if (systemModules[i]->systemModuleCommandExecute(cmd, args)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // no command found
|
||||
}
|
||||
|
||||
// Parse the cmd from a buffer
|
||||
void XnodeSystem::executeCommand(char* input,bool isRemote) {
|
||||
#ifdef DEBUG_SYSTEM
|
||||
Serial.print(F("#D XSystem.executeCommand input="));
|
||||
Serial.print(input);
|
||||
Serial.println();
|
||||
#endif
|
||||
if (isRemote) {
|
||||
XSerial.printCharP(pmRemoteExecutePrefix);
|
||||
XSerial.printPromt();
|
||||
XSerial.printChar(input);
|
||||
XSerial.print(CHAR_NEWLINE);
|
||||
}
|
||||
replyBufferIndex = ZERO;
|
||||
uint8_t idx = ZERO;
|
||||
char *cmd, *ptr, *args[CMD_MAX_ARGS];
|
||||
if (strtok((char *) input, CMD_WHITE_SPACE) == NULL) {
|
||||
// no command given so just print new promt.
|
||||
buildReplyCharP(pmCmdErrUnknown); // TODO: replace with key+value
|
||||
buildReply(CHAR_NEWLINE);
|
||||
buildReply('\0');
|
||||
return;
|
||||
}
|
||||
cmd = (char *) input;
|
||||
while ((ptr = strtok(NULL, CMD_WHITE_SPACE)) != NULL) {
|
||||
args[idx] = ptr;
|
||||
if (++idx == (CMD_MAX_ARGS - ONE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
args[idx] = NULL;
|
||||
bool parsed = executeCommandModule(cmd, args);
|
||||
if (!parsed) {
|
||||
buildReplyCharP(pmCmdErrUnknown);
|
||||
buildReplyChar(cmd); // TODO: add args
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
buildReply('\0');
|
||||
}
|
||||
|
||||
void XnodeSystem::buildReply(unsigned long value, int base) {
|
||||
char buf[8 * sizeof(long) + ONE]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - ONE];
|
||||
*str = ZERO; // reverse printing so start with termination.
|
||||
if (base < 2) {
|
||||
base = 10;// fix base 1 or 0 default to decimals
|
||||
}
|
||||
do {
|
||||
unsigned long m = value;
|
||||
value /= base;
|
||||
char c = m - base * value;
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(value);
|
||||
return buildReplyChar(str);
|
||||
}
|
||||
void XnodeSystem::buildReply(float value,int digitsFull,int digitsDot) {
|
||||
dtostrf(value, digitsFull, digitsDot, (char*)replyBuffer+replyBufferIndex);
|
||||
replyBufferIndex += (digitsFull + 1 + digitsDot) - 1; // "999.9" "-99.9" and remove terminating zero.
|
||||
}
|
||||
void XnodeSystem::buildReply(char value) {
|
||||
replyBuffer[replyBufferIndex++] = value;
|
||||
if (replyBufferIndex > SYSTEM_REPLY_ARRAY_SIZE) {
|
||||
replyBufferIndex--;
|
||||
replyBuffer[replyBufferIndex] = ZERO; // terminate last char
|
||||
#ifdef DEBUG_SYSTEM
|
||||
Serial.print("#D+");
|
||||
Serial.print(value); // print overflow chars
|
||||
Serial.print("-");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void XnodeSystem::buildReplyChar(char* value) {
|
||||
while (*value != ZERO) {
|
||||
buildReply(*value);
|
||||
value++;
|
||||
}
|
||||
}
|
||||
void XnodeSystem::buildReplyCharP(const char* value) {
|
||||
buildReplyChar(XUtil.UNPSTR(value));
|
||||
}
|
||||
void XnodeSystem::buildReplyCommandListP(const char* cmdName) {
|
||||
buildReplyCharP(cmdName);
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
bool XnodeSystem::buildReplyCommandArgumentError(char* cmd, char** args) {
|
||||
if (args[ZERO] != NULL) {
|
||||
return false; // nothing printed
|
||||
}
|
||||
buildReplyCharP(pmCmdErrArgument);
|
||||
buildReplyChar(cmd);
|
||||
buildReply(CHAR_NEWLINE);
|
||||
return true;
|
||||
}
|
||||
void XnodeSystem::buildReplyPValueIP(const char* valueName,uint8_t ip[4]) {
|
||||
buildReplyCharP(valueName);
|
||||
buildReply(CHAR_EQUALS);
|
||||
buildReply(ip[0], DEC);
|
||||
buildReply(CHAR_DOT);
|
||||
buildReply(ip[1], DEC);
|
||||
buildReply(CHAR_DOT);
|
||||
buildReply(ip[2], DEC);
|
||||
buildReply(CHAR_DOT);
|
||||
buildReply(ip[3], DEC);
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
|
||||
void XnodeSystem::buildReplyPValue(const char* valueName,unsigned long value) {
|
||||
buildReplyCharP(valueName);
|
||||
buildReply(CHAR_EQUALS);
|
||||
buildReply(value);
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
void XnodeSystem::buildReplyPValue(const char* valueName,int value) {
|
||||
buildReplyPValue(valueName,(unsigned long)value);
|
||||
}
|
||||
void XnodeSystem::buildReplyPValue(const char* valueName,float value,int digitsFull,int digitsDot) {
|
||||
buildReplyCharP(valueName);
|
||||
buildReply(CHAR_EQUALS);
|
||||
buildReply(value,digitsFull,digitsDot);
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
void XnodeSystem::buildReplyPValueP(const char* valueName,const char* valueP) {
|
||||
buildReplyCharP(valueName);
|
||||
buildReply(CHAR_EQUALS);
|
||||
buildReplyCharP(valueP);
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
void XnodeSystem::buildReplyPValueByteA(const char* valueName,byte* value, byte data_len) {
|
||||
buildReplyCharP(valueName);
|
||||
buildReply(CHAR_EQUALS);
|
||||
for (byte i = ZERO; i < data_len; ++i) {
|
||||
byte d = value[i];
|
||||
if (d<0xF) {
|
||||
buildReply('0'); // exta zero to have two chars
|
||||
}
|
||||
buildReply(d, HEX);
|
||||
}
|
||||
buildReply(CHAR_NEWLINE);
|
||||
}
|
||||
|
||||
49
lib/xnode-shared/XnodeSystem.h
Normal file
49
lib/xnode-shared/XnodeSystem.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef XnodeSystem_h
|
||||
#define XnodeSystem_h
|
||||
|
||||
#include <XnodeSystemHardware.h>
|
||||
#include <XnodeSystemModule.h>
|
||||
#include <XnodeConstants.h>
|
||||
#include <XnodeProtocol.h>
|
||||
#include <XnodeSerial.h>
|
||||
#include <XnodeUtil.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
#define SYSTEM_MODULE_ARRAY_SIZE 4
|
||||
#define SYSTEM_REPLY_ARRAY_SIZE 250
|
||||
|
||||
class XnodeSystem {
|
||||
private:
|
||||
void beginDebug();
|
||||
bool executeCommandModule(char* cmd, char** args);
|
||||
void cmdHelp();
|
||||
void cmdSysInfo();
|
||||
void buildReply(char value);
|
||||
void buildReplyChar(char* value);
|
||||
void buildReply(unsigned long value, int = DEC);
|
||||
void buildReply(float value,int digitsFull,int digitsDot);
|
||||
public:
|
||||
char replyBuffer[SYSTEM_REPLY_ARRAY_SIZE];
|
||||
XnodeSystemHardware* hardware;
|
||||
void begin(XnodeSystemHardware* hardware);
|
||||
void loop();
|
||||
void bootDone();
|
||||
void configSave();
|
||||
void executeCommand(char* input,bool isRemote=false);
|
||||
void registrateSystemModule(XnodeSystemModule* module);
|
||||
|
||||
void buildReplyCommandListP(const char* cmdName);
|
||||
bool buildReplyCommandArgumentError(char* cmd, char** args);
|
||||
void buildReplyCharP(const char* value);
|
||||
void buildReplyPValueIP(const char* valueName,uint8_t ip[4]);
|
||||
void buildReplyPValue(const char* valueName,unsigned long value);
|
||||
void buildReplyPValue(const char* valueName,int value);
|
||||
void buildReplyPValue(const char* valueName,float value,int digitsFull = 3,int digitsDot = 1);
|
||||
void buildReplyPValueP(const char* valueName,const char* valueP);
|
||||
void buildReplyPValueByteA(const char* valueName,byte* value, byte data_len);
|
||||
};
|
||||
|
||||
extern XnodeSystem XSystem;
|
||||
|
||||
#endif
|
||||
|
||||
15
lib/xnode-shared/XnodeSystemHardware.h
Normal file
15
lib/xnode-shared/XnodeSystemHardware.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef XnodeSystemHardware_h
|
||||
#define XnodeSystemHardware_h
|
||||
|
||||
class XnodeSystemHardware {
|
||||
public:
|
||||
virtual const char* getSystemHardwareTypeP();
|
||||
virtual const char* getSystemHardwareVersionP();
|
||||
virtual unsigned long getSystemHardwareRebootCount();
|
||||
virtual bool systemHardwareConfigBegin();
|
||||
virtual void systemHardwareConfigSave();
|
||||
virtual void systemHardwareConfigReset();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
11
lib/xnode-shared/XnodeSystemModule.h
Normal file
11
lib/xnode-shared/XnodeSystemModule.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef XnodeSystemModule_h
|
||||
#define XnodeSystemModule_h
|
||||
|
||||
class XnodeSystemModule {
|
||||
public:
|
||||
virtual bool systemModuleCommandExecute(char* cmd, char** args);
|
||||
virtual void systemModuleCommandList();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
85
lib/xnode-shared/XnodeUtil.cpp
Normal file
85
lib/xnode-shared/XnodeUtil.cpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#include <XnodeUtil.h>
|
||||
|
||||
char unpstr_buff[UNPSTR_BUFF_SIZE]; // buffer to copy progmem data into
|
||||
|
||||
// Uncopy from program/flash memory to sram
|
||||
char* XnodeUtil::UNPSTR(const char* ptr) {
|
||||
for (uint8_t i = ZERO; i < UNPSTR_BUFF_SIZE; i++) {
|
||||
unpstr_buff[i] = '\0'; // clean buffer
|
||||
}
|
||||
uint8_t i = ZERO;
|
||||
uint8_t c = ZERO;
|
||||
do {
|
||||
c = pgm_read_byte(ptr++);
|
||||
unpstr_buff[i++] = c;
|
||||
} while (c != ZERO);
|
||||
return unpstr_buff;
|
||||
}
|
||||
|
||||
// Fill pstr_buff from pointer
|
||||
char* XnodeUtil::UNPSTRA(const uint16_t* argu) {
|
||||
// rm readByte use word which auto size ptr
|
||||
uint8_t msb = pgm_read_byte((const char*) argu + 1);
|
||||
uint8_t lsb = pgm_read_byte((const char*) argu);
|
||||
const char*p = (const char*) ((msb * 256) + lsb);
|
||||
return UNPSTR(p);
|
||||
}
|
||||
|
||||
uint8_t XnodeUtil::strcmp(char *s1, char *s2) {
|
||||
while (*s1 && *s2 && *s1 == *s2) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
if (*s1 == *s2) {
|
||||
return 0;
|
||||
}
|
||||
if (*s1 < *s2) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t XnodeUtil::strcmpP(char *s1, const char* s2) {
|
||||
return strcmp(s1, UNPSTR(s2));
|
||||
}
|
||||
|
||||
void XnodeUtil::charsToByteA(char* input,byte* data, byte data_len) {
|
||||
for (byte i = ZERO; i < data_len; i++) {
|
||||
data[i] = ZERO; // clear array
|
||||
}
|
||||
byte charIdx = ZERO;
|
||||
for (byte i = ZERO; i < data_len; i++) {
|
||||
char c1 = input[charIdx];
|
||||
char c2 = input[charIdx + ONE];
|
||||
if (c1 == ZERO || c2 == ZERO) {
|
||||
break;
|
||||
}
|
||||
data[i] = charsToByte(c1, c2);
|
||||
charIdx++;
|
||||
charIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
byte XnodeUtil::charsToByte(char c1, char c2) {
|
||||
byte result = ZERO;
|
||||
result += charToNibble(c1) * 16;
|
||||
result += charToNibble(c2);
|
||||
return result;
|
||||
}
|
||||
|
||||
byte XnodeUtil::charToNibble(char c) {
|
||||
uint8_t result = ZERO;
|
||||
if (c > '0' && c <= '9') {
|
||||
result = c - '0';
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
result = c - 'A' + 10;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int XnodeUtil::freeRam() {
|
||||
extern int __heap_start, *__brkval;
|
||||
int v;
|
||||
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
||||
}
|
||||
|
||||
27
lib/xnode-shared/XnodeUtil.h
Normal file
27
lib/xnode-shared/XnodeUtil.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef XnodeUtil_h
|
||||
#define XnodeUtil_h
|
||||
|
||||
#include <XnodeConstants.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define UNPSTR_BUFF_SIZE 32
|
||||
|
||||
class XnodeUtil {
|
||||
public:
|
||||
static char* UNPSTR(const char* ptr);
|
||||
static char* UNPSTRA(const uint16_t* argu);
|
||||
static uint8_t strcmp(char *s1, char *s2);
|
||||
static uint8_t strcmpP(char *s1, const char* s2);
|
||||
|
||||
static void charsToByteA(char* input,byte* data, byte data_len);
|
||||
static byte charsToByte(char c1, char c2);
|
||||
static byte charToNibble(char s);
|
||||
|
||||
static int freeRam();
|
||||
};
|
||||
|
||||
extern XnodeUtil XUtil;
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue