131 lines
3.7 KiB
C

#include <stdint.h>
#include <tim.h>
#include <counter.h>
#include <show.h>
#include <logger.h>
#include <PontCoopScheduler.h>
#include <wizHelper.h>
#include <config.h>
const uint32_t COUNTER_FREQUENCY = 1.0e6;
// 100: 2 digits behind decimal point
// 1000: 3 digits behind decimal point
const uint32_t PRECISION = 1000;
volatile static uint32_t mainsCntSum = 0;
volatile static uint32_t mainsCntCnt = 0;
static t_seconds *seconds;
typedef struct {
uint64_t timestamp;
uint32_t frequency;
} t_event;
#define SECONDS_PER_MINUTE 60
typedef struct {
char deviceId[sizeof(((t_configBlock*)0)->location)];
uint8_t done;
t_event events[SECONDS_PER_MINUTE];
} t_minuteStruct;
typedef union {
t_minuteStruct s;
uint8_t b[sizeof(t_minuteStruct)];
} t_minuteBuffer;
#define NUM_OF_MINUTE_BUFFERS 2
t_minuteBuffer minuteBuffers[NUM_OF_MINUTE_BUFFERS];
uint8_t activeMinuteBuffer = 0;
void counterMinuteTick(void *handle) {
for (uint8_t minuteBufferIdx = 0; minuteBufferIdx < NUM_OF_MINUTE_BUFFERS; minuteBufferIdx++) {
t_minuteBuffer *minuteBuffer = &(minuteBuffers[minuteBufferIdx]);
if (minuteBuffer->s.done == 1) {
coloredMsg(LOG_BLUE, "cmt, buffer %d is done, handle it", minuteBufferIdx);
for (uint8_t i = 0; i < SECONDS_PER_MINUTE; i++) {
coloredMsg(LOG_BLUE, "cmt: freq: %lu, time: %lu", minuteBuffer->s.events[i].frequency, minuteBuffer->s.events[i].timestamp);
}
minuteBuffer->s.done = 0;
}
}
}
void counterSecondTick(void *handle) {
static uint8_t bufferIdx = 0;
uint32_t tmpSum = 0;
uint32_t tmpCnt = 0;
HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
tmpSum = mainsCntSum;
mainsCntSum = 0;
tmpCnt = mainsCntCnt;
mainsCntCnt = 0;
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
uint32_t cnt = tmpSum / tmpCnt;
uint32_t freq = PRECISION * COUNTER_FREQUENCY / cnt;
coloredMsg(LOG_GREEN, "cst, Freq: %lu", freq);
coloredMsg(LOG_GREEN, "cst, Tick: %d %lu %lu", seconds->valid, seconds->missedUpdates, seconds->seconds);
if (! seconds->valid) {
coloredMsg(LOG_RED, "cst, time is not yet valid");
} else if (minuteBuffers[activeMinuteBuffer].s.done == 1) {
coloredMsg(LOG_RED, "cst, minute buffer overrun");
} else {
minuteBuffers[activeMinuteBuffer].s.events[bufferIdx].timestamp = seconds->seconds;
minuteBuffers[activeMinuteBuffer].s.events[bufferIdx].frequency = freq;
coloredMsg(LOG_GREEN, "cst, added to buffer %d, slot %d", activeMinuteBuffer, bufferIdx);
bufferIdx += 1;
if (bufferIdx == SECONDS_PER_MINUTE) {
coloredMsg(LOG_GREEN, "cst, buffer %d is done", activeMinuteBuffer);
minuteBuffers[activeMinuteBuffer].s.done = 1;
activeMinuteBuffer += 1;
bufferIdx = 0;
if (activeMinuteBuffer >= NUM_OF_MINUTE_BUFFERS) {
activeMinuteBuffer = 0;
}
}
}
}
void mainsCntsInputCaptureCallback(TIM_HandleTypeDef *htim) {
static uint8_t state = 0;
static uint32_t savedV = 0;
uint32_t v = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (state == 0) {
show(DEBUG_2, ON);
savedV = v;
state = 1;
} else if (state == 1) {
show(DEBUG_2, OFF);
uint32_t captured = (savedV < v) ? (v - savedV) : ((htim->Init.Period - savedV) + v);
mainsCntSum += captured;
mainsCntCnt += 1;
state = 0;
} else {
state = 0;
}
}
void counterInit() {
seconds = wizGetSeconds();
minuteBuffers[0].s.done = 0;
minuteBuffers[1].s.done = 0;
schAdd(counterSecondTick, NULL, 0, 1000);
schAdd(counterMinuteTick, NULL, 5, 60 * 1000);
HAL_TIM_IC_Start_IT(&mainsCnt, TIM_CHANNEL_1);
}