diff --git a/Tag/Device_Firmware/Known_Versions_Code b/Tag/Device_Firmware/Known_Versions_Code new file mode 100644 index 0000000..e69de29 diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag.avrsln b/Tag/Device_Firmware/V0.2.1/WIDTag.avrsln new file mode 100644 index 0000000..e5580fd --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag.avrsln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# AvrStudio Solution File, Format Version 11.00 +Project("{D1100916-62DA-4D80-A9B4-55A1E7CCEEB3}") = "WIDTag", "WIDTag\WIDTag.avrgccproj", "{77BCDBD5-EB6F-4198-9537-80123C2374B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|AVR = Debug|AVR + Release|AVR = Release|AVR + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Debug|AVR.ActiveCfg = Debug|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Debug|AVR.Build.0 = Debug|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Release|AVR.ActiveCfg = Release|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Release|AVR.Build.0 = Release|AVR + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag.avrsuo b/Tag/Device_Firmware/V0.2.1/WIDTag.avrsuo new file mode 100644 index 0000000..c37fc0e Binary files /dev/null and b/Tag/Device_Firmware/V0.2.1/WIDTag.avrsuo differ diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_NRF24L01.h b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_NRF24L01.h new file mode 100644 index 0000000..26cd0f3 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_NRF24L01.h @@ -0,0 +1,71 @@ +/* + * M_NRF24L01.h + * + * Created on: 09/03/2010 + * Author: Matty + */ + +#ifndef M_NRF24L01_H_ +#define M_NRF24L01_H_ + +#include +#include +#include + + +//Pins: +#define CSN1 2 +#define CE1 1 +#define NRF_MISO 4 +#define NRF_MOSI 3 +#define NRF_SCK 5 + + +//nRF24L01 Registers: +#define NREG_CONFIG 0x00 +#define NREG_EN_AA 0x01 +#define NREG_EN_RXADDR 0x02 +#define NREG_SETUP_AW 0x03 +#define NREG_SETUP_RETR 0x04 +#define NREG_RF_CH 0x05 +#define NREG_RF_SETUP 0x06 +#define NREG_STATUS 0x07 +#define NREG_OBSERVE_TX 0x08 +#define NREG_RPD 0x09 +#define NREG_RX_ADDR_P0 0x0A //5 bytes +#define NREG_RX_ADDR_P1 0x0B //5 bytes +#define NREG_RX_ADDR_P2 0x0C +#define NREG_RX_ADDR_P3 0x0D +#define NREG_RX_ADDR_P4 0x0E +#define NREG_RX_ADDR_P5 0x0F +#define NREG_TX_ADDR 0x10 //5 bytes +#define NREG_RX_PW_P0 0x11 +#define NREG_RX_PW_P1 0x12 +#define NREG_RX_PW_P2 0x13 +#define NREG_RX_PW_P3 0x14 +#define NREG_RX_PW_P4 0x15 +#define NREG_RX_PW_P5 0x16 +#define NREG_FIFOSTATUS 0x17 + +//Macros: +#define NRF_POWERDOWN NRF24L01_SetMode(0,1) +#define NRF_RXMODE NRF24L01_SetMode(1,1) +#define NRF_TXMODE NRF24L01_SetMode(1,0) + +//Function Prototypes +void NRF24L01_SPI_Setup( ); +void NRF24L01_SPI_TX(uint8_t); +uint8_t NRF24L01_SPI_RX( ); +void NRF24L01_W_Reg(uint8_t , uint8_t); +void NRF24L01_W_Reg_Long(uint8_t , uint8_t* , uint8_t); +uint8_t NRF24L01_R_Reg(uint8_t); +void NRF24L01_R_Reg_Long(uint8_t , uint8_t* , uint8_t); +uint8_t NRF24L01_TX_PAYLOAD(uint32_t*); +//uint8_t NRF24L01_R_RX_PAYLOAD(uint32_t*); +void NRF24L01_SetupnRF24L01(uint8_t, uint8_t*); +void NRF24L01_SetMode(uint8_t , uint8_t); +void NRF24L01_Flush_RX_FIFO( ); +void NRF24L01_Flush_TX_FIFO( ); + + +#endif /* M_NRF24L01_H_ */ diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_PRTC.h b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_PRTC.h new file mode 100644 index 0000000..1742896 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_PRTC.h @@ -0,0 +1,44 @@ +/* + * M_PRTC.h + * + * Created on: 04/09/2010 + * Author: MC + */ + +#ifndef M_PRTC_H_ +#define M_PRTC_H_ + +#include +#include +#include +#include + +struct RTCTime { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; + + uint8_t Day; + uint8_t Month; + int Year; +}; + + +//Function Prototypes: +void RTC_Setup(); +uint16_t RTC_GetCNT(); +uint8_t IntToBCD(uint8_t); +uint8_t BCDToInt(uint8_t); +void CopyTime (struct RTCTime*, struct RTCTime*); +void AddTimes(struct RTCTime*, struct RTCTime*); +void ClearTime(struct RTCTime*); +uint8_t CompareTimes (struct RTCTime* , struct RTCTime* ); +//uint8_t FirstTimeGreater (struct RTCTime* , struct RTCTime* ); +uint8_t ValidDateTime(struct RTCTime*); +uint8_t DaysInMonth(uint8_t , uint8_t ); +int str2Time(char*, struct RTCTime*); +void sPrintTime(char*, struct RTCTime* , char*); +void ZipTime(struct RTCTime*, uint8_t*); +void UnzipTime(struct RTCTime*, uint8_t*); + +#endif /* M_PRTC_H_ */ diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_USART.h b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_USART.h new file mode 100644 index 0000000..ee1c3a0 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/M_USART.h @@ -0,0 +1,93 @@ +/* + * M_USART.h + * + * Created on: 22/01/2010 + * Author: Matthew Cochrane + */ + +#ifndef M_USART_H_ +#define M_USART_H_ + +//Includes +#include +#include + +//Defines +//Register & Bit Defines - These need to be altered for your specific chip +#define UDRRRegH UBRR0H +#define UDRRRegL UBRR0L +#define UCSRAReg UCSR0A +#define UCSRBReg UCSR0B +#define UCSRCReg UCSR0C +#define UDRReg UDR0 +#define U2XBit U2X0 +#define RXENBit RXEN0 +#define TXENBit TXEN0 +#define UCSZ0Bit UCSZ00 +#define UCSZ1Bit UCSZ01 +#define UDREBit UDRE0 +#define RXCBit RXC0 +//Formatting and Escape Sequences +#define ECC_COL_BLACK "0" +#define ECC_COL_RED "1" +#define ECC_COL_GREEN "2" +#define ECC_COL_YELLOW "3" +#define ECC_COL_BLUE "4" +#define ECC_COL_MAGENTA "5" +#define ECC_COL_CYAN "6" +#define ECC_COL_WHITE "7" +#define ECC_COL_RESET "9" +#define ESC_FG "3" +#define ESC_BG "4" +#define ESC_FONT_NORMAL "0" //ALL attributes off +#define ESC_FONT_BOLD "1" +#define ESC_FONT_ITALIC "3" //Not widely supported. Sometimes treated as inverse. +#define ESC_FONT_UNDERLINE "4" +#define ESC_FONT_NOUNDERLINE "24" +#define ESC_FONT_2XUNDERLINE "21" //Not widely supported +#define ESC_INTENSITY_FAINT "2" //Not widely supported +#define ESC_INTENSITY_NORMAL "22" //Not bold and not faint +#define ESC_BLINK_SLOW "5" //less than 150 per minute +#define ESC_BLINK_RAPID "6" //more than 150 per minute +#define ESC_BLINK_OFF "25" +#define ESC_IMG_NEG "7" //Inverse - swap foreground and background colours +#define ESC_IMG_POS "27" +#define ESC_CONCEAL "8" //Not widely supported. Hides any further writing +#define ESC_REVEAL "28" //conceal off + +//Macros +#define ESC_COL(type,col) type col +#define ESC_SGR1(var1) "\x1B[" var1 "m" +#define ESC_SGR2(var1, var2) "\x1B[" var1 ";" var2 "m" +#define ESC_SGR3(var1, var2, var3) "\x1B[" var1 ";" var2 ";" var3 "m" +#define ESC_SGR4(var1, var2, var3, var4) "\x1B[" var1 ";" var2 ";" var3 ";" var4 "m" +#define ESC_SGR5(var1, var2, var3, var4, var5) "\x1B[" var1 ";" var2 ";" var3 ";" var4 ";" var5 "m" +#define ESC_MOV_CUR_UP(n) "\x1B[" #n "A" +#define ESC_MOV_CUR_DOWN(n) "\x1B[" #n "B" +#define ESC_MOV_CUR_RIGHT(n) "\x1B[" #n "C" +#define ESC_MOV_CUR_LEFT(n) "\x1B[" #n "D" +#define ESC_MOV_CUR_ROW(n) "\x1B[" #n "A" +#define ESC_MOV_CUR_COL(n) "\x1B[" #n "A" +#define ESC_MOV_CUR(x,y) "\x1B[" #y ";" #x "H" //Row x, Col y +#define ESC_CLS "\x1B[2J" +#define ESC_CLR_LINE "\x1B[2K" +#define ESC_SCROLL_UP(n) "\x1B[" #n "S" +#define ESC_SCROLL_DOWN(n) "\x1B[" #n "T" +#define ESC_GET_CUR_POS "\x1B[6n" +#define ESC_CUR_SAVE "\x1B[s" +#define ESC_CUR_RESTORE "\x1B[u" + +#define USART_printf_P(str, ...) do {sprintf_P(s, PSTR(str), __VA_ARGS__); USART_tx_String(s);} while (0) + +//Function Prototypes +void USART_Setup(unsigned int, unsigned char); +void USART_tx_Byte(char); +void USART_tx_String(const char *); +void USART_tx_String_P(const char *); +char USART_rx_Byte(unsigned int); +int USART_rx_Byte_nb( void ); +unsigned char USART_rx_String(char *, unsigned int); +void USART_UpdateTimers(void); + + +#endif /* M_USART_H_ */ diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/WIDTag.h b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/WIDTag.h new file mode 100644 index 0000000..613a1fd --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag/Includes/WIDTag.h @@ -0,0 +1,90 @@ +/* + * WIDTag.h + * + * Created on: 05/09/2010 + * Author: Matthew Cochrane + */ + +#ifndef WIDTAG_H_ +#define WIDTAG_H_ + +//Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "M_PRTC.h" +#include "M_USART.h" +#include "M_NRF24L01.h" + +//Define +#define CPU8MHZ 1 +//#define CPU1MHZ 1 +#ifdef CPU8MHZ + #define UBRRVAL 0x0067 //for 8MHz (Double Speed) + #define TIMEOUT 253 //aprox 8 seconds + #define NORWAITTIMPRE (1< + 00 = -18dBm (7.0mA in TX mode) + 01 = -12dBm (7.5mA in TX mode) + 10 = -6dBm (9.0mA in TX mode) + 00 = 0dBm (11.3mA in TX mode) + */ + //Setup RF -> 2Mbps data rate, 0dBm output power + //NRF24L01_W_Reg(NREG_RF_SETUP, 0b00000111); + //Setup RF -> 1Mbps data rate, 0dBm output power + //NRF24L01_W_Reg(NREG_RF_SETUP, 0b00000011); + //Setup RF -> 250kbps data rate, 0dBm output power + NRF24L01_W_Reg(NREG_RF_SETUP, 0b00100111); + //uint8_t myData[5]; + //for (uint8_t i = 0; i < 5; i++) myData[i] = 0xE6; + //Set the address of RX Pipe 0 to pipeAddress + NRF24L01_W_Reg_Long(NREG_RX_ADDR_P0, (uint8_t*)pipeAddress, 5); + //Set TX Address to pipeAddress + NRF24L01_W_Reg_Long(NREG_TX_ADDR, (uint8_t*)pipeAddress, 5); + //Disable auto-ACK + NRF24L01_W_Reg(NREG_EN_AA, 0x00); + //Enable only pipe 0 + NRF24L01_W_Reg(NREG_EN_RXADDR, 0b00000001); + //Enable Pipe 0 and use payload width of 4 + NRF24L01_W_Reg(NREG_RX_PW_P0, 4); +} + +void NRF24L01_SetMode(uint8_t Power, uint8_t RXMode) { + uint8_t ConfigReg; + //Power up and put into RX mode + ConfigReg = NRF24L01_R_Reg(NREG_CONFIG); + + if (Power) + ConfigReg |= 0b00000010; + else + ConfigReg &= 0b11111101; + + if (RXMode) { + ConfigReg |= 0b00000001; + NRF24L01_W_Reg(NREG_CONFIG, ConfigReg); + if (Power) { + PORTB |= (1< 99) return 99; + uint8_t a = val/10; + return (a<<4)|(val-(a*10)); +} + +uint8_t BCDToInt (uint8_t val) { + if (val > 0x99) return 99; + return (val&0x0F)+10*(val>>4); +} + +void CopyTime (struct RTCTime* SrcTime, struct RTCTime* DstTime) { + for (uint8_t i = 0; i < 6; i++) + *(((uint8_t*)DstTime)+i) = *(((uint8_t*)SrcTime)+i); +} + +void ClearTime (struct RTCTime* Time1) { + Time1->Year = 0; + Time1->Month = 0; + Time1->Day = 0; + Time1->Hour = 0; + Time1->Minute = 0; + Time1->Second = 0; +} + +/*uint8_t FirstTimeGreater (struct RTCTime* Time1, struct RTCTime* Time2) { + //It is assumed that times are VALID! + + //if Time1 >= Time2 then TRUE + //if Time1 < Time2 then FALSE + + //if Time1 > Time2 then 1 + //if Time2 > Time1 then 0 + //if Time1 = Time2 then 2 + + if (Time2->Year > Time1->Year) { + return 0; + } else if (Time2->Year < Time1->Year) { + return 1; + } else { + if (Time2->Month > Time1->Month) { + return 0; + } else if (Time2->Month < Time1->Month) { + return 1; + } else { + if (Time2->Day > Time1->Day) { + return 0; + } else if (Time2->Day < Time1->Day) { + return 1; + } else { + if (Time2->Hour > Time1->Hour) { + return 0; + } else if (Time2->Hour < Time1->Hour) { + return 1; + } else { + if (Time2->Minute > Time1->Minute) { + return 0; + } else if (Time2->Minute < Time1->Minute) { + return 1; + } else { + if (Time2->Second > Time1->Second) { + return 0; + } else if (Time2->Second < Time1->Second) { + return 1; + } else { + return 2; + } + } + } + } + } + } + +}*/ + +uint8_t ValidDateTime(struct RTCTime* DT) { + uint8_t days; + if (DT->Second > 59 || DT->Minute > 59 || DT->Hour > 23) + return 0; + + if (DT->Day == 0 || DT->Month == 0 || DT->Month > 12) + return 0; + + days = DaysInMonth(DT->Month, DT->Year); + + if (DT->Day > days) + return 0; + + //If we got here.. it's a valid date! + return 1; +} + +void AddTimes (struct RTCTime* DateTime, struct RTCTime* AddTime) { + //DateTime = DateTime + AddTime + //AddTime can be a specific number of days month minutes etc. + //DateTime MUST BE A PROPER DATETIME! + //Double overflows are supported + //Overflows added from small time through to large time + //(ie. secs then mins then hours then days etc.) + + uint8_t a; + + DateTime->Second += AddTime->Second; + while (DateTime->Second > 59) { + DateTime->Second -= 60; + DateTime->Minute++; + } + DateTime->Minute += AddTime->Minute; + + while (DateTime->Minute > 59) { + DateTime->Minute -= 60; + DateTime->Hour++; + } + DateTime->Hour += AddTime->Hour; + while (DateTime->Hour > 23) { + DateTime->Hour -= 24; + DateTime->Day++; + } + DateTime->Day += AddTime->Day; + + while (DateTime->Day > (a = DaysInMonth(DateTime->Month, DateTime->Year))) { + DateTime->Day -= a; + DateTime->Month++; + } + DateTime->Month += AddTime->Month; + while (DateTime->Month > 12) { + DateTime->Month -= 12; + DateTime->Year++; + } + DateTime->Year += AddTime->Year; + //while (DateTime->Year > 99) { + // DateTime->Year -= 100; + //} +} + +uint8_t DaysInMonth(uint8_t Month, uint8_t Year) { + switch (Month) { + //31 day months + case 1://Jan + case 3://Mar + case 5://May + case 7://July + case 8://Aug + case 10://Oct + case 12://Dec + return 31; + break; + //30 day months + case 4://April + case 6://June + case 9://Sep + case 11://Nov + return 30; + break; + //The dreaded February!!! + case 2://Feb + //Is it a leap year?? + if(((Year + 2000) % 4 == 0 && (Year + 2000) % 100 != 0) || (Year + 2000) % 400 == 0) + return 29;//Yes + else + return 28;//No + break; + default: + return 0; + } +} + +void sPrintTime (char* __s, struct RTCTime* pTime, char* lbl) { + if (lbl[0] == '\0') + sprintf_P(__s,PSTR("%02d-%02d-%02d %02d:%02d:%02d") + , pTime->Year + , pTime->Month + , pTime->Day + , pTime->Hour + , pTime->Minute + , pTime->Second); + else + sprintf_P(__s,PSTR("%s: %02d-%02d-%02d %02d:%02d:%02d\r\n") + , lbl + , pTime->Year + , pTime->Month + , pTime->Day + , pTime->Hour + , pTime->Minute + , pTime->Second); + //USART_tx_String(s); +} + +int str2Time(char* __s, struct RTCTime* destTime) { + //Format of string: DDMMYYHHMMSS - that's 12 characters. + int i; + + //check that it's 'valid' + for(i = 0; i < 12; i++) { + if (__s[i] < '0' || __s[i] > '9') + return -1; + } + + destTime->Day = BCDToInt((uint8_t)(((__s[0]-'0')<<4)+(__s[1]-'0'))); + destTime->Month = BCDToInt((uint8_t)(((__s[2]-'0')<<4)+(__s[3]-'0'))); + destTime->Year = BCDToInt((uint8_t)(((__s[4]-'0')<<4)+(__s[5]-'0'))); + destTime->Hour = BCDToInt((uint8_t)(((__s[6]-'0')<<4)+(__s[7]-'0'))); + destTime->Minute = BCDToInt((uint8_t)(((__s[8]-'0')<<4)+(__s[9]-'0'))); + destTime->Second = BCDToInt((uint8_t)(((__s[10]-'0')<<4)+(__s[11]-'0'))); + + if (ValidDateTime(destTime)) + return 0; + else + return -1; +} + +void ZipTime(struct RTCTime* rawTime, uint8_t* zipTime) { + //using compression method B: + // Byte 1 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr1 Yr0 Sec5 Sec4 Sec3 Sec2 Sec1 Sec0 + // Byte 2 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr3 Yr2 Min5 Min4 Min3 Min2 Min1 Min0 + // Byte 3 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr6 Yr5 Yr4 Hr4 Hr3 Hr2 Hr1 Hr0 + // Byte 4 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr9 Yr8 Yr7 Day4 Day3 Day2 Day1 Day0 + // Byte 5 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr13 Yr12 Yr11 Yr10 Mon3 Mon2 Mon1 Mon0 + + zipTime[0] = (rawTime->Second&0x3F)|(rawTime->Year&0x0003); + zipTime[1] = (rawTime->Minute&0x3F)|(rawTime->Year&0x000C); + zipTime[2] = (rawTime->Hour&0x1F)|(rawTime->Year&0x0070); + zipTime[3] = (rawTime->Day&0x1F)|(rawTime->Year&0x0380); + zipTime[4] = (rawTime->Month&0x0F)|(rawTime->Year&0x3C00); + +} + +void UnzipTime(struct RTCTime* rawTime, uint8_t* zipTime) { + //using compression method B: + // Byte 1 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr1 Yr0 Sec5 Sec4 Sec3 Sec2 Sec1 Sec0 + // Byte 2 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr3 Yr2 Min5 Min4 Min3 Min2 Min1 Min0 + // Byte 3 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr6 Yr5 Yr4 Hr4 Hr3 Hr2 Hr1 Hr0 + // Byte 4 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr9 Yr8 Yr7 Day4 Day3 Day2 Day1 Day0 + // Byte 5 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr13 Yr12 Yr11 Yr10 Mon3 Mon2 Mon1 Mon0 + + + rawTime->Second = zipTime[0]&0x3F; + rawTime->Hour = zipTime[1]&0x3F; + rawTime->Minute = zipTime[2]&0x1F; + rawTime->Day = zipTime[3]&0x1F; + rawTime->Month = zipTime[4]&0x0F; + rawTime->Year = (uint16_t)(zipTime[0]&0xC0>>6)|(zipTime[1]&0xC0>>4)| + (zipTime[2]&0xE0>>1)|(zipTime[3]&0xE0<<3)|(zipTime[4]&0xF0<<7); + + + zipTime[0] = (rawTime->Second&0x3F)|(rawTime->Year&0x0003); + zipTime[1] = (rawTime->Minute&0x3F)|(rawTime->Year&0x000C); + zipTime[2] = (rawTime->Hour&0x1F)|(rawTime->Year&0x0070); + zipTime[3] = (rawTime->Day&0x1F)|(rawTime->Year&0x0380); + zipTime[4] = (rawTime->Month&0x0F)|(rawTime->Year&0x3C00); + +} diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag/Libs/M_USART.c b/Tag/Device_Firmware/V0.2.1/WIDTag/Libs/M_USART.c new file mode 100644 index 0000000..04c6850 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag/Libs/M_USART.c @@ -0,0 +1,178 @@ +/* + * M_USART.c + * + * Created on: 22/01/2010 + * Author: Matty + */ + +#include "M_USART.h" + +volatile unsigned int Timer1; + +/* Function Name: SetupUSART +** Created On: 22/01/2010 +** Created By: Matthew Cochrane +** Description: Sets up the USART in asynchronous mode to a Baud rate specified by +** UBRR and UU2X with 8 data bits no parity and one stop bit. +** Inputs: +** UBRR - Value to set the UBRR register to +** UU2X - Boolean variable which if true will enable double data rate for the USART. +*/ +void USART_Setup (unsigned int UBRR, unsigned char UU2X) { + //Setup Baud Rate + UDRRRegH = (unsigned char)(UBRR >> 8); + UDRRRegL = (unsigned char)(UBRR & 0x00FF); + + //Setup Double Speed Setting + if (UU2X) { + UCSRAReg = (1< 0) Timer1--; +} + + + + + diff --git a/Tag/Device_Firmware/V0.2.1/WIDTag/Src/WIDTag.c b/Tag/Device_Firmware/V0.2.1/WIDTag/Src/WIDTag.c new file mode 100644 index 0000000..bca3f62 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.1/WIDTag/Src/WIDTag.c @@ -0,0 +1,496 @@ +/* + * WIDTag.c + * + * Name: Wireless ID Tag + * Created on: 05/09/2010 + * Author: Matthew Cochrane + * MCU: ATMEGA328P + * Fuse Bits: + * High - 0xD9 + * Low - 0xE2 + * + */ + +#include "WIDTag.h" + +char s[80]; +char s1[50]; +volatile unsigned char patience; +volatile uint8_t Wakeup_Source = WAKEUP_SOURCE_NONE; +uint32_t Device_ID; +uint8_t RF_ID[5]; +uint8_t RF_Chan; +uint8_t DevArmed; +volatile uint16_t timer10ms = 0; +struct RTCTime RTC_c_Time; +struct RTCTime RTC_Period; +//struct RTCTime TX_Period; +uint8_t TX_Period; +uint8_t PrintTime = 0; +volatile uint8_t TX_Delay = 0; //Also used in M_NRF24L01.c to check for tx timeout +uint8_t modDelay = 0; + +ISR(TIMER0_OVF_vect) { + USART_UpdateTimers(); +} + +ISR(TIMER0_COMPA_vect) { + if (timer10ms) --timer10ms; + else TCCR0B = 0; +} + +ISR(PCINT2_vect) { + Wakeup_Source = WAKEUP_SOURCE_UART; +} + +ISR(TIMER2_OVF_vect) { + Wakeup_Source = WAKEUP_SOURCE_RTC; + AddTimes(&RTC_c_Time, &RTC_Period); + if (TX_Delay) --TX_Delay; + //NOTE: + // Ran for 10 hours WITHOUT xtal capacitors and the clock was out by about a second. + // After less than a day of running without caps its ~ 5s out (updated windows time before and after) +} + +ISR(TIMER2_COMPA_vect) { + +} + +int main(void) { + + uint8_t i, j; + + /*//TEST CODE// + //0 - LED + DDRC = (1<<0); + //USART Tx + DDRD = (1<<1); + + // Enable pullups + PORTC = 0b00111000; + PORTD = 0b11111111; + PRR = ~((1<")); + USART_tx_String_P(PSTR(">")); + //flush USART RX buffer + while (USART_rx_Byte_nb() != -1); + //Receive byte + retChar = USART_rx_Byte(TIMEOUT); + switch (retChar) { + case 'T': + USART_tx_String_P(PSTR("ET (DDMMYYHHMMSS):\r\n"));//Enter Date/Time (DDMMYYHHMMSS).\r\n>")); + + for (i = 0; i < 12; i++) + s[i] = USART_rx_Byte(TIMEOUT<<2); + s[12] = '\0'; + + if (str2Time(s, &tmpTime) == 0) + CopyTime(&tmpTime, &RTC_c_Time); + + sPrintTime(s, &RTC_c_Time, "Time"); + USART_tx_String(s); + break; + case 'P': + USART_tx_String_P(PSTR("ETX (MSS):\r\n"));//Enter TX Period (MSS).\r\n>")); + + s[3] = 0; + for (i = 0; i < 3; i++) { + s[i] = USART_rx_Byte(TIMEOUT<<1)-'0'; + if (s[i] > 9 || s[i] < 0) + s[3] = 1; + } + + if (!s[3]) { + i = s[0]*60+s[1]*10+s[2]; + if (i > 255) { + USART_tx_String_P(PSTR("Bad\r\n"));//Invalid TX period entered.\r\n")); + } else { + TX_Period = i; + TX_Delay = i; + eeprom_write_byte((uint8_t*)TXPERADD,TX_Period); + //USART_printf_P("TX Period set to %d seconds\r\n", TX_Period); + USART_printf_P("TX %ds\r\n", TX_Period); + } + } else { + USART_tx_String_P(PSTR("Bad\r\n"));//Invalid TX period entered.\r\n")); + } + break; + case 's': + TXPayload(); + break; + case 'N': + USART_printf_P("Status:0x%02X\r\n", NRF24L01_R_Reg(NREG_STATUS)); + break; + case 't': + PrintTime ^= 1; + //USART_printf_P("PrintTime :0x%02X\r\n", PrintTime); + break; + case '?': + ReadAllVarsFromEEPROM(); + //DEV_ID + USART_printf_P("DEV_ID:%08lX\r\n", Device_ID); + //RFID + USART_tx_String_P(PSTR("RFID:")); + for (i = 0; i < 4; i++) { + USART_printf_P("%02X-", RF_ID[i]); + } + USART_printf_P("%02X\r\n", RF_ID[4]); + //RFCHAN + USART_printf_P("RFCHAN:%d\r\n", RF_Chan); + //ARMED + USART_printf_P("DEVARMED:%u\r\n", DevArmed); + //TXPERIOD + USART_printf_P("TXPERIOD:%d\r\n", TX_Period); + break; + case '*': + //DEV_ID + s[0] = 's'; + USART_tx_String_P(PSTR("DEV_ID (XXXXXXXX):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + Device_ID = (uint32_t)strtoul(s, (char **)NULL,16); + WriteEEPROM((uint8_t*)&Device_ID, 4,DEVIDADD); + } + s[0] = 's'; + //RFID + USART_tx_String_P(PSTR("RFID (XX-XX-XX-XX-XX):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + for (i = 0; i < 5; i++) + RF_ID[i] = (uint8_t)strtoul(s+i*3, (char **)NULL,16); + WriteEEPROM(RF_ID,5,RFIDADD); + RFedit = 1; + } + s[0] = 's'; + //RFCHAN + USART_tx_String_P(PSTR("RFCHAN (###):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + RF_Chan = 100*(s[0]-'0') + 10*(s[1]-'0') + (s[2]-'0'); + eeprom_write_byte((uint8_t*)RFCHANADD, RF_Chan); + RFedit = 1; + } + s[0] = 's'; + //DEVARMED + USART_tx_String_P(PSTR("DEVARMED (X):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + DevArmed = s[0]-'0'; + eeprom_write_byte((uint8_t*)DEVARMEDADD,DevArmed); + DevArmSetup(); + } + s[0] = 's'; + //TXPERIOD + USART_tx_String_P(PSTR("TXPERIOD (MSS):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + i = (s[0]-'0')*60+(s[1]-'0')*10+(s[2]-'0'); + //if (i < 255) { + TX_Period = i; + TX_Delay = i; + eeprom_write_byte((uint8_t*)TXPERADD,TX_Period); + //} + } + + if (RFedit && DevArmed != ARM_SHELF) { + //Setup the Nordic Chip with new values + NRF24L01_SPI_Setup(); + NRF24L01_SetupnRF24L01(RF_Chan, RF_ID); + NRF_POWERDOWN; + } + break; + } + //USART_tx_String_P(PSTR("Going to sleep. Press any key to wake.\r\n")); + USART_tx_String_P(PSTR("Sleep.\r\n")); + +} + +/*inline void WriteTimeEEPROM(struct RTCTime* mTime, uint16_t Address) { + WriteEEPROM((uint8_t*)mTime, 5, Address); +} + +inline void ReadTimeEEPROM(struct RTCTime* mTime, uint16_t Address) { + ReadEEPROM((uint8_t*)mTime, 5, Address); +}*/ + +void ReadEEPROM(uint8_t* Data, uint8_t Length, uint16_t Address) { + for (int i = 0; i < Length; i++) + *Data++ = eeprom_read_byte((uint8_t*)Address++); +} + +void WriteEEPROM(uint8_t* Data, uint8_t Length, uint16_t Address) { + for (int i = 0; i < Length; i++) + eeprom_write_byte((uint8_t*)Address++, *Data++); +} + +static inline void delay_ms(uint16_t ms) { + do { + _delay_ms(1); + } while (--ms != 0); +} + +void StartTim10ms(uint16_t Time) { + PRR &= ~(1< + + + 2.0 + 5.0 + {77bcdbd5-eb6f-4198-9537-80123c2374b8} + ATmega88PA + none + Executable + C + $(MSBuildProjectName).elf + $(MSBuildProjectDirectory)\$(Configuration) + True + + + + + C:\Program Files (x86)\Atmel\AVR Studio 5.0\AVR ToolChain\bin + + + WIDTag + WIDTag + WIDTag + debugWIRE + com.atmel.avrdbg.tool.avrdragon + + com.atmel.avrdbg.tool.avrdragon + AVR Dragon + 00A20000865C + + 127.0.0.1 + 50870 + False + + + debugWIRE + + 1000000 + 1000000 + 150000 + false + false + 0 + 0 + 0 + 0 + + + + + com.atmel.avrdbg.tool.simulator + AVR Simulator + + + + 127.0.0.1 + 50870 + False + + + + + + + True + True + Optimize for size (-Os) + True + True + None + True + + + + + True + True + True + True + + + + + True + True + + + F_CPU=8000000UL + + + + + ../Includes + + + Optimize for size (-Os) + True + True + Default (-g2) + True + Default (-g2) + + + + + +
0x400
+
+
+
+ True + True + True + True + WIDTag.elf + Executable +
+ + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + + + + + + +
\ No newline at end of file diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag.avrsln b/Tag/Device_Firmware/V0.2.2/WIDTag.avrsln new file mode 100644 index 0000000..e5580fd --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag.avrsln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# AvrStudio Solution File, Format Version 11.00 +Project("{D1100916-62DA-4D80-A9B4-55A1E7CCEEB3}") = "WIDTag", "WIDTag\WIDTag.avrgccproj", "{77BCDBD5-EB6F-4198-9537-80123C2374B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|AVR = Debug|AVR + Release|AVR = Release|AVR + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Debug|AVR.ActiveCfg = Debug|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Debug|AVR.Build.0 = Debug|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Release|AVR.ActiveCfg = Release|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Release|AVR.Build.0 = Release|AVR + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag.avrsuo b/Tag/Device_Firmware/V0.2.2/WIDTag.avrsuo new file mode 100644 index 0000000..a6cb134 Binary files /dev/null and b/Tag/Device_Firmware/V0.2.2/WIDTag.avrsuo differ diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_NRF24L01.h b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_NRF24L01.h new file mode 100644 index 0000000..26cd0f3 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_NRF24L01.h @@ -0,0 +1,71 @@ +/* + * M_NRF24L01.h + * + * Created on: 09/03/2010 + * Author: Matty + */ + +#ifndef M_NRF24L01_H_ +#define M_NRF24L01_H_ + +#include +#include +#include + + +//Pins: +#define CSN1 2 +#define CE1 1 +#define NRF_MISO 4 +#define NRF_MOSI 3 +#define NRF_SCK 5 + + +//nRF24L01 Registers: +#define NREG_CONFIG 0x00 +#define NREG_EN_AA 0x01 +#define NREG_EN_RXADDR 0x02 +#define NREG_SETUP_AW 0x03 +#define NREG_SETUP_RETR 0x04 +#define NREG_RF_CH 0x05 +#define NREG_RF_SETUP 0x06 +#define NREG_STATUS 0x07 +#define NREG_OBSERVE_TX 0x08 +#define NREG_RPD 0x09 +#define NREG_RX_ADDR_P0 0x0A //5 bytes +#define NREG_RX_ADDR_P1 0x0B //5 bytes +#define NREG_RX_ADDR_P2 0x0C +#define NREG_RX_ADDR_P3 0x0D +#define NREG_RX_ADDR_P4 0x0E +#define NREG_RX_ADDR_P5 0x0F +#define NREG_TX_ADDR 0x10 //5 bytes +#define NREG_RX_PW_P0 0x11 +#define NREG_RX_PW_P1 0x12 +#define NREG_RX_PW_P2 0x13 +#define NREG_RX_PW_P3 0x14 +#define NREG_RX_PW_P4 0x15 +#define NREG_RX_PW_P5 0x16 +#define NREG_FIFOSTATUS 0x17 + +//Macros: +#define NRF_POWERDOWN NRF24L01_SetMode(0,1) +#define NRF_RXMODE NRF24L01_SetMode(1,1) +#define NRF_TXMODE NRF24L01_SetMode(1,0) + +//Function Prototypes +void NRF24L01_SPI_Setup( ); +void NRF24L01_SPI_TX(uint8_t); +uint8_t NRF24L01_SPI_RX( ); +void NRF24L01_W_Reg(uint8_t , uint8_t); +void NRF24L01_W_Reg_Long(uint8_t , uint8_t* , uint8_t); +uint8_t NRF24L01_R_Reg(uint8_t); +void NRF24L01_R_Reg_Long(uint8_t , uint8_t* , uint8_t); +uint8_t NRF24L01_TX_PAYLOAD(uint32_t*); +//uint8_t NRF24L01_R_RX_PAYLOAD(uint32_t*); +void NRF24L01_SetupnRF24L01(uint8_t, uint8_t*); +void NRF24L01_SetMode(uint8_t , uint8_t); +void NRF24L01_Flush_RX_FIFO( ); +void NRF24L01_Flush_TX_FIFO( ); + + +#endif /* M_NRF24L01_H_ */ diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_PRTC.h b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_PRTC.h new file mode 100644 index 0000000..1742896 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_PRTC.h @@ -0,0 +1,44 @@ +/* + * M_PRTC.h + * + * Created on: 04/09/2010 + * Author: MC + */ + +#ifndef M_PRTC_H_ +#define M_PRTC_H_ + +#include +#include +#include +#include + +struct RTCTime { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; + + uint8_t Day; + uint8_t Month; + int Year; +}; + + +//Function Prototypes: +void RTC_Setup(); +uint16_t RTC_GetCNT(); +uint8_t IntToBCD(uint8_t); +uint8_t BCDToInt(uint8_t); +void CopyTime (struct RTCTime*, struct RTCTime*); +void AddTimes(struct RTCTime*, struct RTCTime*); +void ClearTime(struct RTCTime*); +uint8_t CompareTimes (struct RTCTime* , struct RTCTime* ); +//uint8_t FirstTimeGreater (struct RTCTime* , struct RTCTime* ); +uint8_t ValidDateTime(struct RTCTime*); +uint8_t DaysInMonth(uint8_t , uint8_t ); +int str2Time(char*, struct RTCTime*); +void sPrintTime(char*, struct RTCTime* , char*); +void ZipTime(struct RTCTime*, uint8_t*); +void UnzipTime(struct RTCTime*, uint8_t*); + +#endif /* M_PRTC_H_ */ diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_USART.h b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_USART.h new file mode 100644 index 0000000..76c0c15 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/M_USART.h @@ -0,0 +1,96 @@ +/* + * M_USART.h + * + * Created on: 22/01/2010 + * Author: Matthew Cochrane + */ + +#ifndef M_USART_H_ +#define M_USART_H_ + +//Includes +#include +#include +#include + +//Defines +//Register & Bit Defines - These need to be altered for your specific chip +#define UDRRRegH UBRR0H +#define UDRRRegL UBRR0L +#define UCSRAReg UCSR0A +#define UCSRBReg UCSR0B +#define UCSRCReg UCSR0C +#define UDRReg UDR0 +#define U2XBit U2X0 +#define RXENBit RXEN0 +#define TXENBit TXEN0 +#define UCSZ0Bit UCSZ00 +#define UCSZ1Bit UCSZ01 +#define UDREBit UDRE0 +#define RXCBit RXC0 +//Formatting and Escape Sequences +#define ECC_COL_BLACK "0" +#define ECC_COL_RED "1" +#define ECC_COL_GREEN "2" +#define ECC_COL_YELLOW "3" +#define ECC_COL_BLUE "4" +#define ECC_COL_MAGENTA "5" +#define ECC_COL_CYAN "6" +#define ECC_COL_WHITE "7" +#define ECC_COL_RESET "9" +#define ESC_FG "3" +#define ESC_BG "4" +#define ESC_FONT_NORMAL "0" //ALL attributes off +#define ESC_FONT_BOLD "1" +#define ESC_FONT_ITALIC "3" //Not widely supported. Sometimes treated as inverse. +#define ESC_FONT_UNDERLINE "4" +#define ESC_FONT_NOUNDERLINE "24" +#define ESC_FONT_2XUNDERLINE "21" //Not widely supported +#define ESC_INTENSITY_FAINT "2" //Not widely supported +#define ESC_INTENSITY_NORMAL "22" //Not bold and not faint +#define ESC_BLINK_SLOW "5" //less than 150 per minute +#define ESC_BLINK_RAPID "6" //more than 150 per minute +#define ESC_BLINK_OFF "25" +#define ESC_IMG_NEG "7" //Inverse - swap foreground and background colours +#define ESC_IMG_POS "27" +#define ESC_CONCEAL "8" //Not widely supported. Hides any further writing +#define ESC_REVEAL "28" //conceal off + +//Macros +#define ESC_COL(type,col) type col +#define ESC_SGR1(var1) "\x1B[" var1 "m" +#define ESC_SGR2(var1, var2) "\x1B[" var1 ";" var2 "m" +#define ESC_SGR3(var1, var2, var3) "\x1B[" var1 ";" var2 ";" var3 "m" +#define ESC_SGR4(var1, var2, var3, var4) "\x1B[" var1 ";" var2 ";" var3 ";" var4 "m" +#define ESC_SGR5(var1, var2, var3, var4, var5) "\x1B[" var1 ";" var2 ";" var3 ";" var4 ";" var5 "m" +#define ESC_MOV_CUR_UP(n) "\x1B[" #n "A" +#define ESC_MOV_CUR_DOWN(n) "\x1B[" #n "B" +#define ESC_MOV_CUR_RIGHT(n) "\x1B[" #n "C" +#define ESC_MOV_CUR_LEFT(n) "\x1B[" #n "D" +#define ESC_MOV_CUR_ROW(n) "\x1B[" #n "A" +#define ESC_MOV_CUR_COL(n) "\x1B[" #n "A" +#define ESC_MOV_CUR(x,y) "\x1B[" #y ";" #x "H" //Row x, Col y +#define ESC_CLS "\x1B[2J" +#define ESC_CLR_LINE "\x1B[2K" +#define ESC_SCROLL_UP(n) "\x1B[" #n "S" +#define ESC_SCROLL_DOWN(n) "\x1B[" #n "T" +#define ESC_GET_CUR_POS "\x1B[6n" +#define ESC_CUR_SAVE "\x1B[s" +#define ESC_CUR_RESTORE "\x1B[u" + +//extern char s[80]; + +#define USART_printf_P(str, ...) do {sprintf_P(s, PSTR(str), __VA_ARGS__); USART_tx_String(s);} while (0) + +//Function Prototypes +void USART_Setup(unsigned int, unsigned char); +void USART_tx_Byte(char); +void USART_tx_String(const char *); +void USART_tx_String_P(const char *); +char USART_rx_Byte(unsigned int); +int USART_rx_Byte_nb( void ); +unsigned char USART_rx_String(char *, unsigned int); +void USART_UpdateTimers(void); + + +#endif /* M_USART_H_ */ diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/WIDTag.h b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/WIDTag.h new file mode 100644 index 0000000..0ea3775 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag/Includes/WIDTag.h @@ -0,0 +1,91 @@ +/* + * WIDTag.h + * + * Created on: 05/09/2010 + * Author: Matthew Cochrane + */ + +#ifndef WIDTAG_H_ +#define WIDTAG_H_ + +//Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "M_PRTC.h" +#include "M_USART.h" +#include "msTimer.h" +#include "NRF24L01PController.h" + +//Define +#define CPU8MHZ 1 +//#define CPU1MHZ 1 +#ifdef CPU8MHZ + #define UBRRVAL 0x0067 //for 8MHz (Double Speed) + #define TIMEOUT 253 //aprox 8 seconds + #define NORWAITTIMPRE (1< + 00 = -18dBm (7.0mA in TX mode) + 01 = -12dBm (7.5mA in TX mode) + 10 = -6dBm (9.0mA in TX mode) + 00 = 0dBm (11.3mA in TX mode) + */ + //Setup RF -> 2Mbps data rate, 0dBm output power + //NRF24L01_W_Reg(NREG_RF_SETUP, 0b00000111); + //Setup RF -> 1Mbps data rate, 0dBm output power + //NRF24L01_W_Reg(NREG_RF_SETUP, 0b00000011); + //Setup RF -> 250kbps data rate, 0dBm output power + NRF24L01_W_Reg(NREG_RF_SETUP, 0b00100111); + //uint8_t myData[5]; + //for (uint8_t i = 0; i < 5; i++) myData[i] = 0xE6; + //Set the address of RX Pipe 0 to pipeAddress + NRF24L01_W_Reg_Long(NREG_RX_ADDR_P0, (uint8_t*)pipeAddress, 5); + //Set TX Address to pipeAddress + NRF24L01_W_Reg_Long(NREG_TX_ADDR, (uint8_t*)pipeAddress, 5); + //Disable auto-ACK + NRF24L01_W_Reg(NREG_EN_AA, 0x00); + //Enable only pipe 0 + NRF24L01_W_Reg(NREG_EN_RXADDR, 0b00000001); + //Enable Pipe 0 and use payload width of 4 + NRF24L01_W_Reg(NREG_RX_PW_P0, 4); +} + +void NRF24L01_SetMode(uint8_t Power, uint8_t RXMode) { + uint8_t ConfigReg; + //Power up and put into RX mode + ConfigReg = NRF24L01_R_Reg(NREG_CONFIG); + + if (Power) + ConfigReg |= 0b00000010; + else + ConfigReg &= 0b11111101; + + if (RXMode) { + ConfigReg |= 0b00000001; + NRF24L01_W_Reg(NREG_CONFIG, ConfigReg); + if (Power) { + PORTB |= (1< 99) return 99; + uint8_t a = val/10; + return (a<<4)|(val-(a*10)); +} + +uint8_t BCDToInt (uint8_t val) { + if (val > 0x99) return 99; + return (val&0x0F)+10*(val>>4); +} + +void CopyTime (struct RTCTime* SrcTime, struct RTCTime* DstTime) { + for (uint8_t i = 0; i < 6; i++) + *(((uint8_t*)DstTime)+i) = *(((uint8_t*)SrcTime)+i); +} + +void ClearTime (struct RTCTime* Time1) { + Time1->Year = 0; + Time1->Month = 0; + Time1->Day = 0; + Time1->Hour = 0; + Time1->Minute = 0; + Time1->Second = 0; +} + +/*uint8_t FirstTimeGreater (struct RTCTime* Time1, struct RTCTime* Time2) { + //It is assumed that times are VALID! + + //if Time1 >= Time2 then TRUE + //if Time1 < Time2 then FALSE + + //if Time1 > Time2 then 1 + //if Time2 > Time1 then 0 + //if Time1 = Time2 then 2 + + if (Time2->Year > Time1->Year) { + return 0; + } else if (Time2->Year < Time1->Year) { + return 1; + } else { + if (Time2->Month > Time1->Month) { + return 0; + } else if (Time2->Month < Time1->Month) { + return 1; + } else { + if (Time2->Day > Time1->Day) { + return 0; + } else if (Time2->Day < Time1->Day) { + return 1; + } else { + if (Time2->Hour > Time1->Hour) { + return 0; + } else if (Time2->Hour < Time1->Hour) { + return 1; + } else { + if (Time2->Minute > Time1->Minute) { + return 0; + } else if (Time2->Minute < Time1->Minute) { + return 1; + } else { + if (Time2->Second > Time1->Second) { + return 0; + } else if (Time2->Second < Time1->Second) { + return 1; + } else { + return 2; + } + } + } + } + } + } + +}*/ + +uint8_t ValidDateTime(struct RTCTime* DT) { + uint8_t days; + if (DT->Second > 59 || DT->Minute > 59 || DT->Hour > 23) + return 0; + + if (DT->Day == 0 || DT->Month == 0 || DT->Month > 12) + return 0; + + days = DaysInMonth(DT->Month, DT->Year); + + if (DT->Day > days) + return 0; + + //If we got here.. it's a valid date! + return 1; +} + +void AddTimes (struct RTCTime* DateTime, struct RTCTime* AddTime) { + //DateTime = DateTime + AddTime + //AddTime can be a specific number of days month minutes etc. + //DateTime MUST BE A PROPER DATETIME! + //Double overflows are supported + //Overflows added from small time through to large time + //(ie. secs then mins then hours then days etc.) + + uint8_t a; + + DateTime->Second += AddTime->Second; + while (DateTime->Second > 59) { + DateTime->Second -= 60; + DateTime->Minute++; + } + DateTime->Minute += AddTime->Minute; + + while (DateTime->Minute > 59) { + DateTime->Minute -= 60; + DateTime->Hour++; + } + DateTime->Hour += AddTime->Hour; + while (DateTime->Hour > 23) { + DateTime->Hour -= 24; + DateTime->Day++; + } + DateTime->Day += AddTime->Day; + + while (DateTime->Day > (a = DaysInMonth(DateTime->Month, DateTime->Year))) { + DateTime->Day -= a; + DateTime->Month++; + } + DateTime->Month += AddTime->Month; + while (DateTime->Month > 12) { + DateTime->Month -= 12; + DateTime->Year++; + } + DateTime->Year += AddTime->Year; + //while (DateTime->Year > 99) { + // DateTime->Year -= 100; + //} +} + +uint8_t DaysInMonth(uint8_t Month, uint8_t Year) { + switch (Month) { + //31 day months + case 1://Jan + case 3://Mar + case 5://May + case 7://July + case 8://Aug + case 10://Oct + case 12://Dec + return 31; + break; + //30 day months + case 4://April + case 6://June + case 9://Sep + case 11://Nov + return 30; + break; + //The dreaded February!!! + case 2://Feb + //Is it a leap year?? + if(((Year + 2000) % 4 == 0 && (Year + 2000) % 100 != 0) || (Year + 2000) % 400 == 0) + return 29;//Yes + else + return 28;//No + break; + default: + return 0; + } +} + +void sPrintTime (char* __s, struct RTCTime* pTime, char* lbl) { + if (lbl[0] == '\0') + sprintf_P(__s,PSTR("%02d-%02d-%02d %02d:%02d:%02d") + , pTime->Year + , pTime->Month + , pTime->Day + , pTime->Hour + , pTime->Minute + , pTime->Second); + else + sprintf_P(__s,PSTR("%s: %02d-%02d-%02d %02d:%02d:%02d\r\n") + , lbl + , pTime->Year + , pTime->Month + , pTime->Day + , pTime->Hour + , pTime->Minute + , pTime->Second); + //USART_tx_String(s); +} + +int str2Time(char* __s, struct RTCTime* destTime) { + //Format of string: DDMMYYHHMMSS - that's 12 characters. + int i; + + //check that it's 'valid' + for(i = 0; i < 12; i++) { + if (__s[i] < '0' || __s[i] > '9') + return -1; + } + + destTime->Day = BCDToInt((uint8_t)(((__s[0]-'0')<<4)+(__s[1]-'0'))); + destTime->Month = BCDToInt((uint8_t)(((__s[2]-'0')<<4)+(__s[3]-'0'))); + destTime->Year = BCDToInt((uint8_t)(((__s[4]-'0')<<4)+(__s[5]-'0'))); + destTime->Hour = BCDToInt((uint8_t)(((__s[6]-'0')<<4)+(__s[7]-'0'))); + destTime->Minute = BCDToInt((uint8_t)(((__s[8]-'0')<<4)+(__s[9]-'0'))); + destTime->Second = BCDToInt((uint8_t)(((__s[10]-'0')<<4)+(__s[11]-'0'))); + + if (ValidDateTime(destTime)) + return 0; + else + return -1; +} + +void ZipTime(struct RTCTime* rawTime, uint8_t* zipTime) { + //using compression method B: + // Byte 1 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr1 Yr0 Sec5 Sec4 Sec3 Sec2 Sec1 Sec0 + // Byte 2 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr3 Yr2 Min5 Min4 Min3 Min2 Min1 Min0 + // Byte 3 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr6 Yr5 Yr4 Hr4 Hr3 Hr2 Hr1 Hr0 + // Byte 4 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr9 Yr8 Yr7 Day4 Day3 Day2 Day1 Day0 + // Byte 5 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr13 Yr12 Yr11 Yr10 Mon3 Mon2 Mon1 Mon0 + + zipTime[0] = (rawTime->Second&0x3F)|(rawTime->Year&0x0003); + zipTime[1] = (rawTime->Minute&0x3F)|(rawTime->Year&0x000C); + zipTime[2] = (rawTime->Hour&0x1F)|(rawTime->Year&0x0070); + zipTime[3] = (rawTime->Day&0x1F)|(rawTime->Year&0x0380); + zipTime[4] = (rawTime->Month&0x0F)|(rawTime->Year&0x3C00); + +} + +void UnzipTime(struct RTCTime* rawTime, uint8_t* zipTime) { + //using compression method B: + // Byte 1 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr1 Yr0 Sec5 Sec4 Sec3 Sec2 Sec1 Sec0 + // Byte 2 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr3 Yr2 Min5 Min4 Min3 Min2 Min1 Min0 + // Byte 3 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr6 Yr5 Yr4 Hr4 Hr3 Hr2 Hr1 Hr0 + // Byte 4 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr9 Yr8 Yr7 Day4 Day3 Day2 Day1 Day0 + // Byte 5 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr13 Yr12 Yr11 Yr10 Mon3 Mon2 Mon1 Mon0 + + + rawTime->Second = zipTime[0]&0x3F; + rawTime->Hour = zipTime[1]&0x3F; + rawTime->Minute = zipTime[2]&0x1F; + rawTime->Day = zipTime[3]&0x1F; + rawTime->Month = zipTime[4]&0x0F; + rawTime->Year = (uint16_t)(zipTime[0]&0xC0>>6)|(zipTime[1]&0xC0>>4)| + (zipTime[2]&0xE0>>1)|(zipTime[3]&0xE0<<3)|(zipTime[4]&0xF0<<7); + + + zipTime[0] = (rawTime->Second&0x3F)|(rawTime->Year&0x0003); + zipTime[1] = (rawTime->Minute&0x3F)|(rawTime->Year&0x000C); + zipTime[2] = (rawTime->Hour&0x1F)|(rawTime->Year&0x0070); + zipTime[3] = (rawTime->Day&0x1F)|(rawTime->Year&0x0380); + zipTime[4] = (rawTime->Month&0x0F)|(rawTime->Year&0x3C00); + +} diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag/Libs/M_USART.c b/Tag/Device_Firmware/V0.2.2/WIDTag/Libs/M_USART.c new file mode 100644 index 0000000..04c6850 --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag/Libs/M_USART.c @@ -0,0 +1,178 @@ +/* + * M_USART.c + * + * Created on: 22/01/2010 + * Author: Matty + */ + +#include "M_USART.h" + +volatile unsigned int Timer1; + +/* Function Name: SetupUSART +** Created On: 22/01/2010 +** Created By: Matthew Cochrane +** Description: Sets up the USART in asynchronous mode to a Baud rate specified by +** UBRR and UU2X with 8 data bits no parity and one stop bit. +** Inputs: +** UBRR - Value to set the UBRR register to +** UU2X - Boolean variable which if true will enable double data rate for the USART. +*/ +void USART_Setup (unsigned int UBRR, unsigned char UU2X) { + //Setup Baud Rate + UDRRRegH = (unsigned char)(UBRR >> 8); + UDRRRegL = (unsigned char)(UBRR & 0x00FF); + + //Setup Double Speed Setting + if (UU2X) { + UCSRAReg = (1< 0) Timer1--; +} + + + + + diff --git a/Tag/Device_Firmware/V0.2.2/WIDTag/Src/WIDTag.c b/Tag/Device_Firmware/V0.2.2/WIDTag/Src/WIDTag.c new file mode 100644 index 0000000..f1a3e0e --- /dev/null +++ b/Tag/Device_Firmware/V0.2.2/WIDTag/Src/WIDTag.c @@ -0,0 +1,494 @@ +/* + * WIDTag.c + * + * Name: Wireless ID Tag + * Created on: 05/09/2010 + * Author: Matthew Cochrane + * MCU: ATMEGA328P + * Fuse Bits: + * High - 0xD9 + * Low - 0xE2 + * + */ + +#include "WIDTag.h" + +char s[80]; +char s1[50]; +volatile unsigned char patience; +volatile uint8_t Wakeup_Source = WAKEUP_SOURCE_NONE; +uint32_t Device_ID; +uint8_t RF_ID[5]; +uint8_t RF_Chan; +uint8_t DevArmed; +//volatile uint16_t timer10ms = 0; +struct RTCTime RTC_c_Time; +struct RTCTime RTC_Period; +//struct RTCTime TX_Period; +uint8_t TX_Period; +uint8_t PrintTime = 0; +volatile uint8_t TX_Delay = 0; //Also used in M_NRF24L01.c to check for tx timeout +uint8_t modDelay = 0; + +ISR(TIMER0_OVF_vect) { + USART_UpdateTimers(); +} + +// ISR(TIMER0_COMPA_vect) { +// if (timer10ms) --timer10ms; +// else TCCR0B = 0; +// } + +ISR(PCINT2_vect) { + Wakeup_Source = WAKEUP_SOURCE_UART; +} + +ISR(TIMER2_OVF_vect) { + Wakeup_Source = WAKEUP_SOURCE_RTC; + AddTimes(&RTC_c_Time, &RTC_Period); + if (TX_Delay) --TX_Delay; + //NOTE: + // Ran for 10 hours WITHOUT xtal capacitors and the clock was out by about a second. + // After less than a day of running without caps its ~ 5s out (updated windows time before and after) +} + +ISR(TIMER2_COMPA_vect) { + +} + +void inline Nordic_Setup_All(void) { + NRF24L01P_Create(msTimer_StartTimer, msTimer_StartTimer, msTimer_GetCounterTicks); + NRF24L01P_SetupInterface(RF_Chan, RF_ID); + NRF24L01P_SetMode(MODE_TX); + NRF24L01P_FlushTxFIFO(); + NRF24L01P_SetMode(MODE_POWERDOWN); +} + +int main(void) { + + uint8_t i, j; + + /*//TEST CODE// + //0 - LED + DDRC = (1<<0); + //USART Tx + DDRD = (1<<1); + + // Enable pullups + PORTC = 0b00111000; + PORTD = 0b11111111; + PRR = ~((1<")); + USART_tx_String_P(PSTR(">")); + //flush USART RX buffer + while (USART_rx_Byte_nb() != -1); + //Receive byte + retChar = USART_rx_Byte(TIMEOUT); + switch (retChar) { + case 'T': + USART_tx_String_P(PSTR("ET (DDMMYYHHMMSS):\r\n"));//Enter Date/Time (DDMMYYHHMMSS).\r\n>")); + + for (i = 0; i < 12; i++) + s[i] = USART_rx_Byte(TIMEOUT<<2); + s[12] = '\0'; + + if (str2Time(s, &tmpTime) == 0) + CopyTime(&tmpTime, &RTC_c_Time); + + sPrintTime(s, &RTC_c_Time, "Time"); + USART_tx_String(s); + break; + case 'P': + USART_tx_String_P(PSTR("ETX (MSS):\r\n"));//Enter TX Period (MSS).\r\n>")); + + s[3] = 0; + for (i = 0; i < 3; i++) { + s[i] = USART_rx_Byte(TIMEOUT<<1)-'0'; + if (s[i] > 9 || s[i] < 0) + s[3] = 1; + } + + if (!s[3]) { + i = s[0]*60+s[1]*10+s[2]; + if (i > 255) { + USART_tx_String_P(PSTR("Bad\r\n"));//Invalid TX period entered.\r\n")); + } else { + TX_Period = i; + TX_Delay = i; + eeprom_write_byte((uint8_t*)TXPERADD,TX_Period); + //USART_printf_P("TX Period set to %d seconds\r\n", TX_Period); + USART_printf_P("TX %ds\r\n", TX_Period); + } + } else { + USART_tx_String_P(PSTR("Bad\r\n"));//Invalid TX period entered.\r\n")); + } + break; + case 's': + TXPayload(); + break; + case 'N': + ;uint8_t tmpDat; + uint8_t i; + for (i = 0; i <= 0x17; i++) { + NRF24L01P_ReadRegister(i, &tmpDat); + USART_printf_P("Reg: 0x%02X, Val:0x%02X\r\n", i, tmpDat); + } + break; + case 't': + PrintTime ^= 1; + //USART_printf_P("PrintTime :0x%02X\r\n", PrintTime); + break; + case '?': + ReadAllVarsFromEEPROM(); + //DEV_ID + USART_printf_P("DEV_ID:%08lX\r\n", Device_ID); + //RFID + USART_tx_String_P(PSTR("RFID:")); + for (i = 0; i < 4; i++) { + USART_printf_P("%02X-", RF_ID[i]); + } + USART_printf_P("%02X\r\n", RF_ID[4]); + //RFCHAN + USART_printf_P("RFCHAN:%d\r\n", RF_Chan); + //ARMED + USART_printf_P("DEVARMED:%u\r\n", DevArmed); + //TXPERIOD + USART_printf_P("TXPERIOD:%d\r\n", TX_Period); + break; + case '*': + //DEV_ID + s[0] = 's'; + USART_tx_String_P(PSTR("DEV_ID (XXXXXXXX):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + Device_ID = (uint32_t)strtoul(s, (char **)NULL,16); + WriteEEPROM((uint8_t*)&Device_ID, 4,DEVIDADD); + } + s[0] = 's'; + //RFID + USART_tx_String_P(PSTR("RFID (XX-XX-XX-XX-XX):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + for (i = 0; i < 5; i++) + RF_ID[i] = (uint8_t)strtoul(s+i*3, (char **)NULL,16); + WriteEEPROM(RF_ID,5,RFIDADD); + RFedit = 1; + } + s[0] = 's'; + //RFCHAN + USART_tx_String_P(PSTR("RFCHAN (###):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + RF_Chan = 100*(s[0]-'0') + 10*(s[1]-'0') + (s[2]-'0'); + eeprom_write_byte((uint8_t*)RFCHANADD, RF_Chan); + RFedit = 1; + } + s[0] = 's'; + //DEVARMED + USART_tx_String_P(PSTR("DEVARMED (X):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + DevArmed = s[0]-'0'; + eeprom_write_byte((uint8_t*)DEVARMEDADD,DevArmed); + DevArmSetup(); + } + s[0] = 's'; + //TXPERIOD + USART_tx_String_P(PSTR("TXPERIOD (MSS):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + i = (s[0]-'0')*60+(s[1]-'0')*10+(s[2]-'0'); + //if (i < 255) { + TX_Period = i; + TX_Delay = i; + eeprom_write_byte((uint8_t*)TXPERADD,TX_Period); + //} + } + + if (RFedit && DevArmed != ARM_SHELF) { + //Setup the Nordic Chip with new values + Nordic_Setup_All(); + } + break; + } + //USART_tx_String_P(PSTR("Going to sleep. Press any key to wake.\r\n")); + USART_tx_String_P(PSTR("Sleep.\r\n")); + +} + +/*inline void WriteTimeEEPROM(struct RTCTime* mTime, uint16_t Address) { + WriteEEPROM((uint8_t*)mTime, 5, Address); +} + +inline void ReadTimeEEPROM(struct RTCTime* mTime, uint16_t Address) { + ReadEEPROM((uint8_t*)mTime, 5, Address); +}*/ + +void ReadEEPROM(uint8_t* Data, uint8_t Length, uint16_t Address) { + for (int i = 0; i < Length; i++) + *Data++ = eeprom_read_byte((uint8_t*)Address++); +} + +void WriteEEPROM(uint8_t* Data, uint8_t Length, uint16_t Address) { + for (int i = 0; i < Length; i++) + eeprom_write_byte((uint8_t*)Address++, *Data++); +} + +static inline void delay_ms(uint16_t ms) { + do { + _delay_ms(1); + } while (--ms != 0); +} + +// void StartTim10ms(uint16_t Time) { +// PRR &= ~(1< + + + 2.0 + 5.0 + {77bcdbd5-eb6f-4198-9537-80123c2374b8} + ATmega88PA + none + Executable + C + $(MSBuildProjectName).elf + $(MSBuildProjectDirectory)\$(Configuration) + True + + + + + C:\Program Files (x86)\Atmel\AVR Studio 5.0\AVR ToolChain\bin + + + WIDTag + WIDTag + WIDTag + debugWIRE + com.atmel.avrdbg.tool.avrdragon + + com.atmel.avrdbg.tool.avrdragon + AVR Dragon + 00A20000865C + + 127.0.0.1 + 50870 + False + + + debugWIRE + + 1000000 + 1000000 + 150000 + false + false + 0 + 0 + 0 + 0 + + + + + com.atmel.avrdbg.tool.simulator + AVR Simulator + + + + 127.0.0.1 + 50870 + False + + + True + + + + + True + True + Optimize for size (-Os) + True + True + None + True + + + + + True + True + True + True + + + + + True + True + + + F_CPU=8000000UL + + + + + ../Includes + ../Includes/util + + + Optimize for size (-Os) + True + True + Default (-g2) + True + Default (-g2) + + + + + +
0x400
+
+
+
+ True + True + True + True + WIDTag.elf + Executable +
+ + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + + + + + + + +
\ No newline at end of file diff --git a/Tag/Device_Firmware/V1.1/WIDTag.avrsln b/Tag/Device_Firmware/V1.1/WIDTag.avrsln new file mode 100644 index 0000000..e5580fd --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag.avrsln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# AvrStudio Solution File, Format Version 11.00 +Project("{D1100916-62DA-4D80-A9B4-55A1E7CCEEB3}") = "WIDTag", "WIDTag\WIDTag.avrgccproj", "{77BCDBD5-EB6F-4198-9537-80123C2374B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|AVR = Debug|AVR + Release|AVR = Release|AVR + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Debug|AVR.ActiveCfg = Debug|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Debug|AVR.Build.0 = Debug|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Release|AVR.ActiveCfg = Release|AVR + {77BCDBD5-EB6F-4198-9537-80123C2374B8}.Release|AVR.Build.0 = Release|AVR + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Tag/Device_Firmware/V1.1/WIDTag.avrsuo b/Tag/Device_Firmware/V1.1/WIDTag.avrsuo new file mode 100644 index 0000000..6f55330 Binary files /dev/null and b/Tag/Device_Firmware/V1.1/WIDTag.avrsuo differ diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/HW_IO.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/HW_IO.h new file mode 100644 index 0000000..b71558e --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/HW_IO.h @@ -0,0 +1,38 @@ +/* + * IO.h + * + * Created on: 12/10/2011 + * Author: MC + */ + +#ifndef IO_H_ +#define IO_H_ + +#include + +//Typedefs: +typedef uint8_t SPIData_t; +typedef enum pinstate { + PIN_LOW = 0, + PIN_HIGH = 1, + PIN_UNCHANGED = 2, +} pinState_t; + +//Defines: +#define NRF_PORT PORTB +#define NRF_DDR DDRB +#define NRF_CE 1 //O +#define NRF_CSN 2 //O +#define NRF_MOSI 3 //O +#define NRF_MISO 4 //I +#define NRF_SCK 5 //O + +//Function Prototypes: +void IO_SPI_TX(SPIData_t data); +SPIData_t IO_SPI_RX(void); +void IO_NRF_CSN(pinState_t data); +void IO_NRF_CE(pinState_t data); +void IO_NRF_Setup_Pins(void); +void IO_NRF_Setup_SPI(void); + +#endif /* IO_H_ */ diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_NRF24L01.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_NRF24L01.h new file mode 100644 index 0000000..26cd0f3 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_NRF24L01.h @@ -0,0 +1,71 @@ +/* + * M_NRF24L01.h + * + * Created on: 09/03/2010 + * Author: Matty + */ + +#ifndef M_NRF24L01_H_ +#define M_NRF24L01_H_ + +#include +#include +#include + + +//Pins: +#define CSN1 2 +#define CE1 1 +#define NRF_MISO 4 +#define NRF_MOSI 3 +#define NRF_SCK 5 + + +//nRF24L01 Registers: +#define NREG_CONFIG 0x00 +#define NREG_EN_AA 0x01 +#define NREG_EN_RXADDR 0x02 +#define NREG_SETUP_AW 0x03 +#define NREG_SETUP_RETR 0x04 +#define NREG_RF_CH 0x05 +#define NREG_RF_SETUP 0x06 +#define NREG_STATUS 0x07 +#define NREG_OBSERVE_TX 0x08 +#define NREG_RPD 0x09 +#define NREG_RX_ADDR_P0 0x0A //5 bytes +#define NREG_RX_ADDR_P1 0x0B //5 bytes +#define NREG_RX_ADDR_P2 0x0C +#define NREG_RX_ADDR_P3 0x0D +#define NREG_RX_ADDR_P4 0x0E +#define NREG_RX_ADDR_P5 0x0F +#define NREG_TX_ADDR 0x10 //5 bytes +#define NREG_RX_PW_P0 0x11 +#define NREG_RX_PW_P1 0x12 +#define NREG_RX_PW_P2 0x13 +#define NREG_RX_PW_P3 0x14 +#define NREG_RX_PW_P4 0x15 +#define NREG_RX_PW_P5 0x16 +#define NREG_FIFOSTATUS 0x17 + +//Macros: +#define NRF_POWERDOWN NRF24L01_SetMode(0,1) +#define NRF_RXMODE NRF24L01_SetMode(1,1) +#define NRF_TXMODE NRF24L01_SetMode(1,0) + +//Function Prototypes +void NRF24L01_SPI_Setup( ); +void NRF24L01_SPI_TX(uint8_t); +uint8_t NRF24L01_SPI_RX( ); +void NRF24L01_W_Reg(uint8_t , uint8_t); +void NRF24L01_W_Reg_Long(uint8_t , uint8_t* , uint8_t); +uint8_t NRF24L01_R_Reg(uint8_t); +void NRF24L01_R_Reg_Long(uint8_t , uint8_t* , uint8_t); +uint8_t NRF24L01_TX_PAYLOAD(uint32_t*); +//uint8_t NRF24L01_R_RX_PAYLOAD(uint32_t*); +void NRF24L01_SetupnRF24L01(uint8_t, uint8_t*); +void NRF24L01_SetMode(uint8_t , uint8_t); +void NRF24L01_Flush_RX_FIFO( ); +void NRF24L01_Flush_TX_FIFO( ); + + +#endif /* M_NRF24L01_H_ */ diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_PRTC.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_PRTC.h new file mode 100644 index 0000000..1742896 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_PRTC.h @@ -0,0 +1,44 @@ +/* + * M_PRTC.h + * + * Created on: 04/09/2010 + * Author: MC + */ + +#ifndef M_PRTC_H_ +#define M_PRTC_H_ + +#include +#include +#include +#include + +struct RTCTime { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; + + uint8_t Day; + uint8_t Month; + int Year; +}; + + +//Function Prototypes: +void RTC_Setup(); +uint16_t RTC_GetCNT(); +uint8_t IntToBCD(uint8_t); +uint8_t BCDToInt(uint8_t); +void CopyTime (struct RTCTime*, struct RTCTime*); +void AddTimes(struct RTCTime*, struct RTCTime*); +void ClearTime(struct RTCTime*); +uint8_t CompareTimes (struct RTCTime* , struct RTCTime* ); +//uint8_t FirstTimeGreater (struct RTCTime* , struct RTCTime* ); +uint8_t ValidDateTime(struct RTCTime*); +uint8_t DaysInMonth(uint8_t , uint8_t ); +int str2Time(char*, struct RTCTime*); +void sPrintTime(char*, struct RTCTime* , char*); +void ZipTime(struct RTCTime*, uint8_t*); +void UnzipTime(struct RTCTime*, uint8_t*); + +#endif /* M_PRTC_H_ */ diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_USART.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_USART.h new file mode 100644 index 0000000..76c0c15 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/M_USART.h @@ -0,0 +1,96 @@ +/* + * M_USART.h + * + * Created on: 22/01/2010 + * Author: Matthew Cochrane + */ + +#ifndef M_USART_H_ +#define M_USART_H_ + +//Includes +#include +#include +#include + +//Defines +//Register & Bit Defines - These need to be altered for your specific chip +#define UDRRRegH UBRR0H +#define UDRRRegL UBRR0L +#define UCSRAReg UCSR0A +#define UCSRBReg UCSR0B +#define UCSRCReg UCSR0C +#define UDRReg UDR0 +#define U2XBit U2X0 +#define RXENBit RXEN0 +#define TXENBit TXEN0 +#define UCSZ0Bit UCSZ00 +#define UCSZ1Bit UCSZ01 +#define UDREBit UDRE0 +#define RXCBit RXC0 +//Formatting and Escape Sequences +#define ECC_COL_BLACK "0" +#define ECC_COL_RED "1" +#define ECC_COL_GREEN "2" +#define ECC_COL_YELLOW "3" +#define ECC_COL_BLUE "4" +#define ECC_COL_MAGENTA "5" +#define ECC_COL_CYAN "6" +#define ECC_COL_WHITE "7" +#define ECC_COL_RESET "9" +#define ESC_FG "3" +#define ESC_BG "4" +#define ESC_FONT_NORMAL "0" //ALL attributes off +#define ESC_FONT_BOLD "1" +#define ESC_FONT_ITALIC "3" //Not widely supported. Sometimes treated as inverse. +#define ESC_FONT_UNDERLINE "4" +#define ESC_FONT_NOUNDERLINE "24" +#define ESC_FONT_2XUNDERLINE "21" //Not widely supported +#define ESC_INTENSITY_FAINT "2" //Not widely supported +#define ESC_INTENSITY_NORMAL "22" //Not bold and not faint +#define ESC_BLINK_SLOW "5" //less than 150 per minute +#define ESC_BLINK_RAPID "6" //more than 150 per minute +#define ESC_BLINK_OFF "25" +#define ESC_IMG_NEG "7" //Inverse - swap foreground and background colours +#define ESC_IMG_POS "27" +#define ESC_CONCEAL "8" //Not widely supported. Hides any further writing +#define ESC_REVEAL "28" //conceal off + +//Macros +#define ESC_COL(type,col) type col +#define ESC_SGR1(var1) "\x1B[" var1 "m" +#define ESC_SGR2(var1, var2) "\x1B[" var1 ";" var2 "m" +#define ESC_SGR3(var1, var2, var3) "\x1B[" var1 ";" var2 ";" var3 "m" +#define ESC_SGR4(var1, var2, var3, var4) "\x1B[" var1 ";" var2 ";" var3 ";" var4 "m" +#define ESC_SGR5(var1, var2, var3, var4, var5) "\x1B[" var1 ";" var2 ";" var3 ";" var4 ";" var5 "m" +#define ESC_MOV_CUR_UP(n) "\x1B[" #n "A" +#define ESC_MOV_CUR_DOWN(n) "\x1B[" #n "B" +#define ESC_MOV_CUR_RIGHT(n) "\x1B[" #n "C" +#define ESC_MOV_CUR_LEFT(n) "\x1B[" #n "D" +#define ESC_MOV_CUR_ROW(n) "\x1B[" #n "A" +#define ESC_MOV_CUR_COL(n) "\x1B[" #n "A" +#define ESC_MOV_CUR(x,y) "\x1B[" #y ";" #x "H" //Row x, Col y +#define ESC_CLS "\x1B[2J" +#define ESC_CLR_LINE "\x1B[2K" +#define ESC_SCROLL_UP(n) "\x1B[" #n "S" +#define ESC_SCROLL_DOWN(n) "\x1B[" #n "T" +#define ESC_GET_CUR_POS "\x1B[6n" +#define ESC_CUR_SAVE "\x1B[s" +#define ESC_CUR_RESTORE "\x1B[u" + +//extern char s[80]; + +#define USART_printf_P(str, ...) do {sprintf_P(s, PSTR(str), __VA_ARGS__); USART_tx_String(s);} while (0) + +//Function Prototypes +void USART_Setup(unsigned int, unsigned char); +void USART_tx_Byte(char); +void USART_tx_String(const char *); +void USART_tx_String_P(const char *); +char USART_rx_Byte(unsigned int); +int USART_rx_Byte_nb( void ); +unsigned char USART_rx_String(char *, unsigned int); +void USART_UpdateTimers(void); + + +#endif /* M_USART_H_ */ diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/NRF24L01PController.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/NRF24L01PController.h new file mode 100644 index 0000000..64cd188 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/NRF24L01PController.h @@ -0,0 +1,91 @@ +/* + * NRF24L01PController.h + * + * Created on: 12/10/2011 + * Author: MC + */ + +#ifndef NRF24L01PCONTROLLER_H_ +#define NRF24L01PCONTROLLER_H_ + +#include +#include "RuntimeError.h" + +//Enums: +enum { + NRF24L01P_SUCCESS = 0, + NRF24L01P_INVALID_INPUT = -1, + NRF24L01P_TIMEOUT = -2, + NRF24L01P_WRONG_STATE = -3, + NRF24L01P_DATA_UNAVAILABLE = -4, +}; + +typedef enum NRF24L01P_ReadWriteRegRetVal { + NRF_rw_ret_success = NRF24L01P_SUCCESS, + NRF_rw_ret_invalid_input = NRF24L01P_INVALID_INPUT, +} NRF24L01P_RW_Reg_RetVal_t; + +typedef enum NRF24L01P_TxRxPayloadRetVal { + NRF_TxRx_ret_success = NRF24L01P_SUCCESS, + NRF_TxRx_ret_invalid_input = NRF24L01P_INVALID_INPUT, + NRF_TxRx_ret_timeout = NRF24L01P_TIMEOUT, + NRF_TxRx_ret_wrong_mode = NRF24L01P_WRONG_STATE, + NRF_TxRx_ret_rx_fifo_empty = NRF24L01P_DATA_UNAVAILABLE, +} NRF24L01P_TxRx_RetVal_t; + +typedef enum NRF24L01P_RegAdd { + NREG_CONFIG = 0x00, + NREG_EN_AA = 0x01, + NREG_EN_RXADDR = 0x02, + NREG_SETUP_AW = 0x03, + NREG_SETUP_RETR = 0x04, + NREG_RF_CH = 0x05, + NREG_RF_SETUP = 0x06, + NREG_STATUS = 0x07, + NREG_OBSERVE_TX = 0x08, + NREG_RPD = 0x09, + NREG_RX_ADDR_P0 = 0x0A, //5 bytes + NREG_RX_ADDR_P1 = 0x0B, //5 bytes + NREG_RX_ADDR_P2 = 0x0C, + NREG_RX_ADDR_P3 = 0x0D, + NREG_RX_ADDR_P4 = 0x0E, + NREG_RX_ADDR_P5 = 0x0F, + NREG_TX_ADDR = 0x10, //5 bytes + NREG_RX_PW_P0 = 0x11, + NREG_RX_PW_P1 = 0x12, + NREG_RX_PW_P2 = 0x13, + NREG_RX_PW_P3 = 0x14, + NREG_RX_PW_P4 = 0x15, + NREG_RX_PW_P5 = 0x16, + NREG_FIFOSTATUS = 0x17, + NREG_DYNPD = 0x1C, +} NRF24L01P_RegAdd_t; + +typedef enum NRF24L01P_Mode { + MODE_POWERDOWN, + MODE_TX, + MODE_RX, + MODE_UNKNOWN, +} NRF24L01P_Mode_t; + +//Defines: +//#define NRF24L01P_USE_RUNTIME_ERRORS 1 + +//Function Prototypes: +void NRF24L01P_Create(void(*StartTimerFuncPtr)(), void(*StopTimerFuncPtr)(), uint16_t(*getCounterTickFuncPtr)()); +void NRF24L01P_Destroy(void); +extern NRF24L01P_Mode_t (*NRF24L01P_GetMode)(void); +extern NRF24L01P_RW_Reg_RetVal_t (*NRF24L01P_ReadRegister)(NRF24L01P_RegAdd_t address, uint8_t* data); +extern NRF24L01P_RW_Reg_RetVal_t (*NRF24L01P_WriteRegister)(NRF24L01P_RegAdd_t address, uint8_t data); +extern int8_t (*NRF24L01P_SetMode)(NRF24L01P_Mode_t mode); +void NRF24L01P_FlushTxFIFO(void); +void NRF24L01P_FlushRxFIFO(void); +NRF24L01P_TxRx_RetVal_t NRF24L01P_TxPayload(uint32_t data); +NRF24L01P_TxRx_RetVal_t NRF24L01P_RxPayload(uint32_t* data); +extern NRF24L01P_RW_Reg_RetVal_t (*NRF24L01P_WriteRegisterLong)(NRF24L01P_RegAdd_t address, uint8_t* data, uint8_t length); +void NRF24L01P_SetupInterface(uint8_t chan, uint8_t* id); + +#define CPUSLEEP_0m5s 0x0F //0.4883ms with prescalar of 1 +void CPUSleep_Time(uint8_t OCR2A_set); + +#endif /* NRF24L01PCONTROLLER_H_ */ diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/WIDTag.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/WIDTag.h new file mode 100644 index 0000000..20c0e38 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/WIDTag.h @@ -0,0 +1,97 @@ +/* + * WIDTag.h + * + * Created on: 05/09/2010 + * Author: Matthew Cochrane + */ + +#ifndef WIDTAG_H_ +#define WIDTAG_H_ + +//Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "M_PRTC.h" +#include "M_USART.h" +#include "msTimer.h" +#include "NRF24L01PController.h" + +//Define +#define CPU8MHZ 1 +//#define CPU1MHZ 1 +#ifdef CPU8MHZ + #define UBRRVAL 0x0067 //for 8MHz (Double Speed) + #define TIMEOUT 253 //aprox 8 seconds + #define NORWAITTIMPRE (1< + +void msTimer_StartTimer(void); +void msTimer_StopTimer(void); +uint16_t msTimer_GetCounterTicks(void); + + +#endif /* MSTIMER_H_ */ \ No newline at end of file diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/util/RuntimeError.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/util/RuntimeError.h new file mode 100644 index 0000000..72e1d6e --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/util/RuntimeError.h @@ -0,0 +1,31 @@ +/*- ------------------------------------------------------------------ -*/ +/*- Copyright (c) James W. Grenning -- All Rights Reserved -*/ +/*- For use by owners of Test-Driven Development for Embedded C, -*/ +/*- and attendees of Renaissance Software Consulting, Co. training -*/ +/*- classes. -*/ +/*- -*/ +/*- Available at http://pragprog.com/titles/jgade/ -*/ +/*- ISBN 1-934356-62-X, ISBN13 978-1-934356-62-3 -*/ +/*- -*/ +/*- Authorized users may use this source code in your own -*/ +/*- projects, however the source code may not be used to -*/ +/*- create training material, courses, books, articles, and -*/ +/*- the like. We make no guarantees that this source code is -*/ +/*- fit for any purpose. -*/ +/*- -*/ +/*- www.renaissancesoftware.net james@renaissancesoftware.net -*/ +/*- ------------------------------------------------------------------ -*/ + + +#ifndef D_RuntimeError_H +#define D_RuntimeError_H + +/* START: RuntimeError */ +void RuntimeError(const char * message, int parameter, + const char * file, int line); + +#define RUNTIME_ERROR(description, parameter)\ + RuntimeError(description, parameter, __FILE__, __LINE__) +/* END: RuntimeError */ + +#endif diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Includes/util/common.h b/Tag/Device_Firmware/V1.1/WIDTag/Includes/util/common.h new file mode 100644 index 0000000..9b85a0d --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Includes/util/common.h @@ -0,0 +1,41 @@ +/*- ------------------------------------------------------------------ -*/ +/*- Copyright (c) James W. Grenning -- All Rights Reserved -*/ +/*- For use by owners of Test-Driven Development for Embedded C, -*/ +/*- and attendees of Renaissance Software Consulting, Co. training -*/ +/*- classes. -*/ +/*- -*/ +/*- Available at http://pragprog.com/titles/jgade/ -*/ +/*- ISBN 1-934356-62-X, ISBN13 978-1-934356-62-3 -*/ +/*- -*/ +/*- Authorized users may use this source code in your own -*/ +/*- projects, however the source code may not be used to -*/ +/*- create training material, courses, books, articles, and -*/ +/*- the like. We make no guarantees that this source code is -*/ +/*- fit for any purpose. -*/ +/*- -*/ +/*- www.renaissancesoftware.net james@renaissancesoftware.net -*/ +/*- ------------------------------------------------------------------ -*/ + + + + +#ifndef D_common_H +#define D_common_H + +#ifndef BOOL +#define BOOL int +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#endif diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Libs/HW_IO_ATMEGA88.c b/Tag/Device_Firmware/V1.1/WIDTag/Libs/HW_IO_ATMEGA88.c new file mode 100644 index 0000000..2e4c0e0 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Libs/HW_IO_ATMEGA88.c @@ -0,0 +1,51 @@ +/* + * HW_IO_ATMEGA88.c + * + * Created: 15/10/2011 10:47:55 PM + * Author: MC + */ + +#include "HW_IO.h" +#include + +void IO_SPI_TX(SPIData_t data) { + SPDR = data; + while(!(SPSR & (1< + 00 = -18dBm (7.0mA in TX mode) + 01 = -12dBm (7.5mA in TX mode) + 10 = -6dBm (9.0mA in TX mode) + 00 = 0dBm (11.3mA in TX mode) + */ + //Setup RF -> 2Mbps data rate, 0dBm output power + //NRF24L01_W_Reg(NREG_RF_SETUP, 0b00000111); + //Setup RF -> 1Mbps data rate, 0dBm output power + //NRF24L01_W_Reg(NREG_RF_SETUP, 0b00000011); + //Setup RF -> 250kbps data rate, 0dBm output power + NRF24L01_W_Reg(NREG_RF_SETUP, 0b00100111); + //uint8_t myData[5]; + //for (uint8_t i = 0; i < 5; i++) myData[i] = 0xE6; + //Set the address of RX Pipe 0 to pipeAddress + NRF24L01_W_Reg_Long(NREG_RX_ADDR_P0, (uint8_t*)pipeAddress, 5); + //Set TX Address to pipeAddress + NRF24L01_W_Reg_Long(NREG_TX_ADDR, (uint8_t*)pipeAddress, 5); + //Disable auto-ACK + NRF24L01_W_Reg(NREG_EN_AA, 0x00); + //Enable only pipe 0 + NRF24L01_W_Reg(NREG_EN_RXADDR, 0b00000001); + //Enable Pipe 0 and use payload width of 4 + NRF24L01_W_Reg(NREG_RX_PW_P0, 4); +} + +void NRF24L01_SetMode(uint8_t Power, uint8_t RXMode) { + uint8_t ConfigReg; + //Power up and put into RX mode + ConfigReg = NRF24L01_R_Reg(NREG_CONFIG); + + if (Power) + ConfigReg |= 0b00000010; + else + ConfigReg &= 0b11111101; + + if (RXMode) { + ConfigReg |= 0b00000001; + NRF24L01_W_Reg(NREG_CONFIG, ConfigReg); + if (Power) { + PORTB |= (1< 99) return 99; + uint8_t a = val/10; + return (a<<4)|(val-(a*10)); +} + +uint8_t BCDToInt (uint8_t val) { + if (val > 0x99) return 99; + return (val&0x0F)+10*(val>>4); +} + +void CopyTime (struct RTCTime* SrcTime, struct RTCTime* DstTime) { + for (uint8_t i = 0; i < 6; i++) + *(((uint8_t*)DstTime)+i) = *(((uint8_t*)SrcTime)+i); +} + +void ClearTime (struct RTCTime* Time1) { + Time1->Year = 0; + Time1->Month = 0; + Time1->Day = 0; + Time1->Hour = 0; + Time1->Minute = 0; + Time1->Second = 0; +} + +/*uint8_t FirstTimeGreater (struct RTCTime* Time1, struct RTCTime* Time2) { + //It is assumed that times are VALID! + + //if Time1 >= Time2 then TRUE + //if Time1 < Time2 then FALSE + + //if Time1 > Time2 then 1 + //if Time2 > Time1 then 0 + //if Time1 = Time2 then 2 + + if (Time2->Year > Time1->Year) { + return 0; + } else if (Time2->Year < Time1->Year) { + return 1; + } else { + if (Time2->Month > Time1->Month) { + return 0; + } else if (Time2->Month < Time1->Month) { + return 1; + } else { + if (Time2->Day > Time1->Day) { + return 0; + } else if (Time2->Day < Time1->Day) { + return 1; + } else { + if (Time2->Hour > Time1->Hour) { + return 0; + } else if (Time2->Hour < Time1->Hour) { + return 1; + } else { + if (Time2->Minute > Time1->Minute) { + return 0; + } else if (Time2->Minute < Time1->Minute) { + return 1; + } else { + if (Time2->Second > Time1->Second) { + return 0; + } else if (Time2->Second < Time1->Second) { + return 1; + } else { + return 2; + } + } + } + } + } + } + +}*/ + +uint8_t ValidDateTime(struct RTCTime* DT) { + uint8_t days; + if (DT->Second > 59 || DT->Minute > 59 || DT->Hour > 23) + return 0; + + if (DT->Day == 0 || DT->Month == 0 || DT->Month > 12) + return 0; + + days = DaysInMonth(DT->Month, DT->Year); + + if (DT->Day > days) + return 0; + + //If we got here.. it's a valid date! + return 1; +} + +void AddTimes (struct RTCTime* DateTime, struct RTCTime* AddTime) { + //DateTime = DateTime + AddTime + //AddTime can be a specific number of days month minutes etc. + //DateTime MUST BE A PROPER DATETIME! + //Double overflows are supported + //Overflows added from small time through to large time + //(ie. secs then mins then hours then days etc.) + + uint8_t a; + + DateTime->Second += AddTime->Second; + while (DateTime->Second > 59) { + DateTime->Second -= 60; + DateTime->Minute++; + } + DateTime->Minute += AddTime->Minute; + + while (DateTime->Minute > 59) { + DateTime->Minute -= 60; + DateTime->Hour++; + } + DateTime->Hour += AddTime->Hour; + while (DateTime->Hour > 23) { + DateTime->Hour -= 24; + DateTime->Day++; + } + DateTime->Day += AddTime->Day; + + while (DateTime->Day > (a = DaysInMonth(DateTime->Month, DateTime->Year))) { + DateTime->Day -= a; + DateTime->Month++; + } + DateTime->Month += AddTime->Month; + while (DateTime->Month > 12) { + DateTime->Month -= 12; + DateTime->Year++; + } + DateTime->Year += AddTime->Year; + //while (DateTime->Year > 99) { + // DateTime->Year -= 100; + //} +} + +uint8_t DaysInMonth(uint8_t Month, uint8_t Year) { + switch (Month) { + //31 day months + case 1://Jan + case 3://Mar + case 5://May + case 7://July + case 8://Aug + case 10://Oct + case 12://Dec + return 31; + break; + //30 day months + case 4://April + case 6://June + case 9://Sep + case 11://Nov + return 30; + break; + //The dreaded February!!! + case 2://Feb + //Is it a leap year?? + if(((Year + 2000) % 4 == 0 && (Year + 2000) % 100 != 0) || (Year + 2000) % 400 == 0) + return 29;//Yes + else + return 28;//No + break; + default: + return 0; + } +} + +void sPrintTime (char* __s, struct RTCTime* pTime, char* lbl) { + if (lbl[0] == '\0') + sprintf_P(__s,PSTR("%02d-%02d-%02d %02d:%02d:%02d") + , pTime->Year + , pTime->Month + , pTime->Day + , pTime->Hour + , pTime->Minute + , pTime->Second); + else + sprintf_P(__s,PSTR("%s: %02d-%02d-%02d %02d:%02d:%02d\r\n") + , lbl + , pTime->Year + , pTime->Month + , pTime->Day + , pTime->Hour + , pTime->Minute + , pTime->Second); + //USART_tx_String(s); +} + +int str2Time(char* __s, struct RTCTime* destTime) { + //Format of string: DDMMYYHHMMSS - that's 12 characters. + int i; + + //check that it's 'valid' + for(i = 0; i < 12; i++) { + if (__s[i] < '0' || __s[i] > '9') + return -1; + } + + destTime->Day = BCDToInt((uint8_t)(((__s[0]-'0')<<4)+(__s[1]-'0'))); + destTime->Month = BCDToInt((uint8_t)(((__s[2]-'0')<<4)+(__s[3]-'0'))); + destTime->Year = BCDToInt((uint8_t)(((__s[4]-'0')<<4)+(__s[5]-'0'))); + destTime->Hour = BCDToInt((uint8_t)(((__s[6]-'0')<<4)+(__s[7]-'0'))); + destTime->Minute = BCDToInt((uint8_t)(((__s[8]-'0')<<4)+(__s[9]-'0'))); + destTime->Second = BCDToInt((uint8_t)(((__s[10]-'0')<<4)+(__s[11]-'0'))); + + if (ValidDateTime(destTime)) + return 0; + else + return -1; +} + +void ZipTime(struct RTCTime* rawTime, uint8_t* zipTime) { + //using compression method B: + // Byte 1 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr1 Yr0 Sec5 Sec4 Sec3 Sec2 Sec1 Sec0 + // Byte 2 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr3 Yr2 Min5 Min4 Min3 Min2 Min1 Min0 + // Byte 3 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr6 Yr5 Yr4 Hr4 Hr3 Hr2 Hr1 Hr0 + // Byte 4 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr9 Yr8 Yr7 Day4 Day3 Day2 Day1 Day0 + // Byte 5 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr13 Yr12 Yr11 Yr10 Mon3 Mon2 Mon1 Mon0 + + zipTime[0] = (rawTime->Second&0x3F)|(rawTime->Year&0x0003); + zipTime[1] = (rawTime->Minute&0x3F)|(rawTime->Year&0x000C); + zipTime[2] = (rawTime->Hour&0x1F)|(rawTime->Year&0x0070); + zipTime[3] = (rawTime->Day&0x1F)|(rawTime->Year&0x0380); + zipTime[4] = (rawTime->Month&0x0F)|(rawTime->Year&0x3C00); + +} + +void UnzipTime(struct RTCTime* rawTime, uint8_t* zipTime) { + //using compression method B: + // Byte 1 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr1 Yr0 Sec5 Sec4 Sec3 Sec2 Sec1 Sec0 + // Byte 2 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr3 Yr2 Min5 Min4 Min3 Min2 Min1 Min0 + // Byte 3 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr6 Yr5 Yr4 Hr4 Hr3 Hr2 Hr1 Hr0 + // Byte 4 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr9 Yr8 Yr7 Day4 Day3 Day2 Day1 Day0 + // Byte 5 + //Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 + //Yr13 Yr12 Yr11 Yr10 Mon3 Mon2 Mon1 Mon0 + + + rawTime->Second = zipTime[0]&0x3F; + rawTime->Hour = zipTime[1]&0x3F; + rawTime->Minute = zipTime[2]&0x1F; + rawTime->Day = zipTime[3]&0x1F; + rawTime->Month = zipTime[4]&0x0F; + rawTime->Year = (uint16_t)(zipTime[0]&0xC0>>6)|(zipTime[1]&0xC0>>4)| + (zipTime[2]&0xE0>>1)|(zipTime[3]&0xE0<<3)|(zipTime[4]&0xF0<<7); + + + zipTime[0] = (rawTime->Second&0x3F)|(rawTime->Year&0x0003); + zipTime[1] = (rawTime->Minute&0x3F)|(rawTime->Year&0x000C); + zipTime[2] = (rawTime->Hour&0x1F)|(rawTime->Year&0x0070); + zipTime[3] = (rawTime->Day&0x1F)|(rawTime->Year&0x0380); + zipTime[4] = (rawTime->Month&0x0F)|(rawTime->Year&0x3C00); + +} diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Libs/M_USART.c b/Tag/Device_Firmware/V1.1/WIDTag/Libs/M_USART.c new file mode 100644 index 0000000..04c6850 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Libs/M_USART.c @@ -0,0 +1,178 @@ +/* + * M_USART.c + * + * Created on: 22/01/2010 + * Author: Matty + */ + +#include "M_USART.h" + +volatile unsigned int Timer1; + +/* Function Name: SetupUSART +** Created On: 22/01/2010 +** Created By: Matthew Cochrane +** Description: Sets up the USART in asynchronous mode to a Baud rate specified by +** UBRR and UU2X with 8 data bits no parity and one stop bit. +** Inputs: +** UBRR - Value to set the UBRR register to +** UU2X - Boolean variable which if true will enable double data rate for the USART. +*/ +void USART_Setup (unsigned int UBRR, unsigned char UU2X) { + //Setup Baud Rate + UDRRRegH = (unsigned char)(UBRR >> 8); + UDRRRegL = (unsigned char)(UBRR & 0x00FF); + + //Setup Double Speed Setting + if (UU2X) { + UCSRAReg = (1< 0) Timer1--; +} + + + + + diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Libs/NRF24L01PController.c b/Tag/Device_Firmware/V1.1/WIDTag/Libs/NRF24L01PController.c new file mode 100644 index 0000000..8c6826e --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Libs/NRF24L01PController.c @@ -0,0 +1,288 @@ +/* + * NRF24L01PController.c + * + * Created on: 12/10/2011 + * Author: MC + */ + +#include "NRF24L01PController.h" +#include "HW_IO.h" +#include "common.h" +#include + +static const int NRF24L01P_TXTIMEOUTMS = 4; //from datasheet section 6.1.5 pg 23 + +//Defines: +enum { + REGBIT_CONFIG_PRIM_RX_BM = 0b00000001, + REGBIT_CONFIG_PWR_UP_BM = 0b00000010, + REGBIT_STATUS_TX_DS_BM = 0b00100000, + REGBIT_FIFOSTATUS_RX_EMPTY_BM = 0b00000001, +}; + +//Macros: +#define SETBITS(data, mask) data |= (mask) +#define CLRBITS(data, mask) data &= ~(mask) +#define GETBYTE(data, byteNo) *(((uint8_t*)data)+byteNo) + +//Variables: +static uint8_t NRF24L01PMode = 0xFF; +static void (*NRF24L01PStartmsTimer)(void) = NULL; +static uint16_t (*NRF24L01PgetmsCounterTicks)(void) = NULL; +static void (*NRF24L01PStopmsTimer)(void) = NULL; + +//Helper functions: +static inline BOOL InvalidRegisterAddress(NRF24L01P_RegAdd_t address) { + return (address&0b11100000); +} + +static inline uint8_t SPIGenerateReadRegCmdByte(NRF24L01P_RegAdd_t address) { + return address;// & 0b00011111; //first 3 bits of address should already be zero! +} + +static inline uint8_t SPIGenerateWriteRegCmdByte(NRF24L01P_RegAdd_t address) { + return address | 0b00100000; +} + +static inline BOOL InvalidMode(NRF24L01P_Mode_t mode) { + return ((mode < MODE_POWERDOWN) || (mode > MODE_RX)); +} + +void NRF24L01P_Create(void(*StartTimerFuncPtr)(), void(*StopTimerFuncPtr)(), uint16_t(*getCounterTickFuncPtr)()) { + + NRF24L01PStartmsTimer = StartTimerFuncPtr; + NRF24L01PgetmsCounterTicks = getCounterTickFuncPtr; + NRF24L01PStopmsTimer = StopTimerFuncPtr; + IO_NRF_Setup_Pins(); + IO_NRF_Setup_SPI(); + //Doesn't necessarily agree with hardware + NRF24L01PMode = MODE_POWERDOWN; + //NRF24L01P_SetMode(MODE_POWERDOWN); +} + +void NRF24L01P_Destroy() { + NRF24L01PMode = 0xFF; +} + +void NRF24L01P_SetupInterface(uint8_t chan, uint8_t* id) { + // PTX, CRC enabled, mask a couple of ints + NRF24L01P_WriteRegister(NREG_CONFIG, 0b00111001); + //Disable auto retransmit + NRF24L01P_WriteRegister(NREG_SETUP_RETR, 0b00000000); + //Address Width = 5 + NRF24L01P_WriteRegister(NREG_SETUP_AW, 0b00000111); + //Set RF Channel + chan &= ~0x80; + NRF24L01P_WriteRegister(NREG_RF_CH, chan); + /*RF output power: NREG_RF_SETUP 0b000000XX -> + 00 = -18dBm (7.0mA in TX mode) + 01 = -12dBm (7.5mA in TX mode) + 10 = -6dBm (9.0mA in TX mode) + 00 = 0dBm (11.3mA in TX mode) + */ + //Setup RF -> 2Mbps data rate, 0dBm output power + //NRF24L01P_WriteRegister(NREG_RF_SETUP, 0b00000111); + //Setup RF -> 1Mbps data rate, 0dBm output power + //NRF24L01P_WriteRegister(NREG_RF_SETUP, 0b00000011); + //Setup RF -> 250kbps data rate, 0dBm output power + NRF24L01P_WriteRegister(NREG_RF_SETUP, 0b00100111); + //Set the address of RX Pipe 0 to id + NRF24L01P_WriteRegisterLong(NREG_RX_ADDR_P0, id, 5); + //Set TX Address to id + NRF24L01P_WriteRegisterLong(NREG_TX_ADDR, id, 5); + //Disable auto-ACK + NRF24L01P_WriteRegister(NREG_EN_AA, 0b00000000); + //Enable only pipe 0 + NRF24L01P_WriteRegister(NREG_EN_RXADDR, 0b00000001); + //Enable Pipe 0 and use payload width of 4 + NRF24L01P_WriteRegister(NREG_RX_PW_P0, 4); + //Clear flags in status: + NRF24L01P_WriteRegister(NREG_STATUS, 0b01110000); +} + +NRF24L01P_Mode_t NRF24L01P_GetMode_Impl(void) { + return NRF24L01PMode; +} + +NRF24L01P_Mode_t (*NRF24L01P_GetMode)(void) = NRF24L01P_GetMode_Impl; + +NRF24L01P_RW_Reg_RetVal_t NRF24L01P_ReadRegister_Impl(NRF24L01P_RegAdd_t address, uint8_t* data) { + //R_REGISTER + //Command = 000AAAAA; + + if (InvalidRegisterAddress(address)) { + #ifdef NRF24L01P_USE_RUNTIME_ERRORS + RUNTIME_ERROR("NRF24L01P_ReadRegister: Invalid Register Address", address); + #endif + return NRF24L01P_INVALID_INPUT; + } + uint8_t command = SPIGenerateReadRegCmdByte(address); + + //None of these functions can timeout because the SPI is in master mode... + IO_NRF_CSN(PIN_LOW); + IO_SPI_TX(command); + *data = IO_SPI_RX(); + IO_NRF_CSN(PIN_HIGH); + return NRF24L01P_SUCCESS; +} + +NRF24L01P_RW_Reg_RetVal_t (*NRF24L01P_ReadRegister)(NRF24L01P_RegAdd_t address, uint8_t* data) = NRF24L01P_ReadRegister_Impl; + +NRF24L01P_RW_Reg_RetVal_t NRF24L01P_WriteRegister_Impl(NRF24L01P_RegAdd_t address, uint8_t data) { + //W_REGISTER - Executable in power down and standby modes only. + //Command = 001AAAAA; + + return NRF24L01P_WriteRegisterLong(address, &data, 1); +} + +NRF24L01P_RW_Reg_RetVal_t (*NRF24L01P_WriteRegister)(NRF24L01P_RegAdd_t address, uint8_t data) = NRF24L01P_WriteRegister_Impl; + +int8_t NRF24L01P_SetMode_Impl(NRF24L01P_Mode_t mode) { + uint8_t configReg; + uint8_t pinCEVal; + int8_t tmpErr = 0; + + if (InvalidMode(mode)) + return NRF24L01P_INVALID_INPUT; + + if ((tmpErr = NRF24L01P_ReadRegister(NREG_CONFIG, &configReg)) < 0) { + NRF24L01PMode = MODE_UNKNOWN; + return tmpErr; + } + + switch (mode) { + case MODE_RX: + SETBITS(configReg, REGBIT_CONFIG_PWR_UP_BM|REGBIT_CONFIG_PRIM_RX_BM); + pinCEVal = PIN_HIGH; + break; + case MODE_TX: + SETBITS(configReg, REGBIT_CONFIG_PWR_UP_BM); + CLRBITS(configReg, REGBIT_CONFIG_PRIM_RX_BM); + pinCEVal = PIN_LOW; + break; + case MODE_POWERDOWN: + CLRBITS(configReg, REGBIT_CONFIG_PWR_UP_BM); + pinCEVal = PIN_LOW; + break; + default: + break; + } + + if ((tmpErr = NRF24L01P_WriteRegister(NREG_CONFIG, configReg)) < 0) { + NRF24L01PMode = MODE_UNKNOWN; + return tmpErr; + } + + if (pinCEVal < PIN_UNCHANGED) + IO_NRF_CE(pinCEVal); + + NRF24L01PMode = mode; + + return NRF24L01P_SUCCESS; +} + +int8_t (*NRF24L01P_SetMode)(NRF24L01P_Mode_t mode) = NRF24L01P_SetMode_Impl; + +void NRF24L01P_FlushTxFIFO() { + //FLUSH_TX + //Command = 11100001; + IO_NRF_CSN(PIN_LOW); + IO_SPI_TX(0b11100001); + IO_NRF_CSN(PIN_HIGH); +} + +void NRF24L01P_FlushRxFIFO() { + //FLUSH_RX + //Command = 11100010; + //Should not be executed during transmission of ACK packet, that is, ACK + //packet will not be completed. + IO_NRF_CSN(PIN_LOW); + IO_SPI_TX(0b11100010); + IO_NRF_CSN(PIN_HIGH); +} + +NRF24L01P_TxRx_RetVal_t NRF24L01P_TxPayload(uint32_t data) { + //W_TX_PAYLOAD + //Command = 10100000; + uint8_t statReg = 0x00; + uint16_t startTime; + BOOL TimedOut = FALSE; + uint8_t i; + + if (NRF24L01P_GetMode() != MODE_TX) + return NRF_TxRx_ret_wrong_mode; + + IO_NRF_CSN(PIN_LOW); + IO_SPI_TX(0b10100000); + for (i = 0; i < 4; i++) + IO_SPI_TX(GETBYTE(&data, i)); + IO_NRF_CSN(PIN_HIGH); + + IO_NRF_CE(PIN_HIGH); + _delay_us(15); + IO_NRF_CE(PIN_LOW); + _delay_us(12); + + CPUSleep_Time(CPUSLEEP_0m5s); + + NRF24L01PStartmsTimer(); + startTime = NRF24L01PgetmsCounterTicks(); + + do { + NRF24L01P_ReadRegister(NREG_STATUS, &statReg); + TimedOut = (NRF24L01PgetmsCounterTicks() - startTime) >= NRF24L01P_TXTIMEOUTMS; + } while (!(statReg & REGBIT_STATUS_TX_DS_BM) && (!TimedOut)); + + NRF24L01PStopmsTimer(); + + if (TimedOut) return NRF_TxRx_ret_timeout; + + NRF24L01P_WriteRegister(NREG_STATUS, 0b01110000); + + return NRF_TxRx_ret_success; +} + +NRF24L01P_TxRx_RetVal_t NRF24L01P_RxPayload(uint32_t* data) { + uint8_t FIFOStat = 0xFF; + uint8_t i; + + if (NRF24L01P_GetMode() != MODE_RX) + return NRF_TxRx_ret_wrong_mode; + + NRF24L01P_ReadRegister(NREG_FIFOSTATUS, &FIFOStat); + if (FIFOStat & REGBIT_FIFOSTATUS_RX_EMPTY_BM) + return NRF_TxRx_ret_rx_fifo_empty; + IO_NRF_CSN(PIN_LOW); + IO_SPI_TX(0b01100001); + for (i = 0; i < 4; i++) { + GETBYTE(data, i) = IO_SPI_RX(); + } + IO_NRF_CSN(PIN_HIGH); + + return NRF_TxRx_ret_success; +} + +NRF24L01P_RW_Reg_RetVal_t NRF24L01P_WriteRegisterLong_Impl(NRF24L01P_RegAdd_t address, uint8_t* data, uint8_t length) { + //W_REGISTER - Executable in power down and standby modes only. + //Command = 001AAAAA; + + if (InvalidRegisterAddress(address)) { + #ifdef NRF24L01P_USE_RUNTIME_ERRORS + RUNTIME_ERROR("NRF24L01P_WriteRegister: Invalid Register Address", address); + #endif + return NRF24L01P_INVALID_INPUT; + } + + uint8_t command = SPIGenerateWriteRegCmdByte(address); + + IO_NRF_CSN(PIN_LOW); + IO_SPI_TX(command); + while (length--) { + IO_SPI_TX(*data++); + } + IO_NRF_CSN(PIN_HIGH); + return NRF24L01P_SUCCESS; + +} + +NRF24L01P_RW_Reg_RetVal_t (*NRF24L01P_WriteRegisterLong)(NRF24L01P_RegAdd_t address, uint8_t* data, uint8_t length) = NRF24L01P_WriteRegisterLong_Impl; diff --git a/Tag/Device_Firmware/V1.1/WIDTag/Libs/msTimer_ATMEGA88.c b/Tag/Device_Firmware/V1.1/WIDTag/Libs/msTimer_ATMEGA88.c new file mode 100644 index 0000000..b8b28f8 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/Libs/msTimer_ATMEGA88.c @@ -0,0 +1,41 @@ +/* + * msTimer_ATMEGA88.c + * + * Created: 15/10/2011 10:48:28 PM + * Author: MC + */ + +#include "msTimer.h" +#include + +static volatile uint16_t msTimerCount; + +ISR(TIMER0_COMPA_vect) { + msTimerCount++; +} + +void msTimer_StartTimer(void) { + PRR &= ~(1< 30) { + CPUSleep_Time(CPUSLEEP_1ms); + j = j % 10; + } + //} + + reInitCounter += TX_Period; + if (reInitCounter >= (NORDIC_REINIT_PERIOD_SECS)) { +// PORTC |= (1); //1 +// delay_ms(500); +// PORTC &= ~(1); +// delay_ms(500); +// PORTC |= (1); //2 +// delay_ms(500); +// PORTC &= ~(1); +// delay_ms(500); +// PORTC |= (1); //3 + Nordic_Setup_All(); +// PORTC &= ~(1); + reInitCounter = 0; + } + + //Now TX the payload + TXPayload(); + TX_Delay = TX_Period; + } + +// if (PrintTime) { +// //PORTC |= (1); +// _delay_ms(20); +// sPrintTime(s, &RTC_c_Time, "Time"); +// USART_tx_String(s); +// _delay_ms(10); +// //PORTC &= ~(1<<0); +// } + } + + if (Wakeup_Source == WAKEUP_SOURCE_UART) { + //PORTC |= (1<<0); + _delay_ms(20); + ShowMenu(); + _delay_ms(10); + //PORTC &= ~(1<<0); + } + + } + + return 0; +} + +void ShowMenu() { + struct RTCTime tmpTime; + int i; + char retChar; + uint8_t RFedit = 0; + + //USART_tx_String_P(PSTR("USART Woke me.\r\n")); + //USART_tx_String_P(PSTR("Enter appropriate command.\r\n>")); + USART_tx_String_P(PSTR(">")); + //flush USART RX buffer + while (USART_rx_Byte_nb() != -1); + //Receive byte + retChar = USART_rx_Byte(TIMEOUT); + switch (retChar) { + case 'T': + USART_tx_String_P(PSTR("ET (DDMMYYHHMMSS):\r\n"));//Enter Date/Time (DDMMYYHHMMSS).\r\n>")); + + for (i = 0; i < 12; i++) + s[i] = USART_rx_Byte(TIMEOUT<<2); + s[12] = '\0'; + + if (str2Time(s, &tmpTime) == 0) + CopyTime(&tmpTime, &RTC_c_Time); + + sPrintTime(s, &RTC_c_Time, "Time"); + USART_tx_String(s); + break; + case 'P': + USART_tx_String_P(PSTR("ETX (MSS):\r\n"));//Enter TX Period (MSS).\r\n>")); + + s[3] = 0; + for (i = 0; i < 3; i++) { + s[i] = USART_rx_Byte(TIMEOUT<<1)-'0'; + if (s[i] > 9 || s[i] < 0) + s[3] = 1; + } + + if (!s[3]) { + i = s[0]*60+s[1]*10+s[2]; + if (i > 255) { + USART_tx_String_P(PSTR("Bad\r\n"));//Invalid TX period entered.\r\n")); + } else { + TX_Period = i; + TX_Delay = i; + eeprom_write_byte((uint8_t*)TXPERADD,TX_Period); + //USART_printf_P("TX Period set to %d seconds\r\n", TX_Period); + USART_printf_P("TX %ds\r\n", TX_Period); + } + } else { + USART_tx_String_P(PSTR("Bad\r\n"));//Invalid TX period entered.\r\n")); + } + break; + case 's': + TXPayload(); + break; + case 'N': + ;uint8_t tmpDat; + uint8_t i; + for (i = 0; i <= 0x17; i++) { + NRF24L01P_ReadRegister(i, &tmpDat); + USART_printf_P("Reg: 0x%02X, Val:0x%02X\r\n", i, tmpDat); + } + break; + case 't': + PrintTime ^= 1; + //USART_printf_P("PrintTime :0x%02X\r\n", PrintTime); + break; + case '?': + ReadAllVarsFromEEPROM(); + //DEV_ID + USART_printf_P("DEV_ID:%08lX\r\n", Device_ID); + //RFID + USART_tx_String_P(PSTR("RFID:")); + for (i = 0; i < 4; i++) { + USART_printf_P("%02X-", RF_ID[i]); + } + USART_printf_P("%02X\r\n", RF_ID[4]); + //RFCHAN + USART_printf_P("RFCHAN:%d\r\n", RF_Chan); + //ARMED + USART_printf_P("DEVARMED:%u\r\n", DevArmed); + //TXPERIOD + USART_printf_P("TXPERIOD:%d\r\n", TX_Period); + break; + case '*': + //DEV_ID + s[0] = 's'; + USART_tx_String_P(PSTR("DEV_ID (XXXXXXXX):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + Device_ID = (uint32_t)strtoul(s, (char **)NULL,16); + WriteEEPROM((uint8_t*)&Device_ID, 4,DEVIDADD); + } + s[0] = 's'; + //RFID + USART_tx_String_P(PSTR("RFID (XX-XX-XX-XX-XX):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + for (i = 0; i < 5; i++) + RF_ID[i] = (uint8_t)strtoul(s+i*3, (char **)NULL,16); + WriteEEPROM(RF_ID,5,RFIDADD); + RFedit = 1; + } + s[0] = 's'; + //RFCHAN + USART_tx_String_P(PSTR("RFCHAN (###):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + RF_Chan = 100*(s[0]-'0') + 10*(s[1]-'0') + (s[2]-'0'); + eeprom_write_byte((uint8_t*)RFCHANADD, RF_Chan); + RFedit = 1; + } + s[0] = 's'; + //DEVARMED + USART_tx_String_P(PSTR("DEVARMED (X):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + DevArmed = s[0]-'0'; + eeprom_write_byte((uint8_t*)DEVARMEDADD,DevArmed); + DevArmSetup(); + } + s[0] = 's'; + //TXPERIOD + USART_tx_String_P(PSTR("TXPERIOD (MSS):\r\n")); + USART_rx_String(s,TIMEOUT<<3); + if (s[0] != 's' && s[0] != 0xFF) { + i = (s[0]-'0')*60+(s[1]-'0')*10+(s[2]-'0'); + //if (i < 255) { + TX_Period = i; + TX_Delay = i; + eeprom_write_byte((uint8_t*)TXPERADD,TX_Period); + //} + } + + if (RFedit && DevArmed != ARM_SHELF) { + //Setup the Nordic Chip with new values + Nordic_Setup_All(); + } + break; + } + //USART_tx_String_P(PSTR("Going to sleep. Press any key to wake.\r\n")); + USART_tx_String_P(PSTR("Sleep.\r\n")); + +} + +/*inline void WriteTimeEEPROM(struct RTCTime* mTime, uint16_t Address) { + WriteEEPROM((uint8_t*)mTime, 5, Address); +} + +inline void ReadTimeEEPROM(struct RTCTime* mTime, uint16_t Address) { + ReadEEPROM((uint8_t*)mTime, 5, Address); +}*/ + +void ReadEEPROM(uint8_t* Data, uint8_t Length, uint16_t Address) { + for (int i = 0; i < Length; i++) + *Data++ = eeprom_read_byte((uint8_t*)Address++); +} + +void WriteEEPROM(uint8_t* Data, uint8_t Length, uint16_t Address) { + for (int i = 0; i < Length; i++) + eeprom_write_byte((uint8_t*)Address++, *Data++); +} + +static inline void delay_ms(uint16_t ms) { + do { + _delay_ms(1); + } while (--ms != 0); +} + +// void StartTim10ms(uint16_t Time) { +// PRR &= ~(1< + + + 2.0 + 5.0 + {77bcdbd5-eb6f-4198-9537-80123c2374b8} + ATmega88PA + none + Executable + C + $(MSBuildProjectName).elf + $(MSBuildProjectDirectory)\$(Configuration) + True + + + + + D:\Atmel\AVR Studio 5.0\AVR ToolChain\bin + + + WIDTag + WIDTag + WIDTag + debugWIRE + com.atmel.avrdbg.tool.avrdragon + + com.atmel.avrdbg.tool.avrdragon + AVR Dragon + 00A20000865C + + 127.0.0.1 + 50870 + False + + + debugWIRE + + 1000000 + 1000000 + 150000 + false + false + 0 + 0 + 0 + 0 + + + + + com.atmel.avrdbg.tool.simulator + AVR Simulator + + + + 127.0.0.1 + 50870 + False + + + True + + + + + True + True + Optimize for size (-Os) + True + True + None + True + + + + + True + True + True + True + + + + + True + True + + + F_CPU=8000000UL + + + + + ../Includes + ../Includes/util + + + Optimize for size (-Os) + True + True + Default (-g2) + True + Default (-g2) + + + + + +
0x400
+
+
+
+ True + True + True + True + WIDTag.elf + Executable +
+ + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + + + + + + + +
\ No newline at end of file diff --git a/Tag/Device_Firmware/V1.1/WIDTag/WIDTag_Code_Changelog.txt b/Tag/Device_Firmware/V1.1/WIDTag/WIDTag_Code_Changelog.txt new file mode 100644 index 0000000..a528877 --- /dev/null +++ b/Tag/Device_Firmware/V1.1/WIDTag/WIDTag_Code_Changelog.txt @@ -0,0 +1,174 @@ +WID Tag Changelog +Created: 10/08/2011 +Updated: 18/10/2011 +Author: Matthew Cochrane +Company: Wild Spy + +Version: V0.2.2 + - Code Finished: 18/10/2011 + - Workshop Implementation Date: ??/10/2011 + - Firmware: WIDTagV0.2.2.hex + - EEPROM: WIDTag_EEPROM_V0.2.hex + - Fuses: H-0xD6, L-0xE2, E-0xF9(0x01) + + NOTES: + - MCU MUST still be a pico-power device (for BOD Disable feature). ATmega48PA/88PA/168PA/328P + + TODO: + - Test this version in the workshop and see if we still get ESD problems when potting the WIDs. + + Description: + - Fifth code revision at workshop. This code revision was written for two main purposes: + 1. To counter still pervailant issues with the LED ON problem which are causing the device to + stop transmitting once potted. + 2. To try out some Test Driven Development code writing techniques. + - A new NRF24L01+ controller library was written to accomplish both of these requirements. The new + NRF24L01P Library was written in eclipse using Test Driven Development techniques. + - The LED ON issue that was fixed in V0.2.1 was still buggy. It sometimes caused the unit to get stuck + in a loop where if it got hit my too much static, every transmit thereafter would time out. Instead of + showing a solid LED ON, the unit would simply not transmit. + - The above problem is improved upon in this version of the code. In V0.2.1, the Tx timeout was based + on the RTC timer and would only timeout after at leas one second had elapsed. Now the Tx subroutime + uses its own dedicated timer (TC0) which will timeout after 4ms (and yes this IS long enough, search + the datasheet for '4ms'). + - The new library boasts other improvements as well, the main one is that it has been very well tested + using TDD techniques. + - The library is much better written then the previous version. The code file should never need to be + modified (unless there is a bug). It makes use of function pointers and link-time dependancies on + low level IO functions so that they are not stuck in the main code file. This results in low code + coupling, easier to read code and more reliable code. + + Changes: + - New NRF24L01P Library written in eclipse using Test Driven Development techniques. + - The BOD activation voltage was changed from 2.7V to 1.8V. + - The 'N' command from the menu now reads all of the registers from the nordic chip and prints them out. + - The random feature was modified it no longer uses rand() but is based on the tag's ID. Has not been + empirically tested but some basic TDD tests show that it should work fine. + +-------------------------------------------------------------------------------------------------------------------- + +Version: V0.2.1 + - Code Finished: 13/08/2011 + - Workshop Implementation Date: ??/08/2011 + - Firmware: WIDTagV0.2.1.hex + - EEPROM: WIDTag_EEPROM_V0.2.hex + - Fuses: H-0xDD, L-0xE2, E-0xF9(0x01) + + NOTES: + - MCU MUST now be a pico-power device (for BOD Disable feature). ATmega48PA/88PA/168PA/328P + + TODO: + - Test that the batteries still get decent life with 2.7V BOD reset. Consider changing to 1.8V BOD reset? + + Description: + - Fourth code revision at workshop. This code revision was written to fix the LED ON issue with the WIDs. + The previous code version (V0.2.1) was very short lived. The first day it was brought into the workshop + it was discovered that it had not resolved the LED ON issue which it was supposed to. The software BOD + that was implemented in the previous version was left incorporated. The LED ON problem was ultimately + overcome by first finally understanding its cause which could be traced back to its origin after creating. + a repeatible test the caused the fault. This test was performed by unleashing a large static discharge was + the WID's antenna while the MCU was asleep and this consistantly yeilded the same result (~90% of the time). + Nothing would happen until the WID woke up (which was at the correct time) and then the LED would turn on + solid and remain on indefinitely. The root cause of this problem was that the nordic chip (nRF24L01+) was + being reset (?) by a static discharge while the MCU was asleep and its SRAM contents was lost. This meant + that the chip wasn't properly configured next time the MCU woke up. When it did, the MCU sent tx data to the + nordic chip, told it to transmit the data and then waited for the nordic chip to flag that it had transmitted + that data however because it wasn't set up properly, the nordic chip never set this flag and therefore the + MCU would be stuck in an infinite loop. + - The situation was remedied by adding a timeout while the MCU waits for the TX complete flag to be set. If + this timout occurs then we know that the nordic chip was probably reset, so the MCU then re-initialises it. + + + Changes: + - Fixed LED ON problem caused by static discharge. Timeout implemented in function NRF24L01_TX_PAYLOAD. + - Changes from V0.2.0 listed below as they are very recent and because V0.2.0 should never be used! + - Fuses changed so that BOD is activated (2.7V reset cutoff). + - Implemented software BOD feature (BOD on in active mode, off in sleep mode). + - EEPROM locations shifted. WID_ID moved from address 0x00, all addresses shifted by 0x10 and addresses + spread out more so no two variables are directly adjacent. + - New EEPROM file (WIDTag_EEPROM_V0.2.hex), also changed file format from raw to intel hex. + +-------------------------------------------------------------------------------------------------------------------- + +Version: V0.2.0 + - Code Finished: 10/08/2011 + - Workshop Implementation Date: 12/08/2011 + - Firmware: WIDTagV0.2.hex + - EEPROM: WIDTag_EEPROM_V0.2.hex + - Fuses: H-0xDD, L-0xE2, E-0xF9 + + NOTES: + - LED ON PROBLEM STILL NOT FIXED!!! USE V0.2.1!! DO NOT USE THIS VERSION OF CODE!!! + - MCU MUST now be a pico-power device (for BOD Disable feature). ATmega48PA/88PA/168PA/328P + - Found bugs in this version almost immediately once implemented in the workshop! + + TODO: + - Test that the batteries still get decent life with 2.7V BOD reset. Consider changing to 1.8V BOD reset? + + Description: + - Third code revision at workshop. This code revision was written to combat the problems we are experiencing + with WIDs locking up (LED stuck on) and EEPROM values being erronously overwritten. The theory is that these + phenomenon are being caused by the microprocessor going rogue as a result of its power lines droping below its + minimum operating voltage. The Brown Out Detector on the ATMEGA88PA uses far too much power (20-30uA) to be a + viable solution to this problem alone however on Pico-power devices (ATMEGA**P/ATMEGA**PA) there is a software + BOD feature which allows the BOD to be enabled when the MCU is in active mode and disabled when it is in any + sleep mode. This greatly reduces the energy cost of having the BOD active to the point where it makes + essentially no difference to the devices average current consumption (<0.1% difference). The BOD still does + it's job as it's active in the MCUs active mode (is activated and stabilised BEFORE the MCU executes any + instructions) and does not need to be active in sleep mode as the CPU is not executing instructions and thus + the chances of data corruption are greatly reduced. It is still possible that some memory (RAM) locations + are corrupted while in sleep mode if the voltage drops too low. Not sure HOW possible this is but it may + be worth resetting the MCU once or twice a day in case of any corruption. + - The first byte in EEPROM is more prone to being overwritten if a power supply failure occurs. Even though + the chances of this happening are GREATLY reduced with the BOD enabled the EEPROM locations were shifted to + further reduce the risk of this impornt data being corrupted. + + Changes: + - Fuses changed so that BOD is activated (2.7V reset cutoff). + - Implemented software BOD feature (BOD on in active mode, off in sleep mode). + - EEPROM locations shifted. WID_ID moved from address 0x00, all addresses shifted by 0x10 and addresses + spread out more so no two variables are directly adjacent. + - New EEPROM file (WIDTag_EEPROM_V0.2.hex), also changed file format from raw to intel hex. + +-------------------------------------------------------------------------------------------------------------------- + +Version: V0.1.2 + - Code Finished: ??/??/2011 + - Workshop Implementation Date: ??/??/2011 + - Firmware: WIDTagV0.1.2.hex + - EEPROM: WIDTag_EEPROM_V0.1.eeprom + - Fuses: H-0xDF, L-0xE2, E-0xF9 + + Description: + - Second code revision at workshop. + + Changes: + - Fixed LED-on problem (can't remember how.. update this when you remember!) + +-------------------------------------------------------------------------------------------------------------------- + +Version: V0.1.1 + - Code Finished: ??/??/2011 + - Workshop Implementation Date: ??/??/2011 + - Firmware: WIDTagV0.1.1.hex + - EEPROM: WIDTag_EEPROM_V0.1.eeprom + - Fuses: H-0xDF, L-0xE2, E-0xF9 + + Description: + - First code revision. + + Changes: + - Not sure... :s + +-------------------------------------------------------------------------------------------------------------------- + +Version: V0.1.0 + - Firmware: WIDTagV0.1.0.hex + - EEPROM: WIDTag_EEPROM_V0.1.eeprom + - Fuses: H-0xDF, L-0xE2, E-0xF9 + + Description: + - Original code version (documented after the fact) + +-------------------------------------------------------------------------------------------------------------------- + \ No newline at end of file