pecanpico9/tracker/software/threads/error.c

151 wiersze
3.9 KiB
C

/**
* Error Logging module
* Packets send by this module contain tracking points and error logging.
* Transmitting tracking points is not implemented yet. Error encoding is
* already implemented and encoded as described:
*
* Error log encoding
* ========================================
* Offset Size
* 0 4 Absolute time in sec
* 4 4 Error packet 1
* 8 4 Error packet 2
* 12 4 Error packet 3
* n*4 4 Error packet n
*
* n is defined by ERRORLOG_SIZE in config.h. If less errors occured than the
* size of ERRORLOG_SIZE, the error log packet may be shorter.
*
* Error packet encoding
* ========================================
* Bit
* 16...31 Time difference to last error packet (if value == 65535, then time difference 65535sec or longer)
* 10...15 File ID (see File encoding table)
* 0...9 Line Number
*
*/
#include "ch.h"
#include "hal.h"
#include "debug.h"
#include "threads.h"
#include "base.h"
#include "aprs.h"
// File encoding table
const char* const fileIDs[] = {
"", // 0 (no error, used for time padding, if no error occured since 2^16-1 seconds)
"" // 1 (file not listed below)
"tracking.c", // 2
"position.c", // 3
"image.c", // 4
"log.c", // 5
"ssdv.c", // 6
"pi2c.c", // 7
"padc.c", // 8
"ptime.c", // 9
"max.c", // 10
"si4464.c", // 11
"bme280.c", // 12
"pac1720.c", // 13
"ov2640.c", // 14
"sd.c", // 15
"radio.c", // 16
"sleep.c", // 17
"main.c", // 18
"error.c" // 19
};
static error_t error_log[ERRORLOG_SIZE]; // Error log ring memory
static uint8_t error_id; // Incremental ID for ring memory
void log_error(char *file, uint16_t line)
{
if(error_id == ERRORLOG_SIZE)
return; // No memory left
// Find file ID
error_log[error_id].error = 1; // Assign default error file (if file not found)
for(uint8_t i=1; i<sizeof(fileIDs); i++)
if(!strcmp(fileIDs[i], file)) {
error_log[error_id].error = ((i+1) << 10);
break;
}
error_log[error_id].time = ST2S(chVTGetSystemTimeX());
error_log[error_id].error |= (line & 0x3FF);
error_id++; // Increment counter
}
static uint32_t pkt[ERRORLOG_SIZE+1];
static uint8_t pkt_base91[BASE91LEN(4*ERRORLOG_SIZE+4)];
THD_FUNCTION(moduleERROR, arg)
{
module_conf_t* config = (module_conf_t*)arg;
// Execute Initial delay
if(config->init_delay)
chThdSleepMilliseconds(config->init_delay);
// Print initialization message
TRACE_INFO("ERR > Startup module %s", config->name);
systime_t time = chVTGetSystemTimeX();
while(true)
{
TRACE_INFO("ERR > Do module LOG cycle");
config->last_update = chVTGetSystemTimeX(); // Update Watchdog timer
if(!p_sleep(&config->sleep_config))
{
// Encode message
pkt[0] = ST2S(chVTGetSystemTimeX());
for(uint8_t i=0; i<error_id; i++)
{
if(i > 0) // Calculate time difference
{
uint32_t tdiff = error_log[i].time-error_log[i-1].time; // Time difference to last error
if(tdiff >= 0xFFFF) // Time overflow
pkt[i+1] = 0xFFFF << 16;
else
pkt[i+1] = tdiff << 16;
}
pkt[i+1] |= error_log[i].error;
}
uint8_t size = error_id;
error_id = 0;
radioMSG_t msg;
msg.freq = getFrequency(&config->frequency);
msg.power = config->power;
switch(config->protocol) {
case PROT_APRS_2GFSK:
case PROT_APRS_AFSK:
msg.mod = config->protocol == PROT_APRS_AFSK ? MOD_AFSK : MOD_2GFSK;
msg.afsk_config = &(config->afsk_config);
msg.gfsk_config = &(config->gfsk_config);
// Deleting buffer
for(uint8_t t=0; t<sizeof(pkt_base91); t++)
pkt_base91[t] = 0;
base91_encode((uint8_t*)pkt, pkt_base91, 4*size+4);
msg.bin_len = aprs_encode_experimental('E', msg.msg, msg.mod, &config->aprs_config, pkt_base91, strlen((char*)pkt_base91));
transmitOnRadio(&msg);
break;
default:
TRACE_ERROR("ERR > Unsupported protocol selected for module ERR");
}
}
time = waitForTrigger(time, &config->trigger);
}
}