kopia lustrzana https://github.com/DL7AD/pecanpico9
- Merged dbgon and dbgoff command to debug
- Fixed error in SOI-not-found flag in debug.c - Added camera-command command (for testing different camera options while watching the livestream) - Fixed table header in readLog USB command - Added last-image-id to track-point struct (which is also logged), SSDV transmission will start with next ID on STM32 reset. This has been done while habhub alway mixes up different images with the same image id. - Added thread (module) configuration printout on USB debug - Added GPS_LOG and GPS_OFF flag - Changed tracking manager initialization strategy: Tracking Manager runs all time and also logs when there is no new GPS fix Tracking Manager logs images ID Tracking Manager doesnt switch on GPS unless there is a position thread running (in order to save energy when position is not sent out) Implemented several flags in decoder2.py Added script command.c which sends camera registers via USB to the OV5640.Develop
rodzic
e9cff81fa4
commit
37180ab892
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import serial,os,re,sys
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
import pygame.time
|
||||
from cStringIO import StringIO
|
||||
|
||||
try:
|
||||
ser = serial.Serial(port='/dev/ttyACM1')
|
||||
except:
|
||||
sys.stderr.write('Error: Could not open serial port\n')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
ser.write('\r\n')
|
||||
ser.write('command '+str(int(sys.argv[1], 16))+' '+str(int(sys.argv[2], 16))+'\r\n')
|
||||
ser.close()
|
|
@ -40,8 +40,15 @@ while True:
|
|||
print line.strip()
|
||||
continue
|
||||
|
||||
i += 1
|
||||
|
||||
if int(size) == 0:
|
||||
ser.write('picture\r\n')
|
||||
continue
|
||||
|
||||
imgbuf = ser.read(int(size))
|
||||
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == QUIT:
|
||||
exit(0)
|
||||
|
@ -61,6 +68,11 @@ while True:
|
|||
screen.blit(textsurface,(0,0))
|
||||
pygame.display.flip()
|
||||
pygame.display.update(displaygroup.draw(screen))
|
||||
|
||||
f = open('data/data'+str(i)+'.jpg','wb')
|
||||
f.write(imgbuf)
|
||||
f.close()
|
||||
|
||||
except Exception as e:
|
||||
print str(e)
|
||||
textsurface = myfont.render('Error %s' % (e), False, (255, 100, 100))
|
||||
|
@ -69,7 +81,6 @@ while True:
|
|||
pygame.display.update(displaygroup.draw(screen))
|
||||
|
||||
ser.write('picture\r\n')
|
||||
i += 1
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import serial,os,re,sys
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
import pygame.time
|
||||
from cStringIO import StringIO
|
||||
|
||||
try:
|
||||
ser = serial.Serial(port='/dev/ttyACM1')
|
||||
except:
|
||||
sys.stderr.write('Error: Could not open serial port\n')
|
||||
sys.exit(1)
|
||||
|
||||
while True:
|
||||
ser.read(1)
|
|
@ -463,7 +463,7 @@ void start_user_modules(void)
|
|||
config[4].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
|
||||
config[4].ssdv_conf.res = RES_VGA; // Resolution VGA
|
||||
config[4].ssdv_conf.quality = 4; // Image quality
|
||||
//start_image_thread(&config[4]);
|
||||
start_image_thread(&config[4]);
|
||||
|
||||
// Module IMAGE, SSDV 2m 2FSK
|
||||
config[5].power = 127; // Transmission Power
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "config.h"
|
||||
#include "image.h"
|
||||
#include "tracking.h"
|
||||
#include "pi2c.h"
|
||||
|
||||
const SerialConfig uart_config =
|
||||
{
|
||||
|
@ -18,23 +19,19 @@ mutex_t trace_mtx; // Used internal to synchronize multiple chprintf in debug.h
|
|||
|
||||
bool debug_on_usb = false;
|
||||
|
||||
void debugOnUSB_Off(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
void debugOnUSB(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
(void)chp;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
debug_on_usb = false;
|
||||
if(argc < 1)
|
||||
{
|
||||
chprintf(chp, "Argument missing!\r\n");
|
||||
chprintf(chp, "Argument 1: 1 for switch on, 0 for switch off!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
debug_on_usb = atoi(argv[0]);
|
||||
}
|
||||
|
||||
void debugOnUSB_On(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
(void)chp;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
debug_on_usb = true;
|
||||
}
|
||||
|
||||
static uint8_t usb_buffer[96*1024] __attribute__((aligned(32))); // USB image buffer
|
||||
static uint8_t usb_buffer[64*1024] __attribute__((aligned(32))); // USB image buffer
|
||||
void printPicture(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
(void)argc;
|
||||
|
@ -67,8 +64,8 @@ void printPicture(BaseSequentialStream *chp, int argc, char *argv[])
|
|||
}
|
||||
if(!start_detected)
|
||||
{
|
||||
TRACE_USB("DATA > image,jpeg,0");
|
||||
TRACE_USB("DATA > error,no SOI flag found");
|
||||
TRACE_USB("DATA > image/jpeg,0");
|
||||
TRACE_USB("DATA > text/trace,no SOI flag found");
|
||||
}
|
||||
|
||||
} else { // No camera found
|
||||
|
@ -79,16 +76,11 @@ void printPicture(BaseSequentialStream *chp, int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
trackPoint_t* getLogBuffer(uint16_t id)
|
||||
void command2Camera(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
if(sizeof(trackPoint_t)*id < LOG_SECTOR_SIZE-sizeof(trackPoint_t))
|
||||
{
|
||||
return (trackPoint_t*)(LOG_FLASH_ADDR1 + id * sizeof(trackPoint_t));
|
||||
} else if((id-(LOG_SECTOR_SIZE/sizeof(trackPoint_t)))*sizeof(trackPoint_t) < LOG_SECTOR_SIZE-sizeof(trackPoint_t)) {
|
||||
return (trackPoint_t*)(LOG_FLASH_ADDR2 + (id-(LOG_SECTOR_SIZE/sizeof(trackPoint_t))) * sizeof(trackPoint_t));
|
||||
} else { // Outside of memory address allocation
|
||||
return NULL;
|
||||
}
|
||||
(void)chp;
|
||||
(void)argc;
|
||||
I2C_write8_16bitreg(0x3C, atoi(argv[0]), atoi(argv[1]));
|
||||
}
|
||||
|
||||
void readLog(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
|
@ -96,17 +88,19 @@ void readLog(BaseSequentialStream *chp, int argc, char *argv[])
|
|||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
chprintf(chp, "id,date,time,lat,lon,alt,sats,ttff,vbat,vsol,vsub,pbat,rbat,press,temp,hum,idimg\r\n");
|
||||
|
||||
trackPoint_t *tp;
|
||||
for(uint16_t i=0; (tp = getLogBuffer(i)) != NULL; i++)
|
||||
if(tp->id != 0xFFFFFFFF)
|
||||
{
|
||||
chprintf( chp,
|
||||
"%d,%04d-%02d-%02d,%02d:%02d:%02d,%d.%05d,%d.%05d,%d,%d,%d,%d.%03d,%d.%03d,%d.%03d,%d,%d,%d.%01d,%2d.%02d,%2d.%01d\r\n",
|
||||
"%d,%04d-%02d-%02d,%02d:%02d:%02d,%d.%05d,%d.%05d,%d,%d,%d,%d.%03d,%d.%03d,%d.%03d,%d,%d,%d.%01d,%2d.%02d,%2d.%01d,%d\r\n",
|
||||
tp->id,tp->time.year, tp->time.month, tp->time.day, tp->time.hour, tp->time.minute, tp->time.day,
|
||||
tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt,
|
||||
tp->gps_sats, tp->gps_ttff,
|
||||
tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->adc_vusb/1000, (tp->adc_vusb%1000), tp->adc_pbat, tp->adc_rbat,
|
||||
tp->air_press/10, tp->air_press%10, tp->air_temp/100, tp->air_temp%100, tp->air_hum/10, tp->air_hum%10
|
||||
tp->air_press/10, tp->air_press%10, tp->air_temp/100, tp->air_temp%100, tp->air_hum/10, tp->air_hum%10, tp->id_image
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +111,7 @@ void printConfig(BaseSequentialStream *chp, int argc, char *argv[])
|
|||
{
|
||||
chprintf(chp, "Argument missing!\r\n");
|
||||
chprintf(chp, "Argument 1: Id of config!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t id = atoi(argv[0]);
|
||||
|
@ -125,9 +120,14 @@ void printConfig(BaseSequentialStream *chp, int argc, char *argv[])
|
|||
chprintf(chp, "Power: %d\r\n", config[id].power);
|
||||
|
||||
if(config[id].frequency.type == FREQ_STATIC) {
|
||||
chprintf(chp, "Frequency: %d Hz\r\n", config[id].frequency.hz);
|
||||
uint32_t freq = config[id].frequency.hz;
|
||||
if((freq/1000)*1000 == freq)
|
||||
chprintf(chp, "Frequency: %d.%03d MHz\r\n", freq/1000000, (freq%1000000)/1000);
|
||||
else
|
||||
chprintf(chp, "Frequency: %d.%03d MHz\r\n", freq/1000000, (freq%1000000));
|
||||
} else {
|
||||
chprintf(chp, "Frequency: APRS region dependent (currently %d Hz\r\n", getFrequency(&config[id].frequency));
|
||||
uint32_t freq = getFrequency(&config[id].frequency);
|
||||
chprintf(chp, "Frequency: APRS region dependent (currently %d.%03d MHz)\r\n", freq/1000000, (freq%1000000)/1000);
|
||||
}
|
||||
|
||||
chprintf(chp, "Protocol: %d\r\n", config[id].protocol);
|
||||
|
|
|
@ -104,11 +104,11 @@ extern bool debug_on_usb;
|
|||
TRACE_INFO("%-4s > Current time: %02d-%02d-%02d %02d:%02d:%02d:%03d", thd, dbgtime.year, dbgtime.month, dbgtime.day, dbgtime.hour, dbgtime.minute, dbgtime.second, dbgtime.millisecond); \
|
||||
}
|
||||
|
||||
void debugOnUSB_Off(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
void debugOnUSB_On(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
void debugOnUSB(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
void printConfig(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
void printPicture(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
void readLog(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
void command2Camera(BaseSequentialStream *chp, int argc, char *argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -27,11 +27,11 @@ static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
|
|||
{ 0x4051, 0x8f },
|
||||
|
||||
{ 0x3008, 0x42 },
|
||||
{ 0x3103, 0x03 },
|
||||
{ 0x3103, 0x03 },
|
||||
{ 0x3017, 0x7f },
|
||||
{ 0x3018, 0xff },
|
||||
{ 0x302c, 0x02 },
|
||||
{ 0x3108, 0x21 },
|
||||
{ 0x3108, 0x21 }, // PCLK root divider [5:4]
|
||||
{ 0x3630, 0x2e },//2e
|
||||
{ 0x3632, 0xe2 },
|
||||
{ 0x3633, 0x23 },//23
|
||||
|
@ -92,12 +92,12 @@ static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
|
|||
{ 0x3814, 0x31 },
|
||||
{ 0x3815, 0x31 },
|
||||
|
||||
{ 0x3034, 0x1a },
|
||||
{ 0x3035, 0x11 }, //15fps
|
||||
{ 0x3036, 0x46 },
|
||||
{ 0x3037, 0x14 },
|
||||
{ 0x3038, 0x00 },
|
||||
{ 0x3039, 0x00 },
|
||||
{ 0x3034, 0x1a }, // PLL charge pump control [7:4]
|
||||
{ 0x3035, 0x11 }, // System clock divider [7:4]
|
||||
{ 0x3036, 0x46 }, // PLL multiplier [7:0]
|
||||
{ 0x3037, 0x14 }, // PLL root divider [4], PLL pre-divider [3:0]
|
||||
{ 0x3038, 0x00 }, // System control registers (changing not recommended)
|
||||
{ 0x3039, 0x00 }, // PLL bypass [7]
|
||||
|
||||
{ 0x380c, 0x07 },
|
||||
{ 0x380d, 0x68 },
|
||||
|
@ -802,7 +802,6 @@ void set6MHz(void)
|
|||
*/
|
||||
static bool analyze_image(uint8_t *image, uint32_t image_len)
|
||||
{
|
||||
return true;
|
||||
ssdv_t ssdv;
|
||||
uint8_t pkt[SSDV_PKT_SIZE];
|
||||
uint8_t *b;
|
||||
|
@ -851,7 +850,7 @@ static bool analyze_image(uint8_t *image, uint32_t image_len)
|
|||
*/
|
||||
uint32_t OV5640_Snapshot2RAM(uint8_t* buffer, uint32_t size, resolution_t res, bool enableJpegValidation)
|
||||
{
|
||||
uint8_t cntr = 5;
|
||||
uint8_t cntr = 10;
|
||||
bool status;
|
||||
bool jpegValid;
|
||||
uint32_t size_sampled;
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
#include "shell.h"
|
||||
|
||||
static const ShellCommand commands[] = {
|
||||
{"dbgon", debugOnUSB_On},
|
||||
{"dbgoff", debugOnUSB_Off},
|
||||
{"debug", debugOnUSB},
|
||||
{"picture", printPicture},
|
||||
{"log", readLog},
|
||||
// {"printconfig", printConfig}, FIXME: This feature is faulty at the moment
|
||||
{"config", printConfig},
|
||||
{"command", command2Camera},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const ShellConfig shell_cfg = {
|
||||
(BaseSequentialStream *)&SDU1,
|
||||
(BaseSequentialStream*)&SDU1,
|
||||
commands
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,7 @@ int main(void) {
|
|||
|
||||
// Voltage switching (1.8V <=> 3.0V)
|
||||
#if ACTIVATE_USB || ACTIVATE_3V
|
||||
boost_voltage(true); // Ramp up voltage to 3V
|
||||
boost_voltage(true); // Ramp up voltage to 3V
|
||||
chThdSleepMilliseconds(100);
|
||||
#endif
|
||||
|
||||
|
@ -54,9 +54,8 @@ int main(void) {
|
|||
start_essential_threads(); // Startup required modules (tracking managemer, watchdog)
|
||||
start_user_modules(); // Startup optional modules (eg. POSITION, LOG, ...)
|
||||
|
||||
// Print time every 10 sec
|
||||
while(true) {
|
||||
if (SDU1.config->usbp->state == USB_ACTIVE) {
|
||||
if(SDU1.config->usbp->state == USB_ACTIVE) {
|
||||
thread_t *shelltp = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(512), "shell", NORMALPRIO+1, shellThread, (void*)&shell_cfg);
|
||||
chThdWait(shelltp);
|
||||
}
|
||||
|
|
|
@ -125,6 +125,11 @@ uint32_t aprs_encode_position(uint8_t* message, mod_t mod, const aprs_conf_t *co
|
|||
chsnprintf(temp, sizeof(temp), "%d", ++loss_of_gps_counter);
|
||||
ax25_send_string(&packet, temp);
|
||||
|
||||
} else if(trackPoint->gps_lock == GPS_LOG) { // GPS position from log (because the tracker has been just switched on)
|
||||
|
||||
ax25_send_string(&packet, " GPS FROM LOG");
|
||||
loss_of_gps_counter = 0;
|
||||
|
||||
} else {
|
||||
loss_of_gps_counter = 0;
|
||||
}
|
||||
|
|
|
@ -305,45 +305,48 @@ void shutdownRadio(void)
|
|||
uint32_t getAPRSRegionFrequency(void) {
|
||||
trackPoint_t *point = getLastTrackPoint();
|
||||
|
||||
uint32_t freq = 0; // Position unknown
|
||||
// Position unknown
|
||||
if(point == NULL || (point->gps_lat == 0 && point->gps_lon == 0))
|
||||
return 0;
|
||||
|
||||
// America 144.390 MHz
|
||||
if(isPointInAmerica(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_AMERICA;
|
||||
return APRS_FREQ_AMERICA;
|
||||
|
||||
// China 144.640 MHz
|
||||
if(isPointInChina(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_CHINA;
|
||||
return APRS_FREQ_CHINA;
|
||||
|
||||
// Japan 144.660 MHz
|
||||
if(isPointInJapan(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_JAPAN;
|
||||
return APRS_FREQ_JAPAN;
|
||||
|
||||
// Southkorea 144.620 MHz
|
||||
if(isPointInSouthkorea(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_SOUTHKOREA;
|
||||
return APRS_FREQ_SOUTHKOREA;
|
||||
|
||||
// Southkorea 144.620 MHz
|
||||
if(isPointInSoutheastAsia(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_SOUTHEASTASIA;
|
||||
return APRS_FREQ_SOUTHEASTASIA;
|
||||
|
||||
// Australia 145.175 MHz
|
||||
if(isPointInAustralia(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_AUSTRALIA;
|
||||
return APRS_FREQ_AUSTRALIA;
|
||||
|
||||
// Australia 144.575 MHz
|
||||
if(isPointInNewZealand(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_NEWZEALAND;
|
||||
return APRS_FREQ_NEWZEALAND;
|
||||
|
||||
// Argentina/Paraguay/Uruguay 144.930 MHz
|
||||
if(isPointInArgentina(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_ARGENTINA;
|
||||
return APRS_FREQ_ARGENTINA;
|
||||
|
||||
// Brazil 145.575 MHz
|
||||
if(isPointInBrazil(point->gps_lat, point->gps_lon))
|
||||
freq = APRS_FREQ_BRAZIL;
|
||||
return APRS_FREQ_BRAZIL;
|
||||
|
||||
return freq;
|
||||
// For the rest of the world 144.800 MHz
|
||||
return 144800000;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -420,7 +423,7 @@ uint32_t getFrequency(freq_conf_t *config)
|
|||
switch(config->type) {
|
||||
case FREQ_APRS_REGION:; // Dynamic frequency (determined by GPS position)
|
||||
uint32_t freq = getAPRSRegionFrequency();
|
||||
if(!freq) // Use default frequency (if freq is not set = position unknown)
|
||||
if(!freq) // Use default frequency (if freq is 0 = position unknown)
|
||||
return config->hz;
|
||||
return freq;
|
||||
|
||||
|
|
|
@ -273,7 +273,7 @@ const uint8_t noCameraFound[4071] = {
|
|||
0xBD, 0xC0, 0x20, 0x00, 0x01, 0xFF, 0xD9
|
||||
};
|
||||
|
||||
static uint8_t gimage_id; // Global image ID (for all image threads)
|
||||
uint8_t gimage_id; // Global image ID (for all image threads)
|
||||
mutex_t camera_mtx;
|
||||
bool camera_mtx_init = false;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
void start_image_thread(module_conf_t *conf);
|
||||
bool takePicture(ssdv_conf_t *conf, bool enableJpegValidation);
|
||||
extern mutex_t camera_mtx;
|
||||
extern uint8_t gimage_id;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ void start_position_thread(module_conf_t *conf)
|
|||
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
|
||||
|
||||
// Start tracking manager (if not running yet)
|
||||
init_tracking_manager();
|
||||
init_tracking_manager(true);
|
||||
|
||||
// Start position thread
|
||||
TRACE_INFO("POS > Startup position thread");
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "threads.h"
|
||||
#include "tracking.h"
|
||||
#include "watchdog.h"
|
||||
#include "image.h"
|
||||
#include "pi2c.h"
|
||||
#include "pac1720.h"
|
||||
|
||||
|
@ -15,9 +13,8 @@ void start_essential_threads(void) {
|
|||
// Init watchdog
|
||||
init_watchdog();
|
||||
|
||||
// Initialize essential mutex's
|
||||
|
||||
|
||||
// Initialize tracking manager (without GPS, GPS is initialized if needed by position thread)
|
||||
init_tracking_manager(false);
|
||||
|
||||
pi2cInit(); // Initialize I2C
|
||||
pac1720_init(); // Initialize current measurement
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "tracking.h"
|
||||
#include "debug.h"
|
||||
#include "ptime.h"
|
||||
#include "config.h"
|
||||
#include "ublox.h"
|
||||
#include "bme280.h"
|
||||
|
@ -12,12 +11,14 @@
|
|||
#include "radio.h"
|
||||
#include "flash.h"
|
||||
#include "watchdog.h"
|
||||
#include "image.h"
|
||||
|
||||
static trackPoint_t trackPoints[2];
|
||||
static trackPoint_t* lastTrackPoint;
|
||||
static systime_t nextLogEntryTimer;
|
||||
static module_conf_t trac_conf = {.name = "TRAC"}; // Fake config needed for watchdog tracking
|
||||
static bool threadStarted = false;
|
||||
static bool tracking_useGPS = false;
|
||||
|
||||
/**
|
||||
* Returns most recent track point witch is complete.
|
||||
|
@ -27,73 +28,48 @@ trackPoint_t* getLastTrackPoint(void)
|
|||
return lastTrackPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next free log entry address in memory. Returns 0 if all cells are
|
||||
* filled with data
|
||||
*/
|
||||
static uint32_t getNextFreeLogAddress(void)
|
||||
trackPoint_t* getLogBuffer(uint16_t id)
|
||||
{
|
||||
// Search in flash sector 10
|
||||
for(uint32_t address = LOG_FLASH_ADDR1; address < LOG_FLASH_ADDR1+LOG_SECTOR_SIZE; address += sizeof(trackPoint_t))
|
||||
if(sizeof(trackPoint_t)*id < LOG_SECTOR_SIZE-sizeof(trackPoint_t))
|
||||
{
|
||||
trackPoint_t pt;
|
||||
flashRead(address, (char*)&pt, sizeof(trackPoint_t));
|
||||
if(pt.id == 0xFFFFFFFF)
|
||||
return address;
|
||||
return (trackPoint_t*)(LOG_FLASH_ADDR1 + id * sizeof(trackPoint_t));
|
||||
} else if((id-(LOG_SECTOR_SIZE/sizeof(trackPoint_t)))*sizeof(trackPoint_t) < LOG_SECTOR_SIZE-sizeof(trackPoint_t)) {
|
||||
return (trackPoint_t*)(LOG_FLASH_ADDR2 + (id-(LOG_SECTOR_SIZE/sizeof(trackPoint_t))) * sizeof(trackPoint_t));
|
||||
} else { // Outside of memory address allocation
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search in flash sector 11
|
||||
for(uint32_t address = LOG_FLASH_ADDR2; address < LOG_FLASH_ADDR2+LOG_SECTOR_SIZE; address += sizeof(trackPoint_t))
|
||||
{
|
||||
trackPoint_t pt;
|
||||
flashRead(address, (char*)&pt, sizeof(trackPoint_t));
|
||||
if(pt.id == 0xFFFFFFFF)
|
||||
return address;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next free log entry address in memory. Returns 0 if all cells are
|
||||
* filled with data
|
||||
*/
|
||||
static bool getLastLog(trackPoint_t* last)
|
||||
static trackPoint_t* getNextFreeLogAddress(void)
|
||||
{
|
||||
TRACE_INFO("TRAC > Read last track point from flash memory");
|
||||
trackPoint_t* tp;
|
||||
for(uint16_t i=0; (tp = getLogBuffer(i)) != NULL; i++)
|
||||
if(tp->id == 0xFFFFFFFF)
|
||||
return tp;
|
||||
|
||||
uint64_t last_time = 0;
|
||||
uint32_t last_address = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search in flash sector 10
|
||||
for(uint32_t address = LOG_FLASH_ADDR1; address < LOG_FLASH_ADDR1+LOG_SECTOR_SIZE; address += sizeof(trackPoint_t))
|
||||
{
|
||||
trackPoint_t pt;
|
||||
flashRead(address, (char*)&pt, sizeof(trackPoint_t));
|
||||
if(pt.id != 0xFFFFFFFF && date2UnixTimestamp(pt.time) >= last_time) {
|
||||
last_address = address;
|
||||
last_time = date2UnixTimestamp(pt.time);
|
||||
}
|
||||
}
|
||||
|
||||
// Search in flash sector 11
|
||||
for(uint32_t address = LOG_FLASH_ADDR2; address < LOG_FLASH_ADDR2+LOG_SECTOR_SIZE; address += sizeof(trackPoint_t))
|
||||
{
|
||||
trackPoint_t pt;
|
||||
flashRead(address, (char*)&pt, sizeof(trackPoint_t));
|
||||
if(pt.id != 0xFFFFFFFF && date2UnixTimestamp(pt.time) >= last_time) {
|
||||
last_address = address;
|
||||
last_time = date2UnixTimestamp(pt.time);
|
||||
}
|
||||
}
|
||||
|
||||
if(last_address) {
|
||||
flashRead(last_address, (char*)last, sizeof(trackPoint_t));
|
||||
TRACE_INFO("TRAC > Found track point in flash memory ID=%d", last->id);
|
||||
return true;
|
||||
} else {
|
||||
TRACE_INFO("TRAC > No track point found in flash memory");
|
||||
return false;
|
||||
/**
|
||||
* Returns next free log entry address in memory. Returns 0 if all cells are
|
||||
* filled with data
|
||||
*/
|
||||
static trackPoint_t* getLastLog(void)
|
||||
{
|
||||
trackPoint_t* last = NULL;
|
||||
trackPoint_t* tp;
|
||||
for(uint16_t i=0; (tp = getLogBuffer(i)) != NULL; i++) {
|
||||
if(tp->id == 0xFFFFFFFF)
|
||||
return last; // Found last entry
|
||||
last = tp;
|
||||
}
|
||||
if(last->id != 0xFFFFFFFF)
|
||||
return last; // All memory entries are use, so the very last one must be the most recent one.
|
||||
return NULL; // There is no log entry in memory
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,13 +95,13 @@ static void eraseOldestLogData(void)
|
|||
static void writeLogTrackPoint(trackPoint_t* tp)
|
||||
{
|
||||
// Get address to write on
|
||||
uint32_t address = getNextFreeLogAddress();
|
||||
if(!address) // Memory completly used, erase oldest data
|
||||
trackPoint_t* address = getNextFreeLogAddress();
|
||||
if(address == NULL) // Memory completly used, erase oldest data
|
||||
{
|
||||
eraseOldestLogData();
|
||||
address = getNextFreeLogAddress();
|
||||
}
|
||||
if(!address) // Something went wront at erasing the memory
|
||||
if(address == NULL) // Something went wront at erasing the memory
|
||||
{
|
||||
TRACE_ERROR("TRAC > Erasing flash failed");
|
||||
return;
|
||||
|
@ -133,12 +109,12 @@ static void writeLogTrackPoint(trackPoint_t* tp)
|
|||
|
||||
// Write data into flash
|
||||
TRACE_INFO("TRAC > Flash write (ADDR=%08x)", address);
|
||||
flashSectorBegin(flashSectorAt(address));
|
||||
flashWrite(address, (char*)tp, sizeof(trackPoint_t));
|
||||
flashSectorEnd(flashSectorAt(address));
|
||||
flashSectorBegin(flashSectorAt((uint32_t)address));
|
||||
flashWrite((uint32_t)address, (char*)tp, sizeof(trackPoint_t));
|
||||
flashSectorEnd(flashSectorAt((uint32_t)address));
|
||||
|
||||
// Verify
|
||||
if(flashCompare(address, (char*)tp, sizeof(trackPoint_t)))
|
||||
if(flashCompare((uint32_t)address, (char*)tp, sizeof(trackPoint_t)))
|
||||
TRACE_INFO("TRAC > Flash write OK")
|
||||
else
|
||||
TRACE_ERROR("TRAC > Flash write failed");
|
||||
|
@ -172,20 +148,25 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
lastTrackPoint->time.minute = rtc.minute;
|
||||
lastTrackPoint->time.second = rtc.second;
|
||||
|
||||
// Get last GPS fix from memory
|
||||
trackPoint_t lastLogPoint;
|
||||
if(getLastLog(&lastLogPoint)) { // If there has been stored a trackpoint, then get the last know GPS fix
|
||||
lastTrackPoint->gps_lat = lastLogPoint.gps_lat;
|
||||
lastTrackPoint->gps_lon = lastLogPoint.gps_lon;
|
||||
lastTrackPoint->gps_alt = lastLogPoint.gps_alt;
|
||||
// Get last tracking point from memory
|
||||
TRACE_INFO("TRAC > Read last track point from flash memory");
|
||||
trackPoint_t* lastLogPoint = getLastLog();
|
||||
|
||||
if(lastLogPoint != NULL) { // If there has been stored a trackpoint, then get the last know GPS fix
|
||||
TRACE_INFO("TRAC > Found track point in flash memory ID=%d", lastLogPoint->id);
|
||||
lastTrackPoint->gps_lat = lastLogPoint->gps_lat;
|
||||
lastTrackPoint->gps_lon = lastLogPoint->gps_lon;
|
||||
lastTrackPoint->gps_alt = lastLogPoint->gps_alt;
|
||||
} else {
|
||||
TRACE_INFO("TRAC > No track point found in flash memory");
|
||||
}
|
||||
|
||||
lastTrackPoint->gps_lock = GPS_LOSS; // But tell the user that there is no current lock nor any GPS sats locked
|
||||
lastTrackPoint->gps_lock = GPS_LOG; // Tell other threads that it has been taken from log
|
||||
lastTrackPoint->gps_sats = 0;
|
||||
lastTrackPoint->gps_ttff = 0;
|
||||
|
||||
// Debug last stored GPS position
|
||||
if(lastLogPoint.id != 0xFFFFFFFF) {
|
||||
if(lastLogPoint != NULL) {
|
||||
TRACE_INFO(
|
||||
"TRAC > Last GPS position (from memory)\r\n"
|
||||
"%s Latitude: %d.%07ddeg\r\n"
|
||||
|
@ -220,6 +201,14 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
lastTrackPoint->air_temp = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get last image ID. This is important because Habhub does mix up different
|
||||
* images with the same it. So it is good to use a new image ID when the
|
||||
* tracker has been reset.
|
||||
*/
|
||||
if(lastLogPoint != NULL)
|
||||
gimage_id = lastLogPoint->id_image;
|
||||
|
||||
systime_t time = chVTGetSystemTimeX();
|
||||
while(true)
|
||||
{
|
||||
|
@ -232,9 +221,9 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
// Search for GPS satellites
|
||||
gpsFix_t gpsFix = {{0,0,0,0,0,0,0},0,0,0,0,0};
|
||||
|
||||
// Switch on GPS is enough power is available
|
||||
// Switch on GPS is enough power is available and GPS is needed by any position thread
|
||||
uint16_t batt = getBatteryVoltageMV();
|
||||
if(batt >= gps_on_vbat)
|
||||
if(batt >= gps_on_vbat && tracking_useGPS)
|
||||
{
|
||||
// Switch on GPS
|
||||
GPS_Init();
|
||||
|
@ -304,8 +293,11 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
tp->gps_lon = ltp->gps_lon;
|
||||
tp->gps_alt = ltp->gps_alt;
|
||||
|
||||
// Mark GPS loss (or low batt)
|
||||
tp->gps_lock = batt < gps_off_vbat ? GPS_LOWBATT : GPS_LOSS;
|
||||
// Mark GPS loss (or low batt, GPS switch off)
|
||||
if(tracking_useGPS)
|
||||
tp->gps_lock = batt < gps_off_vbat ? GPS_LOWBATT : GPS_LOSS;
|
||||
else
|
||||
tp->gps_lock = GPS_OFF;
|
||||
tp->gps_sats = 0;
|
||||
|
||||
}
|
||||
|
@ -335,23 +327,26 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
tp->air_temp = 0;
|
||||
}
|
||||
|
||||
// Set last time ID
|
||||
tp->id_image = gimage_id;
|
||||
|
||||
// Trace data
|
||||
TRACE_INFO( "TRAC > New tracking point available (ID=%d)\r\n"
|
||||
"%s Time %04d-%02d-%02d %02d:%02d:%02d\r\n"
|
||||
"%s Pos %d.%05d %d.%05d Alt %dm\r\n"
|
||||
"%s Sats %d TTFF %dsec\r\n"
|
||||
"%s ADC Vbat=%d.%03dV Vsol=%d.%03dV VUSB=%d.%03dV Pbat=%dmW Rbat=%dmOhm\r\n"
|
||||
"%s AIR p=%6d.%01dPa T=%2d.%02ddegC phi=%2d.%01d%%",
|
||||
"%s AIR p=%6d.%01dPa T=%2d.%02ddegC phi=%2d.%01d%% ImageID=%d",
|
||||
tp->id,
|
||||
TRACE_TAB, tp->time.year, tp->time.month, tp->time.day, tp->time.hour, tp->time.minute, tp->time.day,
|
||||
TRACE_TAB, tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt,
|
||||
TRACE_TAB, tp->gps_sats, tp->gps_ttff,
|
||||
TRACE_TAB, tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->adc_vusb/1000, (tp->adc_vusb%1000), tp->adc_pbat, tp->adc_rbat,
|
||||
TRACE_TAB, tp->air_press/10, tp->air_press%10, tp->air_temp/100, tp->air_temp%100, tp->air_hum/10, tp->air_hum%10
|
||||
TRACE_TAB, tp->air_press/10, tp->air_press%10, tp->air_temp/100, tp->air_temp%100, tp->air_hum/10, tp->air_hum%10, tp->id_image
|
||||
);
|
||||
|
||||
// Append logging (timeout)
|
||||
if(nextLogEntryTimer <= chVTGetSystemTimeX() && isGPSLocked(&gpsFix))
|
||||
if(nextLogEntryTimer <= chVTGetSystemTimeX())
|
||||
{
|
||||
writeLogTrackPoint(tp);
|
||||
nextLogEntryTimer += log_cycle_time;
|
||||
|
@ -365,8 +360,11 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
}
|
||||
}
|
||||
|
||||
void init_tracking_manager(void)
|
||||
void init_tracking_manager(bool useGPS)
|
||||
{
|
||||
if(useGPS)
|
||||
tracking_useGPS = true;
|
||||
|
||||
if(!threadStarted)
|
||||
{
|
||||
threadStarted = true;
|
||||
|
|
|
@ -5,16 +5,20 @@
|
|||
#include "hal.h"
|
||||
#include "ptime.h"
|
||||
|
||||
#define GPS_LOCKED 0 /* GPS is locked and could aquire a fix */
|
||||
#define GPS_LOSS 1 /* GPS was switched on all time but it couln't aquire a fix */
|
||||
#define GPS_LOWBATT 2 /* GPS was switched on but had to be switched off prematurely while the battery is almost empty (or is too cold) */
|
||||
typedef enum {
|
||||
GPS_LOCKED, // GPS is locked and could aquire a fix
|
||||
GPS_LOSS, // GPS was switched on all time but it couln't aquire a fix
|
||||
GPS_LOWBATT, // GPS was switched on but had to be switched off prematurely while the battery is almost empty (or is too cold)
|
||||
GPS_LOG, // The tracker has been just switched on and the position has been taken from the log
|
||||
GPS_OFF, // There is no active position thread so the GPS was never switched on (in oder to save power)
|
||||
} gpsLock_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id; // Serial ID
|
||||
ptime_t time; // GPS time
|
||||
|
||||
// GPS
|
||||
uint8_t gps_lock; // 0: locked, 1: GPS loss, 2: low power (switched off)
|
||||
gpsLock_t gps_lock; // 0: locked, 1: GPS loss, 2: low power (switched off), 3: taken from log, 4: GPS switch off permanently
|
||||
int32_t gps_lat; // Latitude in °*10^7
|
||||
int32_t gps_lon; // Longitude in °*10^7
|
||||
int32_t gps_alt; // Altitude in meter
|
||||
|
@ -32,12 +36,15 @@ typedef struct {
|
|||
uint32_t air_press; // Airpressure in Pa*10 (in 0.1Pa)
|
||||
uint16_t air_hum; // Rel. humidity in %*10 (in 0.1%)
|
||||
int16_t air_temp; // Temperature in degC*100 (in 0.01°C)
|
||||
|
||||
int8_t id_image; // Last image ID (this is important because it will set the image counter at reset so the last image wont get overwritten with the same image ID)
|
||||
} trackPoint_t;
|
||||
|
||||
void waitForNewTrackPoint(void);
|
||||
trackPoint_t* getLastTrackPoint(void);
|
||||
void getNextLogTrackPoint(trackPoint_t* log);
|
||||
void init_tracking_manager(void);
|
||||
void init_tracking_manager(bool useGPS);
|
||||
trackPoint_t* getLogBuffer(uint16_t id);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue