@@ -0,0 +1,37 @@ | |||||
#include "Config.h" | |||||
#include "Debug.h" | |||||
#include "Hardware.h" | |||||
#define LOGGER_NAME "Config" | |||||
namespace config { | |||||
Config value; | |||||
void write() { | |||||
VERBOSE("writeConfig"); | |||||
hardware::i2c::eeprom.writeBlock(CONFIG_ADDR, value); | |||||
VERBOSE_FORMAT("writeConfig", "%s, %s, %d, %d", value.seed, value.version, value.firstEntry, value.lastEntry); | |||||
} | |||||
void reset() { | |||||
VERBOSE("resetConfig"); | |||||
Config config = { | |||||
CONFIG_SEED, | |||||
VERSION, | |||||
0, | |||||
0 | |||||
}; | |||||
value = config; | |||||
write(); | |||||
} | |||||
void read() { | |||||
VERBOSE("readConfig"); | |||||
hardware::i2c::eeprom.readBlock(CONFIG_ADDR, value); | |||||
if (!String(CONFIG_SEED).equals(value.seed)) reset(); | |||||
VERBOSE_FORMAT("readConfig", "%s, %s, %d, %d", value.seed, value.version, value.firstEntry, value.lastEntry); | |||||
} | |||||
} |
@@ -1,10 +1,23 @@ | |||||
#pragma once | #pragma once | ||||
#include <Arduino.h> | |||||
struct sleepTimings_t { | struct sleepTimings_t { | ||||
uint8_t speed; | uint8_t speed; | ||||
uint16_t seconds; | uint16_t seconds; | ||||
}; | }; | ||||
struct Config { | |||||
char seed[5]; | |||||
char version[7]; | |||||
uint16_t firstEntry; | |||||
uint16_t lastEntry; | |||||
}; | |||||
#define CONFIG_ADDR 0 | |||||
#define CONFIG_SEED "UIYA" | |||||
#define VERSION "1.00" | |||||
#define SLEEP_DEFAULT_TIME_SECONDS 1800 | #define SLEEP_DEFAULT_TIME_SECONDS 1800 | ||||
#define GPS_DEFAULT_INTERMEDIATE_TIMEOUT_MS 10000 | #define GPS_DEFAULT_INTERMEDIATE_TIMEOUT_MS 10000 | ||||
@@ -12,6 +25,8 @@ struct sleepTimings_t { | |||||
namespace config { | namespace config { | ||||
extern Config value; | |||||
static const sleepTimings_t defaultSleepTimings[] PROGMEM = { | static const sleepTimings_t defaultSleepTimings[] PROGMEM = { | ||||
{ 5, SLEEP_DEFAULT_TIME_SECONDS }, | { 5, SLEEP_DEFAULT_TIME_SECONDS }, | ||||
{ 10, 1200 }, | { 10, 1200 }, | ||||
@@ -23,4 +38,7 @@ namespace config { | |||||
{ 180, 180 }, | { 180, 180 }, | ||||
}; | }; | ||||
void read(); | |||||
void write(); | |||||
} | } |
@@ -10,6 +10,7 @@ namespace core { | |||||
void main() { | void main() { | ||||
gps::powerOn(); | gps::powerOn(); | ||||
SIM808_GPS_STATUS gpsStatus = gps::acquireCurrentPosition(GPS_DEFAULT_TOTAL_TIMEOUT_MS); | SIM808_GPS_STATUS gpsStatus = gps::acquireCurrentPosition(GPS_DEFAULT_TOTAL_TIMEOUT_MS); | ||||
SIM808ChargingStatus battery = hardware::sim808::device.getChargingState(); | |||||
gps::powerOff(); | gps::powerOff(); | ||||
if (gpsStatus > SIM808_GPS_STATUS::NO_FIX) { | if (gpsStatus > SIM808_GPS_STATUS::NO_FIX) { | ||||
@@ -19,7 +20,7 @@ namespace core { | |||||
rtc::setTime(time); | rtc::setTime(time); | ||||
rtc::powerOff(); | rtc::powerOff(); | ||||
positions::appendLast(); | |||||
positions::appendLast(battery, gpsStatus); | |||||
uint8_t velocity; | uint8_t velocity; | ||||
gps::getVelocity(velocity); | gps::getVelocity(velocity); | ||||
@@ -1,23 +1,27 @@ | |||||
#include "Debug.h" | #include "Debug.h" | ||||
#include "Flash.h" | #include "Flash.h" | ||||
#include "Positions.h" | |||||
#define MENU_ENTRY(name, text) const char MENU_##name[] PROGMEM = text | #define MENU_ENTRY(name, text) const char MENU_##name[] PROGMEM = text | ||||
MENU_ENTRY(HEADER, "-- Debug Menu --"); | MENU_ENTRY(HEADER, "-- Debug Menu --"); | ||||
MENU_ENTRY(SEPARATOR, "----"); | MENU_ENTRY(SEPARATOR, "----"); | ||||
MENU_ENTRY(RUN, "[0] Run"); | |||||
MENU_ENTRY(RUN_ONCE, "[1] Run once"); | |||||
MENU_ENTRY(RAM, "[2] Read battery"); | |||||
MENU_ENTRY(READ_BATTERY, "[3] Read battery"); | |||||
MENU_ENTRY(GPS_ON, "[4] GPS On"); | |||||
MENU_ENTRY(GPS_OFF, "[5] GPS Off"); | |||||
MENU_ENTRY(GPS_GET, "[6] Get GPS position"); | |||||
MENU_ENTRY(RTC_ON, "[7] RTC On"); | |||||
MENU_ENTRY(RTC_OFF, "[8] RTC Off"); | |||||
MENU_ENTRY(RTC_SET, "[9] Get RTC time"); | |||||
MENU_ENTRY(RTC_GET, "[10] Set RTC time"); | |||||
MENU_ENTRY(QUESTION, "?"); | |||||
MENU_ENTRY(RUN, "[0] Run"); | |||||
MENU_ENTRY(RUN_ONCE, "[1] Run once"); | |||||
MENU_ENTRY(RAM, "[2] Read battery"); | |||||
MENU_ENTRY(READ_BATTERY, "[3] Read battery"); | |||||
MENU_ENTRY(GPS_ON, "[4] GPS On"); | |||||
MENU_ENTRY(GPS_OFF, "[5] GPS Off"); | |||||
MENU_ENTRY(GPS_GET, "[6] Get GPS position"); | |||||
MENU_ENTRY(RTC_ON, "[7] RTC On"); | |||||
MENU_ENTRY(RTC_OFF, "[8] RTC Off"); | |||||
MENU_ENTRY(RTC_SET, "[9] Get RTC time"); | |||||
MENU_ENTRY(RTC_GET, "[10] Set RTC time"); | |||||
MENU_ENTRY(SD_WRITE_TEST "[11] Write to test file"); | |||||
MENU_ENTRY(EEPROM_GET_CONFIG, "[16] Get EEPROM config"); | |||||
MENU_ENTRY(EEPROM_GET_ENTRIES, "[17] Get EEPROM entries"); | |||||
MENU_ENTRY(QUESTION, "?"); | |||||
const char * const MENU_ENTRIES[] PROGMEM = { | const char * const MENU_ENTRIES[] PROGMEM = { | ||||
MENU_HEADER, | MENU_HEADER, | ||||
@@ -47,7 +51,7 @@ const char * const MENU_ENTRIES[] PROGMEM = { | |||||
}; | }; | ||||
int freeRam2() { | |||||
int freeRam2() { // dirty hack because putting it in namespace doesn't compile | |||||
extern int __heap_start, *__brkval; | extern int __heap_start, *__brkval; | ||||
int v; | int v; | ||||
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval); | return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval); | ||||
@@ -90,7 +94,7 @@ namespace debug { | |||||
void getAndDisplayBattery() { | void getAndDisplayBattery() { | ||||
SIM808ChargingStatus status = hardware::sim808::device.getChargingState(); | SIM808ChargingStatus status = hardware::sim808::device.getChargingState(); | ||||
Log.notice("%d %d%% %dmV", status.state, status.level, status.voltage); | |||||
Log.notice(F("%d %d%% %dmV"), status.state, status.level, status.voltage); | |||||
} | } | ||||
void getAndDisplayRtcTime() { | void getAndDisplayRtcTime() { | ||||
@@ -100,6 +104,27 @@ namespace debug { | |||||
Log.notice(F("%d/%d/%d %d:%d:%d"), time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second); | Log.notice(F("%d/%d/%d %d:%d:%d"), time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second); | ||||
} | } | ||||
void getAndDisplayEepromConfig() { | |||||
hardware::i2c::eepromPowerOn(); | |||||
config::read(); | |||||
hardware::i2c::eepromPowerOff(); | |||||
Log.notice(F("%s, %s, %d, %d"), config::value.seed, config::value.version, config::value.firstEntry, config::value.lastEntry); | |||||
} | |||||
void getAndDisplayEepromPositions() { | |||||
uint16_t firstEntryIndex = config::value.firstEntry; | |||||
uint16_t currentEntryIndex = firstEntryIndex; | |||||
PositionEntry currentEntry; | |||||
do { | |||||
positions::get(currentEntryIndex, currentEntry); | |||||
Log.notice(F("%d%%, %dmV, %d, %s"), currentEntry.battery.level, currentEntry.battery.voltage, currentEntry.status, currentEntry.position); | |||||
} while (currentEntryIndex != config::value.lastEntry); | |||||
} | |||||
void setRtcTime() { | void setRtcTime() { | ||||
tmElements_t time; | tmElements_t time; | ||||
gps::getTime(time); | gps::getTime(time); | ||||
@@ -39,7 +39,10 @@ namespace debug { | |||||
RTC_ON = 7, | RTC_ON = 7, | ||||
RTC_OFF = 8, | RTC_OFF = 8, | ||||
RTC_GET = 9, | RTC_GET = 9, | ||||
RTC_SET = 10 | |||||
RTC_SET = 10, | |||||
SD_WRITE_TEST = 11, | |||||
EEPROM_GET_CONFIG = 16, | |||||
EEPROM_GET_ENTRIES = 17 | |||||
}; | }; | ||||
void waitForSerial(); | void waitForSerial(); | ||||
@@ -52,6 +55,10 @@ namespace debug { | |||||
void getAndDisplayRtcTime(); | void getAndDisplayRtcTime(); | ||||
void setRtcTime(); | void setRtcTime(); | ||||
void getAndDisplayEepromConfig(); | |||||
void getAndDisplayEepromPositions(); | |||||
inline void displayFreeRam() { Serial.println(freeRam()); } | inline void displayFreeRam() { Serial.println(freeRam()); } | ||||
} | } |
@@ -52,6 +52,14 @@ void loop() { | |||||
break; | break; | ||||
case debug::GPSTRACKER_DEBUG_COMMAND::RTC_SET: | case debug::GPSTRACKER_DEBUG_COMMAND::RTC_SET: | ||||
debug::setRtcTime(); | debug::setRtcTime(); | ||||
break; | |||||
case debug::GPSTRACKER_DEBUG_COMMAND::EEPROM_GET_CONFIG: | |||||
debug::getAndDisplayEepromConfig(); | |||||
break; | |||||
case debug::GPSTRACKER_DEBUG_COMMAND::EEPROM_GET_ENTRIES: | |||||
debug::getAndDisplayEepromPositions(); | |||||
break; | |||||
case debug::GPSTRACKER_DEBUG_COMMAND::SD_WRITE_TEST: | |||||
default: | default: | ||||
Serial.println(F("Unsupported command !")); | Serial.println(F("Unsupported command !")); | ||||
} | } | ||||
@@ -6,7 +6,8 @@ | |||||
#include <SIM808_Types.h> | #include <SIM808_Types.h> | ||||
#include <Wire.h> | #include <Wire.h> | ||||
#include <E24.h> | |||||
namespace hardware { | namespace hardware { | ||||
namespace sim808 { | namespace sim808 { | ||||
@@ -70,8 +71,12 @@ namespace hardware { | |||||
#define DEVICE_RTC 1 | #define DEVICE_RTC 1 | ||||
#define DEVICE_EEPROM 2 | #define DEVICE_EEPROM 2 | ||||
E24 eeprom = E24(E24Size_t::E24_512K); | |||||
uint8_t powered = 0; | uint8_t powered = 0; | ||||
//inline void powered() { digitalRead(I2C_PWR) == HIGH; } //TODO = replace enum with just reading the output pin ? | |||||
void powerOn() { | void powerOn() { | ||||
if (powered > 0) return; | if (powered > 0) return; | ||||
@@ -1,6 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <SIM808.h> | #include <SIM808.h> | ||||
#include <E24.h> | |||||
namespace hardware { | namespace hardware { | ||||
@@ -20,6 +21,8 @@ namespace hardware { | |||||
} | } | ||||
namespace i2c { | namespace i2c { | ||||
extern E24 eeprom; | |||||
void powerOn(); | void powerOn(); | ||||
void powerOff(); | void powerOff(); | ||||
@@ -1,6 +1,9 @@ | |||||
#include "MainUnit.h" | #include "MainUnit.h" | ||||
#include "Rtc.h" | #include "Rtc.h" | ||||
#include "Pins.h" | #include "Pins.h" | ||||
#include "Debug.h" | |||||
const char WOKE_UP[] PROGMEM = "Woke up from sleep"; | |||||
namespace mainunit { | namespace mainunit { | ||||
@@ -18,11 +21,20 @@ namespace mainunit { | |||||
} | } | ||||
void sleep(period_t period) { | void sleep(period_t period) { | ||||
Log.verbose(F("Sleeping for period : %d"), period); | |||||
LowPower.powerDown(period, ADC_OFF, BOD_OFF); | LowPower.powerDown(period, ADC_OFF, BOD_OFF); | ||||
Log.verbose(reinterpret_cast<const __FlashStringHelper *>(pgm_read_word(WOKE_UP))); | |||||
} | } | ||||
void deepSleep(uint16_t seconds) { | void deepSleep(uint16_t seconds) { | ||||
Log.verbose(F("Deep sleeping for %d seconds"), seconds); | |||||
interruptIn(seconds); | interruptIn(seconds); | ||||
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); | LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); | ||||
Log.verbose(reinterpret_cast<const __FlashStringHelper *>(pgm_read_word(WOKE_UP))); | |||||
} | } | ||||
} | } |
@@ -1,15 +1,70 @@ | |||||
#include "Positions.h" | #include "Positions.h" | ||||
#include "Debug.h" | |||||
#include "Config.h" | |||||
#include "Gps.h" | #include "Gps.h" | ||||
#include "Network.h" | #include "Network.h" | ||||
#include "Storage.h" | #include "Storage.h" | ||||
#define LOGGER_NAME "Positions" | #define LOGGER_NAME "Positions" | ||||
#define ENTRY_RESERVED_SIZE 128 | |||||
#define ENTRIES_ADDR ENTRY_RESERVED_SIZE | |||||
namespace positions { | namespace positions { | ||||
void appendLast() { | |||||
//write gps::lastPosition to eeprom and eventually to sd card | |||||
uint16_t getEntryAddress(uint16_t &index) { | |||||
uint16_t address = ENTRIES_ADDR + (ENTRY_RESERVED_SIZE * index); | |||||
if (address + ENTRY_RESERVED_SIZE > E24_MAX_ADDRESS(hardware::i2c::eeprom.getSize())) { | |||||
address = ENTRIES_ADDR; | |||||
index = 0; | |||||
} | |||||
return address; | |||||
} | |||||
void setEntriesIndexes(uint16_t lastEntry) { | |||||
uint16_t firstEntry = config::value.firstEntry; | |||||
while (config::value.lastEntry < config::value.firstEntry) { | |||||
config::value.firstEntry++; | |||||
getEntryAddress(firstEntry); | |||||
} | |||||
config::value.lastEntry = lastEntry; | |||||
config::value.firstEntry = firstEntry; | |||||
} | |||||
void appendLast(const SIM808ChargingStatus battery, const SIM808_GPS_STATUS gpsStatus) { | |||||
VERBOSE("appendLast"); | |||||
uint16_t entryIndex; | |||||
uint16_t entryAddress; | |||||
PositionEntry entry = { battery, gpsStatus }; | |||||
strncpy(entry.position, gps::lastPosition, POSITION_SIZE); | |||||
storage::powerOn(); | |||||
config::read(); | |||||
entryIndex = config::value.lastEntry + 1; | |||||
entryAddress = getEntryAddress(entryIndex); | |||||
bool success = hardware::i2c::eeprom.writeBlock(entryAddress, entry); | |||||
if (success) { | |||||
VERBOSE_MSG("appendLast", "written to EEPROM"); | |||||
setEntriesIndexes(entryIndex); | |||||
config::write(); | |||||
} | |||||
storage::powerOff(); | |||||
} | |||||
void get(uint16_t &index, PositionEntry &entry) { | |||||
uint16_t entryAddress = getEntryAddress(index); | |||||
storage::powerOn(); | |||||
hardware::i2c::eeprom.readBlock(entryAddress, entry); | |||||
storage::powerOff(); | |||||
} | } | ||||
bool needsToSend() { | bool needsToSend() { | ||||
@@ -1,7 +1,19 @@ | |||||
#pragma once | #pragma once | ||||
#include <SIM808_Types.h> | |||||
#define POSITION_SIZE 115 | |||||
struct PositionEntry { | |||||
SIM808ChargingStatus battery; //sizeof = 4 | |||||
SIM808_GPS_STATUS status; //sizeof = 1 | |||||
char position[POSITION_SIZE]; //sizeof = 115 | |||||
}; //sizeof = 119 | |||||
namespace positions { | namespace positions { | ||||
void appendLast(); | |||||
void appendLast(const SIM808ChargingStatus battery, const SIM808_GPS_STATUS gpsStatus); | |||||
void get(uint16_t &index, PositionEntry &entry); | |||||
bool needsToSend(); | bool needsToSend(); | ||||
void send(); | void send(); |
@@ -20,7 +20,7 @@ namespace rtc { | |||||
inline void setAlarm(uint16_t seconds) { | inline void setAlarm(uint16_t seconds) { | ||||
tmElements_t time; | tmElements_t time; | ||||
getTime(time); | getTime(time); | ||||
setAlarm(makeTime(time) + seconds); //TODO : use operator | |||||
setAlarm(makeTime(time) + seconds); | |||||
} | } | ||||
void setAlarm(tmElements_t &time); | void setAlarm(tmElements_t &time); |
@@ -10,4 +10,6 @@ namespace storage { | |||||
inline void powerOff() { | inline void powerOff() { | ||||
hardware::i2c::eepromPowerOff(); | hardware::i2c::eepromPowerOff(); | ||||
} | } | ||||
} | } |