initial
This commit is contained in:
commit
4b3e3a3710
9
cube/User/Inc/cmdHandler.h
Normal file
9
cube/User/Inc/cmdHandler.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef _CMDHANDLER_H_
|
||||
#define _CMDHANDLER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void cmdHandlerInit();
|
||||
|
||||
|
||||
#endif /* _CMDHANDLER_H_ */
|
23
cube/User/Inc/cmdHelper.h
Normal file
23
cube/User/Inc/cmdHelper.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _CMDHELPER_H_
|
||||
#define _CMDHELPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef bool (*cmdFunc_t)(uint8_t argc, char **args);
|
||||
|
||||
typedef struct {
|
||||
char name[24];
|
||||
char help[512];
|
||||
cmdFunc_t cmdFunc;
|
||||
} cmd_t;
|
||||
|
||||
void sendString(const char *buf);
|
||||
bool sendFormatString(const char *format, ...);
|
||||
|
||||
const cmd_t *getRegularCommands();
|
||||
const cmd_t *getAdminCommands();
|
||||
const cmd_t *getConfigCommands();
|
||||
|
||||
#endif /* _CMDHELPER_H_ */
|
43
cube/User/Inc/config.h
Normal file
43
cube/User/Inc/config.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <spi.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define CONFIG_MAGIC 0xdead000a
|
||||
#define DEVICE_MAGIC 0xaffe0000
|
||||
|
||||
typedef struct __attribute__((__packed__)) s_configBlock {
|
||||
uint32_t configMagic;
|
||||
char deviceName[16];
|
||||
uint8_t macAddress[6];
|
||||
int32_t frontendThreshold;
|
||||
char brokerName[64];
|
||||
char watchdogTopic[64];
|
||||
char startupTopic[64];
|
||||
char statusTopic[64];
|
||||
char mbusDataTopic[64];
|
||||
char syslogServerName[64];
|
||||
uint8_t numOfDeviceBlocks;
|
||||
uint8_t filler[1];
|
||||
} t_configBlock;
|
||||
|
||||
|
||||
#define MAX_MBUS_DEVICES 16
|
||||
#define MBUSDEVICE_NAMELENGTH 16
|
||||
#define MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS 4
|
||||
|
||||
typedef struct __attribute__((__packed__)) s_deviceBlock {
|
||||
uint32_t deviceMagic;
|
||||
char deviceName[MBUSDEVICE_NAMELENGTH];
|
||||
uint8_t address;
|
||||
int8_t consideredField[MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS];
|
||||
int32_t period;
|
||||
uint8_t filler[3];
|
||||
} t_deviceBlock;
|
||||
|
||||
void configInit();
|
||||
t_configBlock* getConfig();
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
50
cube/User/Inc/eeprom.h
Normal file
50
cube/User/Inc/eeprom.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef EEPROM_H_
|
||||
#define EEPROM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <spi.h>
|
||||
#include <config.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
|
||||
#define EEPROM_WRITE_BLOCK_SIZE 32
|
||||
#define EEPROM_AFTER_WRITE_DELAY 7
|
||||
|
||||
|
||||
typedef struct __attribute__((__packed__)) s_eepromHeader {
|
||||
uint32_t magic;
|
||||
uint32_t writeCounter;
|
||||
} t_eepromHeader;
|
||||
static_assert((sizeof(t_eepromHeader) <= EEPROM_WRITE_BLOCK_SIZE), "t_eepromHeader has illegal size, must be less than or equal 32");
|
||||
|
||||
typedef struct __attribute__((__packed__)) s_deviceStats {
|
||||
uint32_t totalRunningHours;
|
||||
uint32_t totalPowercycles;
|
||||
uint32_t totalRequests;
|
||||
uint32_t totalFailures;
|
||||
} t_deviceStats;
|
||||
static_assert((sizeof(t_deviceStats) <= EEPROM_WRITE_BLOCK_SIZE), "t_deviceStats has illegal size, must be less than or equal 32");
|
||||
|
||||
static_assert((sizeof(t_configBlock) % 32 == 0), "t_configBlock has illegal size, must be dividable by 32");
|
||||
static_assert((sizeof(t_deviceBlock) % 32 == 0), "t_deviceBlock has illegal size, must be dividable by 32");
|
||||
|
||||
|
||||
#define EEPROM_BASE_ADDR 0
|
||||
#define EEPROM_DEVICE_STATS_ADDR 32
|
||||
#define EEPROM_CONFIG_BLOCK_ADDR 64
|
||||
#define EEPROM_DEVICE_BLOCK_BASE_ADDR (EEPROM_CONFIG_BLOCK_ADDR + sizeof(t_configBlock))
|
||||
|
||||
|
||||
|
||||
void eepromInit();
|
||||
void eepromWrite(uint16_t addr, uint8_t *buf, uint8_t len);
|
||||
void eepromRead(uint16_t addr, uint8_t *buf, uint8_t len);
|
||||
void eepromSpiTxCpltCallback(SPI_HandleTypeDef *hspi);
|
||||
t_deviceStats* getGlobalDeviceStats();
|
||||
void eepromReadConfigBlock(t_configBlock *destConfigBlock);
|
||||
void eepromWriteConfigBlock(t_configBlock *srcConfigBlock);
|
||||
void eepromReadDeviceBlock(uint8_t blockNum, t_deviceBlock *destDeviceBlock);
|
||||
void eepromWriteDeviceBlock(uint8_t blockNum, t_deviceBlock *srcDeviceBlock);
|
||||
|
||||
#endif /* EEPROM_H_ */
|
13
cube/User/Inc/frontend.h
Normal file
13
cube/User/Inc/frontend.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _FRONTEND_H_
|
||||
#define _FRONTEND_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <adc.h>
|
||||
|
||||
|
||||
void frontendInit();
|
||||
void frontendAdcCallback(ADC_HandleTypeDef* hadc);
|
||||
void frontendEnable();
|
||||
void frontendDisable();
|
||||
|
||||
#endif // _FRONTEND_H_
|
42
cube/User/Inc/logger.h
Normal file
42
cube/User/Inc/logger.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef _LOGGER_H_
|
||||
#define _LOGGER_H_
|
||||
|
||||
#include <main.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
// Disabling this option is preferred. However, when debugging system hangs
|
||||
// this option needs to be enabled.
|
||||
// #define LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
typedef enum {
|
||||
LOG_NORMAL,
|
||||
LOG_HIGH,
|
||||
LOG_RED,
|
||||
LOG_GREEN,
|
||||
LOG_BLUE,
|
||||
LOG_YELLOW
|
||||
} t_logColor;
|
||||
|
||||
// initialize the logger, creates a ringbuffer
|
||||
void logInit();
|
||||
|
||||
// de-initialize the logger, free the ringbuffer
|
||||
void logFree();
|
||||
|
||||
// log a message, make sure it is a null-terminated string
|
||||
// return value can be ignored, it is only used in test
|
||||
int logMsg(const char *format, ...);
|
||||
|
||||
int coloredMsg(const t_logColor color, bool syslogToo, const char *format, ...);
|
||||
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
void debugTxCpltCallback(UART_HandleTypeDef *huart);
|
||||
#endif
|
||||
|
||||
#ifndef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
int logExec();
|
||||
#endif
|
||||
|
||||
#endif // _LOGGER_H_
|
11
cube/User/Inc/main2.h
Normal file
11
cube/User/Inc/main2.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _MAIN2_H_
|
||||
#define _MAIN2_H_
|
||||
|
||||
|
||||
void my_setup_1();
|
||||
void my_setup_2();
|
||||
void my_loop();
|
||||
void my_errorHandler();
|
||||
void SYSTICK_Callback();
|
||||
|
||||
#endif // _MAIN2_H_
|
226
cube/User/Inc/oled-fonts.h
Normal file
226
cube/User/Inc/oled-fonts.h
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* oled-fonts.h
|
||||
*
|
||||
* Created on: May 29, 2017
|
||||
* Author: wn
|
||||
*/
|
||||
|
||||
#ifndef OLED_FONTS_H_
|
||||
#define OLED_FONTS_H_
|
||||
|
||||
|
||||
/*
|
||||
* Code found at http://www.instructables.com/id/How-to-use-OLED-display-arduino-module/
|
||||
* Thank you very much!
|
||||
* Adapted from Arduino to STM32 HAL by wollud1969
|
||||
*/
|
||||
|
||||
|
||||
|
||||
const unsigned char F6x8[][6] =
|
||||
{
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp
|
||||
{ 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // !
|
||||
{ 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
|
||||
{ 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
|
||||
{ 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
|
||||
{ 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // %
|
||||
{ 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
|
||||
{ 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // '
|
||||
{ 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
|
||||
{ 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
|
||||
{ 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // *
|
||||
{ 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +
|
||||
{ 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // ,
|
||||
{ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // -
|
||||
{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
|
||||
{ 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
|
||||
{ 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0
|
||||
{ 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1
|
||||
{ 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
|
||||
{ 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3
|
||||
{ 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4
|
||||
{ 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
|
||||
{ 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6
|
||||
{ 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
|
||||
{ 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
|
||||
{ 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9
|
||||
{ 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
|
||||
{ 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;
|
||||
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
|
||||
{ 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
|
||||
{ 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
|
||||
{ 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
|
||||
{ 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @
|
||||
{ 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A
|
||||
{ 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B
|
||||
{ 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C
|
||||
{ 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D
|
||||
{ 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E
|
||||
{ 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F
|
||||
{ 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G
|
||||
{ 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H
|
||||
{ 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I
|
||||
{ 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J
|
||||
{ 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K
|
||||
{ 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L
|
||||
{ 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M
|
||||
{ 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N
|
||||
{ 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O
|
||||
{ 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P
|
||||
{ 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q
|
||||
{ 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R
|
||||
{ 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
|
||||
{ 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T
|
||||
{ 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U
|
||||
{ 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V
|
||||
{ 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W
|
||||
{ 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
|
||||
{ 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
|
||||
{ 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
|
||||
{ 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ 91
|
||||
{ 0x00, 0x02, 0x04 ,0x08, 0x10, 0x20 }, // \92
|
||||
{ 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ]
|
||||
{ 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
|
||||
{ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
|
||||
{ 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // '
|
||||
{ 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
|
||||
{ 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b
|
||||
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
|
||||
{ 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d
|
||||
{ 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
|
||||
{ 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f
|
||||
{ 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g
|
||||
{ 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h
|
||||
{ 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i
|
||||
{ 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j
|
||||
{ 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k
|
||||
{ 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l
|
||||
{ 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m
|
||||
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n
|
||||
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
|
||||
{ 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p
|
||||
{ 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q
|
||||
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r
|
||||
{ 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
|
||||
{ 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t
|
||||
{ 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u
|
||||
{ 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v
|
||||
{ 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w
|
||||
{ 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
|
||||
{ 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y
|
||||
{ 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z
|
||||
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } // horiz lines
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const unsigned char F8X16[]=
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
|
||||
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//!1
|
||||
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"2
|
||||
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//#3
|
||||
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$4
|
||||
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//%5
|
||||
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//&6
|
||||
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//'7
|
||||
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//(8
|
||||
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//)9
|
||||
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//*10
|
||||
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+11
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//,12
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//-13
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//.14
|
||||
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,///15
|
||||
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//016
|
||||
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//117
|
||||
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//218
|
||||
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//319
|
||||
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//420
|
||||
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//521
|
||||
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//622
|
||||
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//723
|
||||
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//824
|
||||
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//925
|
||||
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//:26
|
||||
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//;27
|
||||
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//<28
|
||||
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//=29
|
||||
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//>30
|
||||
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//?31
|
||||
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@32
|
||||
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A33
|
||||
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B34
|
||||
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C35
|
||||
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D36
|
||||
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E37
|
||||
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F38
|
||||
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G39
|
||||
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H40
|
||||
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I41
|
||||
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J42
|
||||
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K43
|
||||
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L44
|
||||
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M45
|
||||
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N46
|
||||
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O47
|
||||
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P48
|
||||
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q49
|
||||
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R50
|
||||
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S51
|
||||
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T52
|
||||
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U53
|
||||
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V54
|
||||
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W55
|
||||
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X56
|
||||
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y57
|
||||
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z58
|
||||
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[59
|
||||
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\60
|
||||
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//]61
|
||||
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^62
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_63
|
||||
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//`64
|
||||
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a65
|
||||
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b66
|
||||
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c67
|
||||
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d68
|
||||
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e69
|
||||
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f70
|
||||
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g71
|
||||
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h72
|
||||
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i73
|
||||
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j74
|
||||
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k75
|
||||
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l76
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m77
|
||||
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n78
|
||||
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o79
|
||||
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p80
|
||||
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q81
|
||||
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r82
|
||||
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s83
|
||||
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t84
|
||||
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//unsigned char5
|
||||
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v86
|
||||
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w87
|
||||
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x88
|
||||
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y89
|
||||
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z90
|
||||
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{91
|
||||
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//|92
|
||||
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//}93
|
||||
0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~94
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* OLED_FONTS_H_ */
|
32
cube/User/Inc/oled.h
Normal file
32
cube/User/Inc/oled.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* oled.h
|
||||
*
|
||||
* Created on: May 29, 2017
|
||||
* Author: wn
|
||||
*/
|
||||
|
||||
#ifndef OLED_H_
|
||||
#define OLED_H_
|
||||
|
||||
|
||||
/*
|
||||
* Code found at http://www.instructables.com/id/How-to-use-OLED-display-arduino-module/
|
||||
* Thank you very much!
|
||||
* Adapted from Arduino to STM32 HAL by wollud1969
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
OLED_SCREEN0 = 0,
|
||||
OLED_SCREEN1
|
||||
} oledScreen_t;
|
||||
|
||||
void oledInit(void);
|
||||
void oledClearActiveScreen();
|
||||
void oledClearAllScreens();
|
||||
void oledPrint(oledScreen_t screen, char msg[]);
|
||||
void oledPrintf(oledScreen_t screen, const char *format, ...);
|
||||
void oledSetActiveScreen(oledScreen_t screen);
|
||||
|
||||
#endif /* OLED_H_ */
|
26
cube/User/Inc/ringbuffer.h
Normal file
26
cube/User/Inc/ringbuffer.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _RINGBUFFER_H_
|
||||
#define _RINGBUFFER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t bufferReadIdx;
|
||||
uint32_t bufferWriteIdx;
|
||||
uint32_t bufferSize;
|
||||
uint8_t* buffer;
|
||||
} ringbuffer_t;
|
||||
|
||||
void ringbufferInit(ringbuffer_t *handle, uint32_t bufferSize);
|
||||
void ringbufferFree(ringbuffer_t *handle);
|
||||
|
||||
int ringbufferPut(ringbuffer_t *handle, uint8_t *data, uint32_t dataLen);
|
||||
bool ringbufferEmpty(ringbuffer_t *handle);
|
||||
int ringbufferGetOne(ringbuffer_t *handle); // if positive, cast to uint8_t and be happy, if negative error
|
||||
|
||||
// not yet implemented
|
||||
uint8_t *ringbufferGet(ringbuffer_t *handle, uint32_t dataLen);
|
||||
|
||||
|
||||
#endif // _RINGBUFFER_H_
|
20
cube/User/Inc/show.h
Normal file
20
cube/User/Inc/show.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef _SHOW_H_
|
||||
#define _SHOW_H_
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
DEBUG_1 = 0,
|
||||
DEBUG_2 = 1,
|
||||
LED_RED = 2,
|
||||
LED_GREEN = 3
|
||||
} signalPin_t;
|
||||
|
||||
typedef enum { ON, OFF, TOGGLE, BLINK } signalAction_t;
|
||||
|
||||
void showInit();
|
||||
void show(signalPin_t signalPin, signalAction_t action);
|
||||
|
||||
|
||||
#endif // _SHOW_H_
|
8
cube/User/Inc/utils.h
Normal file
8
cube/User/Inc/utils.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void activeDelay(uint8_t delay_ms);
|
||||
|
||||
#endif // _UTILS_H_
|
13
cube/User/Inc/wizHelper.h
Normal file
13
cube/User/Inc/wizHelper.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _WIZHELPER_H_
|
||||
#define _WIZHELPER_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
int wizInit();
|
||||
bool isNetworkAvailable();
|
||||
uint8_t* wizGetIPAddress();
|
||||
bool wizDnsQuery(char *name, uint8_t *ip);
|
||||
|
||||
#endif // _WIZHELPER_H_
|
81
cube/User/Src/adminCmds.c
Normal file
81
cube/User/Src/adminCmds.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include <cmdHelper.h>
|
||||
#include <logger.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mbusComm.h>
|
||||
#include <loopCtrl.h>
|
||||
|
||||
|
||||
// clear statistics
|
||||
static bool clearCmd(uint8_t argc, char **args) {
|
||||
t_mbusCommStats zeroedStats = { .mbusRequestCnt = 0, .mbusErrorCnt = 0, .uartOctetCnt = 0, .uartOverrunCnt = 0, .uartFramingErrCnt = 0, .uartParityErrCnt = 0, .uartNoiseErrCnt = 0 };
|
||||
mbusCommSetStats(zeroedStats);
|
||||
coloredMsg(LOG_YELLOW, true, "ch cc global statistics cleared");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mbusCommEnableCmd(uint8_t argc, char **args) {
|
||||
bool retCode = true;
|
||||
if (argc == 2) {
|
||||
if (0 == strcmp("false", args[1])) {
|
||||
mbusCommEnable(false);
|
||||
coloredMsg(LOG_YELLOW, true, "ch mcec Meterbus communication disabled");
|
||||
} else if (0 == strcmp("true", args[1])) {
|
||||
mbusCommEnable(true);
|
||||
coloredMsg(LOG_YELLOW, true, "ch mcec Meterbus communication enabled");
|
||||
} else {
|
||||
retCode = false;
|
||||
}
|
||||
} else {
|
||||
retCode = false;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static bool loopEnableCmd(uint8_t argc, char **args) {
|
||||
bool retCode = true;
|
||||
if (argc == 2) {
|
||||
if (0 == strcmp("false", args[1])) {
|
||||
loopDisable();
|
||||
coloredMsg(LOG_YELLOW, true, "ch lec loop disabled");
|
||||
} else if (0 == strcmp("true", args[1])) {
|
||||
loopEnable();
|
||||
coloredMsg(LOG_YELLOW, true, "ch lec loop enabled");
|
||||
} else {
|
||||
retCode = false;
|
||||
}
|
||||
} else {
|
||||
retCode = false;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const cmd_t ADMIN_COMMANDS[] = {
|
||||
{ .name = "clear", .cmdFunc = clearCmd,
|
||||
.help = \
|
||||
"clear ................................ Clears the global Meterbus\n\r" \
|
||||
" statistics\n\r"
|
||||
},
|
||||
{ .name = "mbusCommEnable", .cmdFunc = mbusCommEnableCmd,
|
||||
.help = \
|
||||
"mbusCommEnable true|false ............ Enables or disables the Meterbus\n\r" \
|
||||
" communication\n\r"
|
||||
},
|
||||
{ .name = "loopEnable", .cmdFunc = loopEnableCmd,
|
||||
.help = \
|
||||
"loopEnable true|false ................ Enables or disables the loop.\n\r" \
|
||||
" Disable Meterbus communication\n\r" \
|
||||
" first if you want to disable the\n\r" \
|
||||
" for a longer time, otherwise the\n\r" \
|
||||
" request will enable it again\n\r"
|
||||
},
|
||||
{ .name = "END_OF_CMDS", .help = "",.cmdFunc = NULL }
|
||||
};
|
||||
|
||||
|
||||
|
||||
const cmd_t *getAdminCommands() {
|
||||
return ADMIN_COMMANDS;
|
||||
}
|
343
cube/User/Src/cmdHandler.c
Normal file
343
cube/User/Src/cmdHandler.c
Normal file
@ -0,0 +1,343 @@
|
||||
#include <cmdHandler.h>
|
||||
#include <cmdHelper.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <socket.h>
|
||||
|
||||
#include <logger.h>
|
||||
#include <PontCoopScheduler.h>
|
||||
#include <wizHelper.h>
|
||||
#include <config.h>
|
||||
|
||||
|
||||
extern const uint8_t CMD_SOCK;
|
||||
|
||||
const uint16_t cmdPort = 23;
|
||||
|
||||
typedef enum {
|
||||
CH_INIT,
|
||||
CH_LISTEN,
|
||||
CH_WAITING,
|
||||
CH_BANNER,
|
||||
CH_PROMPT,
|
||||
CH_RECEIVE,
|
||||
CH_DISCONNECT,
|
||||
CH_DISCONNECT_WAIT,
|
||||
CH_ERROR
|
||||
} chState_t;
|
||||
|
||||
void sendString(const char *buf) {
|
||||
send(CMD_SOCK, (uint8_t*)buf, strlen(buf));
|
||||
}
|
||||
|
||||
bool sendFormatString(const char *format, ...) {
|
||||
bool retCode = true;
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
char buf[4096];
|
||||
int vcnt = vsnprintf(buf, sizeof(buf), format, vl);
|
||||
retCode = (vcnt < sizeof(buf));
|
||||
va_end(vl);
|
||||
sendString(buf);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
// returns 0 to continue waiting for input
|
||||
// returns -1 to close the connection
|
||||
// returns 1 to toggle to admin mode
|
||||
// returns 2 to toggle to config mode
|
||||
// returns 3 to toggle back to default mode
|
||||
static int8_t cmdExecuteCommand(uint8_t *cmdLine, bool resetSpecialModes) {
|
||||
const static char HELP_MSG[] = \
|
||||
"Usage\n\r" \
|
||||
"\n\r" \
|
||||
"help ................................. Show this help page\n\r" \
|
||||
"quit ................................. Terminate the console session\n\r" \
|
||||
"enable ............................... Enable admin mode\n\r" \
|
||||
"config ............................... Enter configuration mode\n\r" \
|
||||
"disable .............................. Disable admin/config mode\n\r" \
|
||||
;
|
||||
const static char CONFIG_INTRO_MSG[] = \
|
||||
"In configuration mode each command changing the configuration\n\r" \
|
||||
"will save changes directly to the EEPROM.\n\r" \
|
||||
"However, the system will only consider these changes after a\n\r" \
|
||||
"restart since only in this sitution the EEPROM is read.\n\r" \
|
||||
"\n\r" \
|
||||
;
|
||||
const static char GOODBYE_MSG[] = "Good bye\n\r";
|
||||
const static char OK_MSG[] = "OK\n\r";
|
||||
const static char FAILED_MSG[] = "Failed\n\r";
|
||||
const static char UNKNOWN_COMMAND[] = "Unknown command\n\r";
|
||||
uint8_t *messageToSend = NULL;
|
||||
|
||||
static bool adminMode = false;
|
||||
static bool configMode = false;
|
||||
|
||||
if (resetSpecialModes) {
|
||||
adminMode = false;
|
||||
configMode = false;
|
||||
}
|
||||
|
||||
cmd_t const * commands = getRegularCommands();
|
||||
if (adminMode) {
|
||||
commands = getAdminCommands();
|
||||
} else if (configMode) {
|
||||
commands = getConfigCommands();
|
||||
}
|
||||
|
||||
coloredMsg(LOG_YELLOW, true, "ch cec cmdLine is %s", cmdLine);;
|
||||
|
||||
#define MAX_NUM_OF_ARGS 8
|
||||
char *args[MAX_NUM_OF_TASKS];
|
||||
uint8_t argc = 0;
|
||||
char *inCmdLine = (char*)cmdLine;
|
||||
do {
|
||||
args[argc++] = strtok(inCmdLine, " ");
|
||||
inCmdLine = NULL;
|
||||
} while (args[argc - 1] != NULL);
|
||||
if (argc > 0) {
|
||||
argc--;
|
||||
}
|
||||
char *cmd = args[0];
|
||||
|
||||
int8_t retCode = 0;
|
||||
coloredMsg(LOG_YELLOW, true, "ch cec cmd is %s, number of arguments %d", cmd, argc);
|
||||
|
||||
if (0 == strcmp(cmd, "quit")) {
|
||||
messageToSend = (uint8_t*)GOODBYE_MSG;
|
||||
retCode = -1;
|
||||
} else if (0 == strcmp(cmd, "help")) {
|
||||
if (configMode) {
|
||||
sendString(CONFIG_INTRO_MSG);
|
||||
}
|
||||
sendString(HELP_MSG);
|
||||
uint8_t cmdIdx = 0;
|
||||
while (true) {
|
||||
cmd_t command = commands[cmdIdx];
|
||||
if (0 == strcmp("END_OF_CMDS", command.name)) {
|
||||
break;
|
||||
}
|
||||
sendString(command.help);
|
||||
cmdIdx++;
|
||||
}
|
||||
messageToSend = NULL;
|
||||
} else if (0 == strcmp(cmd, "enable")) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch cec enable admin mode");
|
||||
adminMode = true;
|
||||
retCode = 1;
|
||||
} else if (0 == strcmp(cmd, "disable")) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch cec disable admin mode");
|
||||
adminMode = false;
|
||||
configMode = false;
|
||||
retCode = 3;
|
||||
} else if (0 == strcmp(cmd, "config")) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch cec enable config mode");
|
||||
configMode = true;
|
||||
retCode = 2;
|
||||
} else {
|
||||
uint8_t cmdIdx = 0;
|
||||
while (true) {
|
||||
cmd_t command = commands[cmdIdx];
|
||||
if (0 == strcmp("END_OF_CMDS", command.name)) {
|
||||
messageToSend = (uint8_t*) UNKNOWN_COMMAND;
|
||||
break;
|
||||
}
|
||||
if (0 == strcmp(cmd, command.name)) {
|
||||
messageToSend = command.cmdFunc(argc, args) ? (uint8_t*)OK_MSG : (uint8_t*)FAILED_MSG;
|
||||
break;
|
||||
}
|
||||
cmdIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (messageToSend) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch cec command finally returns %s", messageToSend);
|
||||
send(CMD_SOCK, messageToSend, strlen((char*)messageToSend));
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static void cmdHandlerEngine(void *handle) {
|
||||
static uint8_t receiveBuffer[256];
|
||||
|
||||
static chState_t state = CH_INIT;
|
||||
static bool resetSpecialModes = false;
|
||||
|
||||
static char banner[] = \
|
||||
"MBGW3\n\r" \
|
||||
"Type help for usage help\n\r" \
|
||||
"or quit to close the connection.\n\r";
|
||||
|
||||
static char *prompt;
|
||||
static char defaultPrompt[] = " > ";
|
||||
static char adminPrompt[] = " (admin) # ";
|
||||
static char configPrompt[] = " (config) $ ";
|
||||
|
||||
|
||||
int8_t res = 0;
|
||||
uint8_t sockState;
|
||||
int32_t resultSend;
|
||||
int16_t receivedOctets;
|
||||
int32_t resultRecv;
|
||||
uint8_t resultDisconnect;
|
||||
|
||||
|
||||
if (isNetworkAvailable()) {
|
||||
switch (state) {
|
||||
case CH_INIT:
|
||||
coloredMsg(LOG_YELLOW, false, "ch che initializing socket");
|
||||
|
||||
res = socket(CMD_SOCK, Sn_MR_TCP, cmdPort, SF_IO_NONBLOCK);
|
||||
coloredMsg(LOG_YELLOW, false, "ch che socket returns %d", res);
|
||||
|
||||
if (res == CMD_SOCK) {
|
||||
coloredMsg(LOG_YELLOW, false, "ch che socket is initialized");
|
||||
state = CH_LISTEN;
|
||||
} else {
|
||||
state = CH_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case CH_LISTEN:
|
||||
coloredMsg(LOG_YELLOW, false, "ch che listening");
|
||||
|
||||
res = listen(CMD_SOCK);
|
||||
coloredMsg(LOG_YELLOW, false, "ch che listen returns %d", res);
|
||||
|
||||
if (res == SOCK_OK) {
|
||||
coloredMsg(LOG_YELLOW, false, "ch che ok, waiting for established");
|
||||
state = CH_WAITING;
|
||||
} else {
|
||||
state = CH_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case CH_WAITING:
|
||||
sockState = getSn_SR(CMD_SOCK);
|
||||
if (sockState != SOCK_LISTEN) {
|
||||
coloredMsg(LOG_YELLOW, false, "ch che socket state is 0x%02x", sockState);
|
||||
state = CH_DISCONNECT;
|
||||
}
|
||||
|
||||
if (sockState == SOCK_ESTABLISHED) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch che connection is established");
|
||||
state = CH_BANNER;
|
||||
}
|
||||
break;
|
||||
|
||||
case CH_BANNER:
|
||||
coloredMsg(LOG_YELLOW, false, "ch che send banner");
|
||||
sockState = getSn_SR(CMD_SOCK);
|
||||
if (sockState != SOCK_ESTABLISHED) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch che sockState is 0x%02x when trying to send banner", sockState);
|
||||
state = CH_DISCONNECT;
|
||||
} else {
|
||||
resultSend = send(CMD_SOCK, (uint8_t*)banner, strlen(banner));
|
||||
coloredMsg(LOG_YELLOW, false, "ch che sent banner, send returns 0x%02x", resultSend);
|
||||
prompt = defaultPrompt;
|
||||
resetSpecialModes = true;
|
||||
state = CH_PROMPT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CH_PROMPT:
|
||||
coloredMsg(LOG_YELLOW, false, "ch che send prompt");
|
||||
sockState = getSn_SR(CMD_SOCK);
|
||||
if (sockState != SOCK_ESTABLISHED) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch che sockState is 0x%02x when trying to send promt", sockState);
|
||||
state = CH_DISCONNECT;
|
||||
} else {
|
||||
sendFormatString("%s %s", getConfig()->deviceName, prompt);
|
||||
coloredMsg(LOG_YELLOW, false, "ch che sent prompt %s %s", getConfig()->deviceName, prompt);
|
||||
state = CH_RECEIVE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CH_RECEIVE:
|
||||
sockState = getSn_SR(CMD_SOCK);
|
||||
if (sockState != SOCK_ESTABLISHED) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch che sockState is 0x%02x when trying to receive something", sockState);
|
||||
state = CH_DISCONNECT;
|
||||
} else {
|
||||
receivedOctets = getSn_RX_RSR(CMD_SOCK);
|
||||
|
||||
if (receivedOctets > 0) {
|
||||
memset(receiveBuffer, 0, sizeof(receiveBuffer));
|
||||
resultRecv = recv(CMD_SOCK, receiveBuffer, sizeof(receiveBuffer));
|
||||
coloredMsg(LOG_YELLOW, false, "ch che recv returns 0x%02x", resultRecv);
|
||||
if (resultRecv > 0) {
|
||||
if ((receiveBuffer[strlen((char*)receiveBuffer) - 1] == 0x0a) ||
|
||||
(receiveBuffer[strlen((char*)receiveBuffer) - 1] == 0x0d)) {
|
||||
receiveBuffer[strlen((char*)receiveBuffer) - 1] = 0;
|
||||
}
|
||||
if ((receiveBuffer[strlen((char*)receiveBuffer) - 1] == 0x0a) ||
|
||||
(receiveBuffer[strlen((char*)receiveBuffer) - 1] == 0x0d)) {
|
||||
receiveBuffer[strlen((char*)receiveBuffer) - 1] = 0;
|
||||
}
|
||||
coloredMsg(LOG_YELLOW, false, "ch che received: %s", receiveBuffer);
|
||||
int8_t resCEC = cmdExecuteCommand(receiveBuffer, resetSpecialModes);
|
||||
resetSpecialModes = false;
|
||||
switch (resCEC) {
|
||||
case 0:
|
||||
state = CH_PROMPT;
|
||||
break;
|
||||
case -1:
|
||||
state = CH_DISCONNECT;
|
||||
break;
|
||||
case 1:
|
||||
prompt = adminPrompt;
|
||||
state = CH_PROMPT;
|
||||
break;
|
||||
case 2:
|
||||
prompt = configPrompt;
|
||||
state = CH_PROMPT;
|
||||
break;
|
||||
case 3:
|
||||
prompt = defaultPrompt;
|
||||
state = CH_PROMPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CH_DISCONNECT:
|
||||
coloredMsg(LOG_YELLOW, true, "ch che close our end");
|
||||
resultDisconnect = disconnect(CMD_SOCK);
|
||||
coloredMsg(LOG_YELLOW, true, "ch che disconnect returns 0x%02x", resultDisconnect);
|
||||
state = CH_DISCONNECT_WAIT;
|
||||
break;
|
||||
|
||||
case CH_DISCONNECT_WAIT:
|
||||
//coloredMsg(LOG_YELLOW, false, "ch che waiting after disconnect");
|
||||
sockState = getSn_SR(CMD_SOCK);
|
||||
//coloredMsg(LOG_YELLOW, false, "ch che sockState is 0x%02x", sockState);
|
||||
if (sockState == SOCK_CLOSED) {
|
||||
coloredMsg(LOG_YELLOW, true, "ch che socket is closed now");
|
||||
state = CH_INIT;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case CH_ERROR:
|
||||
coloredMsg(LOG_YELLOW, true, "ch che error state, will stop here");
|
||||
schDel(cmdHandlerEngine, NULL);
|
||||
state = CH_INIT;
|
||||
schAdd(cmdHandlerEngine, NULL, 5000, 100);
|
||||
coloredMsg(LOG_YELLOW, true, "ch che restart command handler engine in 5s");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmdHandlerInit() {
|
||||
schAdd(cmdHandlerEngine, NULL, 0, 100);
|
||||
}
|
164
cube/User/Src/config.c
Normal file
164
cube/User/Src/config.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <config.h>
|
||||
#include <eeprom.h>
|
||||
#include <logger.h>
|
||||
#include <mbusComm.h>
|
||||
|
||||
|
||||
|
||||
#define NUM_OF_DEFAULT_DEVICES 8
|
||||
t_deviceBlock defaultDeviceBlock[] = {
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Total",
|
||||
.address = 80,
|
||||
.consideredField = { 0, 17, -1, -1 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Computer",
|
||||
.address = 85,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Dryer",
|
||||
.address = 81,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Laundry",
|
||||
.address = 82,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Dishwasher",
|
||||
.address = 83,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Light",
|
||||
.address = 84,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Freezer",
|
||||
.address = 86,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
.deviceMagic = DEVICE_MAGIC,
|
||||
.deviceName = "Fridge",
|
||||
.address = 87,
|
||||
.consideredField = { 0, 4, 2, 3 },
|
||||
.period = 10,
|
||||
.filler = { 0, 0, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
t_configBlock defaultConfigBlock = {
|
||||
.configMagic = CONFIG_MAGIC,
|
||||
.deviceName = "MBGW3",
|
||||
.macAddress = { 0x00, 0xA0, 0x57, 0x05, 0x3E, 0x0D },
|
||||
.frontendThreshold = 240,
|
||||
.brokerName = "mqttbroker",
|
||||
.watchdogTopic = "IoT/Watchdog",
|
||||
.startupTopic = "IoT/MBGW3/Startup",
|
||||
.statusTopic = "IoT/MBGW3/Status",
|
||||
.mbusDataTopic = "IoT/MBGW3/Measurement",
|
||||
.syslogServerName = "syslogserver",
|
||||
.numOfDeviceBlocks = NUM_OF_DEFAULT_DEVICES,
|
||||
.filler = { 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
t_configBlock mainConfigBlock;
|
||||
|
||||
|
||||
|
||||
t_configBlock* getConfig() {
|
||||
return &mainConfigBlock;
|
||||
}
|
||||
|
||||
|
||||
void configInit() {
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci Reading configuration block from eeprom");
|
||||
eepromReadConfigBlock(&mainConfigBlock);
|
||||
|
||||
if (mainConfigBlock.configMagic != CONFIG_MAGIC) {
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci Invalid configuration block read from eeprom");
|
||||
|
||||
eepromWriteConfigBlock(&defaultConfigBlock);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci Default configuration block written to eeprom");
|
||||
|
||||
for (uint8_t i = 0; i < NUM_OF_DEFAULT_DEVICES; i++) {
|
||||
eepromWriteDeviceBlock(i, &defaultDeviceBlock[i]);
|
||||
}
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci Default device blocks written to eeprom");
|
||||
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci Reading configuration block from eeprom again");
|
||||
eepromReadConfigBlock(&mainConfigBlock);
|
||||
}
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci configMagic: %lx", mainConfigBlock.configMagic);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci deviceName: %s", mainConfigBlock.deviceName);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci MAC address: %02x:%02x:%02x:%02x:%02x:%02x", mainConfigBlock.macAddress[0],
|
||||
mainConfigBlock.macAddress[1],
|
||||
mainConfigBlock.macAddress[2],
|
||||
mainConfigBlock.macAddress[3],
|
||||
mainConfigBlock.macAddress[4],
|
||||
mainConfigBlock.macAddress[5]);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci frontend threshold: %ld", mainConfigBlock.frontendThreshold);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci broker: %s", mainConfigBlock.brokerName);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci watchdogTopic: %s", mainConfigBlock.watchdogTopic);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci startupTopic: %s", mainConfigBlock.startupTopic);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci statusTopic: %s", mainConfigBlock.statusTopic);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci mbusDataTopic: %s", mainConfigBlock.mbusDataTopic);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci syslog server: %s", mainConfigBlock.syslogServerName);
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci device block cnt: %d", mainConfigBlock.numOfDeviceBlocks);
|
||||
|
||||
for (uint8_t i = 0; i < mainConfigBlock.numOfDeviceBlocks; i++) {
|
||||
t_deviceBlock tmpDeviceBlock;
|
||||
eepromReadDeviceBlock(i, &tmpDeviceBlock);
|
||||
if (tmpDeviceBlock.deviceMagic == DEVICE_MAGIC) {
|
||||
coloredMsg(LOG_BLUE, false, "cfg ci device %d: ", i);
|
||||
coloredMsg(LOG_BLUE, false, " Name: %s, Address: %d, Period: %d",
|
||||
tmpDeviceBlock.deviceName, tmpDeviceBlock.address, tmpDeviceBlock.period);
|
||||
coloredMsg(LOG_BLUE, false, " Considered Fields: %d %d %d %d",
|
||||
tmpDeviceBlock.consideredField[0],
|
||||
tmpDeviceBlock.consideredField[1],
|
||||
tmpDeviceBlock.consideredField[2],
|
||||
tmpDeviceBlock.consideredField[3]);
|
||||
if (tmpDeviceBlock.period == 0) {
|
||||
coloredMsg(LOG_BLUE, false, " device is marked as inactive");
|
||||
} else if (tmpDeviceBlock.period == -1) {
|
||||
coloredMsg(LOG_BLUE, false, " device is marked as deleted");
|
||||
} else {
|
||||
mbusCommAddDevice(&tmpDeviceBlock);
|
||||
}
|
||||
} else {
|
||||
coloredMsg(LOG_BLUE, false, "magic of device %d does not match, ignored", i);
|
||||
}
|
||||
}
|
||||
}
|
447
cube/User/Src/configCmds.c
Normal file
447
cube/User/Src/configCmds.c
Normal file
@ -0,0 +1,447 @@
|
||||
#include <cmdHelper.h>
|
||||
#include <logger.h>
|
||||
|
||||
#include <eeprom.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
static bool showConfigCmd(uint8_t argc, char **args) {
|
||||
bool retCode = true;
|
||||
|
||||
t_configBlock configBlock;
|
||||
eepromReadConfigBlock(&configBlock);
|
||||
sendString("This is the saved configuration.\n\r");
|
||||
sendString("It is not necessarily the active configuration.\n\r");
|
||||
sendFormatString("configMagic: %lx\n\r", configBlock.configMagic);
|
||||
sendFormatString("deviceName: %s\n\r", configBlock.deviceName);
|
||||
sendFormatString("MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n\r", configBlock.macAddress[0],
|
||||
configBlock.macAddress[1],
|
||||
configBlock.macAddress[2],
|
||||
configBlock.macAddress[3],
|
||||
configBlock.macAddress[4],
|
||||
configBlock.macAddress[5]);
|
||||
sendFormatString("frontend threshold: %ld\n\r", configBlock.frontendThreshold);
|
||||
sendFormatString("broker: %s\n\r", configBlock.brokerName);
|
||||
sendFormatString("watchdogTopic: %s\n\r", configBlock.watchdogTopic);
|
||||
sendFormatString("startupTopic: %s\n\r", configBlock.startupTopic);
|
||||
sendFormatString("statusTopic: %s\n\r", configBlock.statusTopic);
|
||||
sendFormatString("mbusDataTopic: %s\n\r", configBlock.mbusDataTopic);
|
||||
sendFormatString("syslog server: %s\n\r", configBlock.syslogServerName);
|
||||
sendFormatString("device block cnt: %d\n\r", configBlock.numOfDeviceBlocks);
|
||||
|
||||
for (uint8_t i = 0; i < configBlock.numOfDeviceBlocks; i++) {
|
||||
t_deviceBlock tmpDeviceBlock;
|
||||
eepromReadDeviceBlock(i, &tmpDeviceBlock);
|
||||
if (tmpDeviceBlock.deviceMagic == DEVICE_MAGIC) {
|
||||
sendFormatString("device %d: \n\r", i);
|
||||
sendFormatString(" Name: %s, Address: %d, Period: %d\n\r",
|
||||
tmpDeviceBlock.deviceName, tmpDeviceBlock.address, tmpDeviceBlock.period);
|
||||
sendFormatString(" Considered Fields: %d %d %d %d\n\r",
|
||||
tmpDeviceBlock.consideredField[0],
|
||||
tmpDeviceBlock.consideredField[1],
|
||||
tmpDeviceBlock.consideredField[2],
|
||||
tmpDeviceBlock.consideredField[3]);
|
||||
if (tmpDeviceBlock.deviceMagic != DEVICE_MAGIC) {
|
||||
sendString(" DEVICE MAGIC DOES NOT MATCH\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static bool setStringParameterCmd(uint8_t argc, char **args, size_t offset, size_t length) {
|
||||
bool retCode = true;
|
||||
|
||||
t_configBlock configBlock;
|
||||
char *parameterName = args[1];
|
||||
char *newParameterValue = args[2];
|
||||
if (strlen(newParameterValue) >= length) {
|
||||
sendString("given new value for is too long\n\r");
|
||||
retCode = false;
|
||||
} else {
|
||||
sendFormatString("set %s to %s\n\r", parameterName, newParameterValue);
|
||||
|
||||
eepromReadConfigBlock(&configBlock);
|
||||
strcpy((((char*)&configBlock) + offset), newParameterValue);
|
||||
eepromWriteConfigBlock(&configBlock);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static bool setInt32ParameterCmd(uint8_t argc, char **args, size_t offset, int32_t minV, int32_t maxV) {
|
||||
bool retCode = true;
|
||||
|
||||
t_configBlock configBlock;
|
||||
char *parameterName = args[1];
|
||||
char *newParameterValue = args[2];
|
||||
long int value = strtol(newParameterValue, NULL, 10);
|
||||
if (value < minV) {
|
||||
sendString("value is too small\n\r");
|
||||
retCode = false;
|
||||
} else if (value > maxV) {
|
||||
sendString("value is too large\n\r");
|
||||
} else {
|
||||
int32_t v = (int32_t) value;
|
||||
sendFormatString("set %s to %ld\n\r", parameterName, v);
|
||||
|
||||
eepromReadConfigBlock(&configBlock);
|
||||
*((int32_t*)(((uint8_t*)&configBlock) + offset)) = v;
|
||||
eepromWriteConfigBlock(&configBlock);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
static bool setDeviceNameCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, deviceName),
|
||||
sizeof(((t_configBlock*)0)->deviceName));
|
||||
}
|
||||
|
||||
static bool setBrokerNameCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, brokerName),
|
||||
sizeof(((t_configBlock*)0)->brokerName));
|
||||
}
|
||||
|
||||
static bool setSyslogServerCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, syslogServerName),
|
||||
sizeof(((t_configBlock*)0)->syslogServerName));
|
||||
}
|
||||
|
||||
static bool setWatchdogTopicCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, watchdogTopic),
|
||||
sizeof(((t_configBlock*)0)->watchdogTopic));
|
||||
}
|
||||
|
||||
static bool setStartupTopicCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, startupTopic),
|
||||
sizeof(((t_configBlock*)0)->startupTopic));
|
||||
}
|
||||
|
||||
static bool setStatusTopicCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, statusTopic),
|
||||
sizeof(((t_configBlock*)0)->statusTopic));
|
||||
}
|
||||
|
||||
static bool setMbusDataTopicCmd(uint8_t argc, char **args) {
|
||||
return setStringParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, mbusDataTopic),
|
||||
sizeof(((t_configBlock*)0)->mbusDataTopic));
|
||||
}
|
||||
|
||||
static bool setFrontendThresholdCmd(uint8_t argc, char **args) {
|
||||
return setInt32ParameterCmd(argc, args,
|
||||
offsetof(t_configBlock, frontendThreshold),
|
||||
0, 1023);
|
||||
}
|
||||
|
||||
static bool makeDevice(uint8_t argOffset, uint8_t argc, char **args, t_deviceBlock *deviceBlock) {
|
||||
if (strcmp(args[1], "help") == 0) {
|
||||
sendString("deviceName address period field1 field2 field3 field4\n\r");
|
||||
sendString("deviceName: max. length = 16\n\r");
|
||||
sendString("address: between 1 and 254\n\r");
|
||||
sendString("period: in seconds, between 0 (disabled) and 86400 (1 day)\n\r");
|
||||
sendString("fields: between -1 (not considered) and 254\n\r");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ((argc - argOffset) != 8) {
|
||||
sendString("wrong number of arguments\n\r");
|
||||
return false;
|
||||
}
|
||||
|
||||
char *deviceName = args[1 + argOffset];
|
||||
if (strcmp(deviceName, "*") != 0) {
|
||||
if (strlen(deviceName) >= sizeof(deviceBlock->deviceName)) {
|
||||
sendString("devicename too long\n\r");
|
||||
return false;
|
||||
}
|
||||
strcpy(deviceBlock->deviceName, deviceName);
|
||||
}
|
||||
|
||||
char *rawAddressStr = args[2 + argOffset];
|
||||
if (strcmp(rawAddressStr, "*") != 0) {
|
||||
long int rawAddress = strtol(rawAddressStr, NULL, 10);
|
||||
if (rawAddress < 1 || rawAddress > 254) {
|
||||
sendString("illegal address\n\r");
|
||||
return false;
|
||||
}
|
||||
deviceBlock->address = (uint8_t)rawAddress;
|
||||
}
|
||||
|
||||
char *rawPeriodStr = args[3 + argOffset];
|
||||
if (strcmp(rawPeriodStr, "*") != 0) {
|
||||
long int rawPeriod = strtol(rawPeriodStr, NULL, 10);
|
||||
if (rawPeriod < 0 || rawPeriod > 86400) {
|
||||
sendString("illegal period\n\r");
|
||||
return false;
|
||||
}
|
||||
deviceBlock->period = (int32_t) rawPeriod;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) {
|
||||
char *rawFieldNumStr = args[4 + i + argOffset];
|
||||
if (strcmp(rawFieldNumStr, "*") != 0) {
|
||||
long int rawFieldNum = strtol(rawFieldNumStr, NULL, 10);
|
||||
if (rawFieldNum < -1 || rawFieldNum > 127) {
|
||||
sendString("illegal considered field index\n\r");
|
||||
return false;
|
||||
}
|
||||
deviceBlock->consideredField[i] = (int8_t) rawFieldNum;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool addDeviceCmd(uint8_t argc, char **args) {
|
||||
t_deviceBlock deviceBlock = { .deviceName = "", .address = 0, .period = 0, .consideredField = { -1, -1, -1, -1}};
|
||||
bool retCode = makeDevice(0, argc, args, &deviceBlock);
|
||||
if (retCode) {
|
||||
sendString("New device would be:\n\r");
|
||||
sendFormatString(" Name: %s, Address: %d, Period: %d\n\r",
|
||||
deviceBlock.deviceName, deviceBlock.address, deviceBlock.period);
|
||||
for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) {
|
||||
sendFormatString(" Considered field: %d\n\r", deviceBlock.consideredField[i]);
|
||||
}
|
||||
}
|
||||
deviceBlock.deviceMagic = DEVICE_MAGIC;
|
||||
|
||||
uint8_t index = getConfig()->numOfDeviceBlocks;
|
||||
for (uint8_t i = 0; i < getConfig()->numOfDeviceBlocks; i++) {
|
||||
t_deviceBlock tmpDeviceBlock;
|
||||
eepromReadDeviceBlock(i, &tmpDeviceBlock);
|
||||
if (tmpDeviceBlock.period == -1) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
eepromWriteDeviceBlock(index, &deviceBlock);
|
||||
if (index == getConfig()->numOfDeviceBlocks) {
|
||||
t_configBlock configBlock;
|
||||
eepromReadConfigBlock(&configBlock);
|
||||
configBlock.numOfDeviceBlocks += 1;
|
||||
eepromWriteConfigBlock(&configBlock);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static bool deleteDeviceCmd(uint8_t argc, char **args) {
|
||||
long int rawIndex = strtol(args[1], NULL, 10);
|
||||
if (rawIndex < 0 || rawIndex > getConfig()->numOfDeviceBlocks) {
|
||||
sendFormatString("illegal index, must be greater 0 and less %d\n\r", getConfig()->numOfDeviceBlocks);
|
||||
return false;
|
||||
}
|
||||
uint8_t index = (uint8_t) rawIndex;
|
||||
|
||||
t_deviceBlock deviceBlock;
|
||||
eepromReadDeviceBlock(index, &deviceBlock);
|
||||
deviceBlock.period = -1;
|
||||
eepromWriteDeviceBlock(index, &deviceBlock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool changeDeviceCmd(uint8_t argc, char **args) {
|
||||
if (strcmp(args[1], "help") == 0) {
|
||||
sendString("First argument: index of device in list\n\r");
|
||||
sendFormatString("Between 0 and %d\n\r", getConfig()->numOfDeviceBlocks);
|
||||
sendString("For further arguments use a * to keep the value\n\r");
|
||||
return makeDevice(0, argc, args, NULL);
|
||||
}
|
||||
|
||||
long int rawIndex = strtol(args[1], NULL, 10);
|
||||
if (rawIndex < 0 || rawIndex > getConfig()->numOfDeviceBlocks) {
|
||||
sendFormatString("illegal index, must be greater 0 and less %d\n\r", getConfig()->numOfDeviceBlocks);
|
||||
return false;
|
||||
}
|
||||
uint8_t index = (uint8_t) rawIndex;
|
||||
|
||||
t_deviceBlock deviceBlock;
|
||||
eepromReadDeviceBlock(index, &deviceBlock);
|
||||
|
||||
bool retCode = makeDevice(1, argc, args, &deviceBlock);
|
||||
if (retCode) {
|
||||
sendString("Changed device will be:\n\r");
|
||||
sendFormatString(" Index: %d\n\r", index);
|
||||
sendFormatString(" Name: %s, Address: %d, Period: %d\n\r",
|
||||
deviceBlock.deviceName, deviceBlock.address, deviceBlock.period);
|
||||
for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) {
|
||||
sendFormatString(" Considered field: %d\n\r", deviceBlock.consideredField[i]);
|
||||
}
|
||||
if (deviceBlock.period == 0) {
|
||||
sendString(" Device is marked as inactive\n\r");
|
||||
}
|
||||
eepromWriteDeviceBlock(index, &deviceBlock);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static bool listDevicesCmd(uint8_t argc, char **args) {
|
||||
for (uint8_t i = 0; i < getConfig()->numOfDeviceBlocks; i++) {
|
||||
t_deviceBlock deviceBlock;
|
||||
eepromReadDeviceBlock(i, &deviceBlock);
|
||||
sendFormatString("Index: %d\n\r", i);
|
||||
sendFormatString(" Name: %s, Address: %d, Period: %d\n\r",
|
||||
deviceBlock.deviceName, deviceBlock.address, deviceBlock.period);
|
||||
for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) {
|
||||
sendFormatString(" Considered field: %d\n\r", deviceBlock.consideredField[i]);
|
||||
}
|
||||
if (deviceBlock.period == 0) {
|
||||
sendString(" Device is marked as inactive\n\r");
|
||||
} else if (deviceBlock.period == -1) {
|
||||
sendString(" Device is marked as deleted\n\r");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const static cmd_t SET_COMMANDS[] = {
|
||||
{ .name = "devicename", .cmdFunc = setDeviceNameCmd,
|
||||
.help = \
|
||||
"devicename ........................... Name of this device\n\r"
|
||||
},
|
||||
{ .name = "brokername", .cmdFunc = setBrokerNameCmd,
|
||||
.help = \
|
||||
"brokername ........................... Hostname of the MQTT broker\n\r"
|
||||
},
|
||||
{ .name = "syslogserver", .cmdFunc = setSyslogServerCmd,
|
||||
.help = \
|
||||
"syslogserver ......................... Hostname of the Syslog server\n\r"
|
||||
},
|
||||
{ .name = "watchdogtopic", .cmdFunc = setWatchdogTopicCmd,
|
||||
.help = \
|
||||
"watchdogtopic ........................ Watchdog Topic\n\r"
|
||||
},
|
||||
{ .name = "startuptopic", .cmdFunc = setStartupTopicCmd,
|
||||
.help = \
|
||||
"startuptopic ......................... Startup Topic\n\r"
|
||||
},
|
||||
{ .name = "statustopic", .cmdFunc = setStatusTopicCmd,
|
||||
.help = \
|
||||
"statustopic .......................... Status Topic\n\r"
|
||||
},
|
||||
{ .name = "mbusdatatopic", .cmdFunc = setMbusDataTopicCmd,
|
||||
.help = \
|
||||
"mbusdatatopic ........................ MBus Data Topic\n\r"
|
||||
},
|
||||
{ .name = "frontendthreshold", .cmdFunc = setFrontendThresholdCmd,
|
||||
.help = \
|
||||
"frontendthreshold .................... Frontend Threshold (default: 240)\n\r"
|
||||
},
|
||||
{ .name = "END_OF_CMDS", .help = "",.cmdFunc = NULL }
|
||||
};
|
||||
|
||||
const static char UNKNOWN_PARAMETER[] = "unknown parameter\n\r";
|
||||
const static char OK_MSG[] = "OK\n\r";
|
||||
const static char FAILED_MSG[] = "Failed\n\r";
|
||||
|
||||
static bool setCmd(uint8_t argc, char **args) {
|
||||
bool retCode = false;
|
||||
uint8_t *messageToSend = NULL;
|
||||
|
||||
char *cmd = args[1];
|
||||
if (argc >= 2) {
|
||||
if (0 == strcmp("help", cmd)) {
|
||||
sendString("You can set the following parameters:\n\r");
|
||||
uint8_t cmdIdx = 0;
|
||||
while (true) {
|
||||
cmd_t command = SET_COMMANDS[cmdIdx];
|
||||
if (0 == strcmp("END_OF_CMDS", command.name)) {
|
||||
break;
|
||||
}
|
||||
sendString(command.help);
|
||||
cmdIdx++;
|
||||
}
|
||||
retCode = true;
|
||||
} else {
|
||||
uint8_t cmdIdx = 0;
|
||||
while (true) {
|
||||
cmd_t command = SET_COMMANDS[cmdIdx];
|
||||
if (0 == strcmp("END_OF_CMDS", command.name)) {
|
||||
messageToSend = (uint8_t*) UNKNOWN_PARAMETER;
|
||||
break;
|
||||
}
|
||||
if (0 == strcmp(cmd, command.name)) {
|
||||
retCode = command.cmdFunc(argc, args);
|
||||
messageToSend = retCode ? (uint8_t*)OK_MSG : (uint8_t*)FAILED_MSG;
|
||||
sendString("Remember you need to restart to active this change.\n\r");
|
||||
break;
|
||||
}
|
||||
cmdIdx++;
|
||||
}
|
||||
sendString((const char*)messageToSend);
|
||||
}
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static bool restartCmd(uint8_t argc, char **args) {
|
||||
HAL_NVIC_SystemReset();
|
||||
// you won't come here ...
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const cmd_t CONFIG_COMMANDS[] = {
|
||||
{ .name = "show", .cmdFunc = showConfigCmd,
|
||||
.help = \
|
||||
"show ................................. Show the configuration\n\r"
|
||||
},
|
||||
{ .name = "set", .cmdFunc = setCmd,
|
||||
.help = \
|
||||
"set .................................. Set configuration parameters\n\r" \
|
||||
" Argument help gives a list of \n\r" \
|
||||
" parameters\n\r"
|
||||
},
|
||||
{ .name = "addDevice", .cmdFunc = addDeviceCmd,
|
||||
.help = \
|
||||
"addDevice ............................ Add a new device to the end of the list\n\r"
|
||||
},
|
||||
{ .name = "changeDevice", .cmdFunc = changeDeviceCmd,
|
||||
.help = \
|
||||
"changeDevice ......................... Change a new device by index\n\r"
|
||||
},
|
||||
{ .name = "listDevices", .cmdFunc = listDevicesCmd,
|
||||
.help = \
|
||||
"listDevices .......................... List the configured devices\n\r"
|
||||
},
|
||||
{ .name = "deleteDevice", .cmdFunc = deleteDeviceCmd,
|
||||
.help = \
|
||||
"deleteDevice ......................... Delete a device\n\r" \
|
||||
" Argument: index\n\r"
|
||||
},
|
||||
{ .name = "restart", .cmdFunc = restartCmd,
|
||||
.help = \
|
||||
"restart .............................. Restart the system,\n\r" \
|
||||
" Required to reload config\n\r"
|
||||
},
|
||||
{ .name = "END_OF_CMDS", .help = "",.cmdFunc = NULL }
|
||||
};
|
||||
|
||||
|
||||
|
||||
const cmd_t *getConfigCommands() {
|
||||
return CONFIG_COMMANDS;
|
||||
}
|
218
cube/User/Src/eeprom.c
Normal file
218
cube/User/Src/eeprom.c
Normal file
@ -0,0 +1,218 @@
|
||||
#include <main.h>
|
||||
#include <spi.h>
|
||||
#include <eeprom.h>
|
||||
#include <string.h>
|
||||
#include <logger.h>
|
||||
#include <mbusComm.h>
|
||||
#include <PontCoopScheduler.h>
|
||||
#include <utils.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define HIGH GPIO_PIN_SET
|
||||
#define LOW GPIO_PIN_RESET
|
||||
|
||||
|
||||
|
||||
static const uint8_t EEPROM_READ = 0x03;
|
||||
static const uint8_t EEPROM_WRITE = 0x02;
|
||||
// static const uint8_t EEPROM_WRDI = 0x04;
|
||||
static const uint8_t EEPROM_WREN = 0x06;
|
||||
// static const uint8_t EEPROM_RDSR = 0x05;
|
||||
// static const uint8_t EEPROM_WRSR = 0x01;
|
||||
|
||||
|
||||
static const uint32_t EEPROM_MAGIC = 0xaffe0009;
|
||||
|
||||
|
||||
static const uint16_t EEPROM_HEADER_ADDR = EEPROM_BASE_ADDR;
|
||||
|
||||
|
||||
typedef union {
|
||||
t_eepromHeader s;
|
||||
uint8_t b[sizeof(struct s_eepromHeader)];
|
||||
} t_eepromHeaderBlock;
|
||||
|
||||
static t_eepromHeaderBlock eepromHeader;
|
||||
|
||||
|
||||
typedef union {
|
||||
t_deviceStats s;
|
||||
uint8_t b[sizeof(t_deviceStats)];
|
||||
} t_deviceStatsBlock;
|
||||
|
||||
static const uint16_t DEVICE_STATS_ADDR = EEPROM_DEVICE_STATS_ADDR;
|
||||
static t_deviceStatsBlock deviceStats;
|
||||
|
||||
static const uint16_t CONFIG_BLOCK_ADDR = EEPROM_CONFIG_BLOCK_ADDR;
|
||||
static const uint16_t DEVICE_BLOCK_ADDR = EEPROM_DEVICE_BLOCK_BASE_ADDR;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef union {
|
||||
struct __attribute__((__packed__)) s_spiMsg {
|
||||
uint8_t cmd;
|
||||
uint16_t addr;
|
||||
uint8_t data[32];
|
||||
} s;
|
||||
uint8_t b[sizeof(struct s_spiMsg)];
|
||||
} t_spiMsg;
|
||||
|
||||
t_deviceStats* getGlobalDeviceStats() {
|
||||
return &(deviceStats.s);
|
||||
}
|
||||
|
||||
inline static void __EEPROM_CS(GPIO_PinState v) {
|
||||
HAL_GPIO_WritePin(EEPROM_CS_GPIO_Port, EEPROM_CS_Pin, v);
|
||||
}
|
||||
|
||||
static uint16_t swap(uint16_t i) {
|
||||
return ((i & 0x00ff) << 8) | ((i & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
|
||||
// active waiting, use only during initialization!
|
||||
static void eepromActiveDelay(uint8_t delay_ms) {
|
||||
activeDelay(delay_ms);
|
||||
}
|
||||
|
||||
void eepromWrite(uint16_t addr, uint8_t *buf, uint8_t len) {
|
||||
t_spiMsg msg = {
|
||||
.s.cmd = EEPROM_WRITE,
|
||||
.s.addr = swap(addr)
|
||||
};
|
||||
memcpy(msg.s.data, buf, len);
|
||||
|
||||
|
||||
uint8_t writeEnable = EEPROM_WREN;
|
||||
__EEPROM_CS(LOW);
|
||||
HAL_SPI_Transmit(&eepromSpi, &writeEnable, 1, HAL_MAX_DELAY);
|
||||
__EEPROM_CS(HIGH);
|
||||
|
||||
__EEPROM_CS(LOW);
|
||||
HAL_SPI_Transmit(&eepromSpi, msg.b, ((uint16_t)(len+3)), HAL_MAX_DELAY);
|
||||
__EEPROM_CS(HIGH);
|
||||
}
|
||||
|
||||
void eepromRead(uint16_t addr, uint8_t *buf, uint8_t len) {
|
||||
t_spiMsg txMsg = {
|
||||
.s.cmd = EEPROM_READ,
|
||||
.s.addr = swap(addr)
|
||||
};
|
||||
|
||||
t_spiMsg rxMsg;
|
||||
|
||||
__EEPROM_CS(LOW);
|
||||
HAL_SPI_TransmitReceive(&eepromSpi, txMsg.b, rxMsg.b, ((uint16_t)(len+3)), HAL_MAX_DELAY);
|
||||
__EEPROM_CS(HIGH);
|
||||
|
||||
memcpy(buf, rxMsg.s.data, len);
|
||||
}
|
||||
|
||||
void eepromSpiTxCpltCallback(SPI_HandleTypeDef *hspi) {
|
||||
|
||||
}
|
||||
|
||||
static void eepromHourlyUpdateDeviceStats(void *handle) {
|
||||
deviceStats.s.totalRunningHours += 1;
|
||||
|
||||
t_mbusCommStats *stats = mbusCommGetStats();
|
||||
|
||||
deviceStats.s.totalRequests += stats->mbusRequestCnt;
|
||||
deviceStats.s.totalFailures += stats->mbusErrorCnt;
|
||||
|
||||
logMsg("eeHUDS, about to write updated device stats");
|
||||
logMsg("eeHUDS, total powercycles so far: %d", deviceStats.s.totalPowercycles);
|
||||
logMsg("eeHUDS, total running hours so far: %d", deviceStats.s.totalRunningHours);
|
||||
logMsg("eeHUDS, total requests so far: %d", deviceStats.s.totalRequests);
|
||||
logMsg("eeHUDS, total failures so far: %d", deviceStats.s.totalFailures);
|
||||
|
||||
eepromWrite(DEVICE_STATS_ADDR, deviceStats.b, sizeof(deviceStats));
|
||||
}
|
||||
|
||||
void eepromReadConfigBlock(t_configBlock *destConfigBlock) {
|
||||
// static_assert((sizeof(*destConfigBlock) % EEPROM_WRITE_BLOCK_SIZE == 0), "config block has illegal size, must be dividable by 32");
|
||||
|
||||
for (uint8_t i = 0; i < (sizeof(*destConfigBlock) / EEPROM_WRITE_BLOCK_SIZE); i++) {
|
||||
eepromRead(CONFIG_BLOCK_ADDR + (i * EEPROM_WRITE_BLOCK_SIZE), ((uint8_t*)destConfigBlock) + (i * EEPROM_WRITE_BLOCK_SIZE), EEPROM_WRITE_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void eepromWriteConfigBlock(t_configBlock *srcConfigBlock) {
|
||||
for (uint8_t i = 0; i < (sizeof(*srcConfigBlock) / EEPROM_WRITE_BLOCK_SIZE); i++) {
|
||||
eepromWrite(CONFIG_BLOCK_ADDR + (i * EEPROM_WRITE_BLOCK_SIZE), ((uint8_t*)srcConfigBlock) + (i * EEPROM_WRITE_BLOCK_SIZE), EEPROM_WRITE_BLOCK_SIZE);
|
||||
eepromActiveDelay(EEPROM_AFTER_WRITE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void eepromReadDeviceBlock(uint8_t blockNum, t_deviceBlock *destDeviceBlock) {
|
||||
static_assert((sizeof(*destDeviceBlock) % EEPROM_WRITE_BLOCK_SIZE == 0), "device block has illegal size, must be dividable by 32");
|
||||
|
||||
for (uint8_t i = 0; i < (sizeof(*destDeviceBlock) / EEPROM_WRITE_BLOCK_SIZE); i++) {
|
||||
eepromRead(DEVICE_BLOCK_ADDR + (blockNum * sizeof(*destDeviceBlock)) + (i * EEPROM_WRITE_BLOCK_SIZE),
|
||||
((uint8_t*)destDeviceBlock) + (i * EEPROM_WRITE_BLOCK_SIZE),
|
||||
EEPROM_WRITE_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void eepromWriteDeviceBlock(uint8_t blockNum, t_deviceBlock *srcDeviceBlock) {
|
||||
for (uint8_t i = 0; i < (sizeof(*srcDeviceBlock) / EEPROM_WRITE_BLOCK_SIZE); i++) {
|
||||
eepromWrite(DEVICE_BLOCK_ADDR + (blockNum * sizeof(*srcDeviceBlock)) + (i * EEPROM_WRITE_BLOCK_SIZE),
|
||||
((uint8_t*)srcDeviceBlock) + (i * EEPROM_WRITE_BLOCK_SIZE),
|
||||
EEPROM_WRITE_BLOCK_SIZE);
|
||||
eepromActiveDelay(EEPROM_AFTER_WRITE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void eepromInit() {
|
||||
__EEPROM_CS(HIGH);
|
||||
|
||||
logMsg("eeI, read header");
|
||||
eepromRead(EEPROM_HEADER_ADDR, eepromHeader.b, sizeof(eepromHeader));
|
||||
logMsg("eeI, magic: %08x", eepromHeader.s.magic);
|
||||
|
||||
if (eepromHeader.s.magic != EEPROM_MAGIC) {
|
||||
logMsg("eeI, eeprom is uninitialized");
|
||||
|
||||
deviceStats.s.totalPowercycles = 0;
|
||||
deviceStats.s.totalRunningHours = 0;
|
||||
deviceStats.s.totalRequests = 0;
|
||||
deviceStats.s.totalFailures = 0;
|
||||
logMsg("eeI, about to write device stats for the first time");
|
||||
eepromWrite(DEVICE_STATS_ADDR, deviceStats.b, sizeof(deviceStats));
|
||||
eepromActiveDelay(EEPROM_AFTER_WRITE_DELAY);
|
||||
|
||||
uint8_t emptyBlock[EEPROM_WRITE_BLOCK_SIZE];
|
||||
memset(emptyBlock, 0, sizeof(emptyBlock));
|
||||
eepromWrite(CONFIG_BLOCK_ADDR, emptyBlock, EEPROM_WRITE_BLOCK_SIZE);
|
||||
eepromActiveDelay(EEPROM_AFTER_WRITE_DELAY);
|
||||
logMsg("eeI, config block initialized");
|
||||
|
||||
eepromHeader.s.magic = EEPROM_MAGIC;
|
||||
eepromHeader.s.writeCounter = 1;
|
||||
logMsg("eeI, about to write header for the first time");
|
||||
eepromWrite(EEPROM_HEADER_ADDR, eepromHeader.b, sizeof(eepromHeader));
|
||||
eepromActiveDelay(EEPROM_AFTER_WRITE_DELAY);
|
||||
logMsg("eeI, eeprom has been initialized");
|
||||
} else {
|
||||
logMsg("eeI, eeprom is initialized");
|
||||
}
|
||||
|
||||
logMsg("eeI, about to read device stats");
|
||||
eepromRead(DEVICE_STATS_ADDR, deviceStats.b, sizeof(deviceStats));
|
||||
logMsg("eeI, total powercycles so far: %d", deviceStats.s.totalPowercycles);
|
||||
logMsg("eeI, total running hours so far: %d", deviceStats.s.totalRunningHours);
|
||||
logMsg("eeI, total requests so far: %d", deviceStats.s.totalRequests);
|
||||
logMsg("eeI, total failures so far: %d", deviceStats.s.totalFailures);
|
||||
|
||||
deviceStats.s.totalPowercycles += 1;
|
||||
logMsg("eeI, about to write device stats with updated power cycles counter");
|
||||
eepromWrite(DEVICE_STATS_ADDR, deviceStats.b, sizeof(deviceStats));
|
||||
eepromActiveDelay(EEPROM_AFTER_WRITE_DELAY);
|
||||
|
||||
schAdd(eepromHourlyUpdateDeviceStats, NULL, 0, 60 * 60 * 1000);
|
||||
logMsg("eeI, hourly device stats update scheduled");
|
||||
}
|
59
cube/User/Src/frontend.c
Normal file
59
cube/User/Src/frontend.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <main.h>
|
||||
#include <adc.h>
|
||||
|
||||
#include <frontend.h>
|
||||
#include <logger.h>
|
||||
#include <show.h>
|
||||
#include <config.h>
|
||||
|
||||
|
||||
static t_configBlock *config;
|
||||
|
||||
|
||||
static volatile int32_t frontendAdcThreshold = 0;
|
||||
static volatile bool frontendEnabled = false;
|
||||
|
||||
|
||||
void frontendInit() {
|
||||
config = getConfig();
|
||||
frontendAdcThreshold = config->frontendThreshold;
|
||||
|
||||
HAL_ADCEx_Calibration_Start(&frontendAdc);
|
||||
logMsg("frontendInit, calibration done");
|
||||
HAL_ADC_Start_IT(&frontendAdc);
|
||||
logMsg("frontendInit, adc started");
|
||||
}
|
||||
|
||||
void frontendEnable() {
|
||||
frontendEnabled = true;
|
||||
}
|
||||
|
||||
void frontendDisable() {
|
||||
frontendEnabled = false;
|
||||
}
|
||||
|
||||
void frontendAdcCallback(ADC_HandleTypeDef* hadc) {
|
||||
static int32_t holdValue = 0;
|
||||
|
||||
if (frontendEnabled) {
|
||||
int32_t currentValue = (int32_t) HAL_ADC_GetValue(hadc);
|
||||
|
||||
if (holdValue == 0) {
|
||||
holdValue = currentValue;
|
||||
}
|
||||
|
||||
if (currentValue - holdValue > frontendAdcThreshold) {
|
||||
HAL_GPIO_WritePin(Frontend_Out_GPIO_Port, Frontend_Out_Pin, GPIO_PIN_RESET);
|
||||
} else {
|
||||
HAL_GPIO_WritePin(Frontend_Out_GPIO_Port, Frontend_Out_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
} else {
|
||||
if (holdValue != 0) {
|
||||
holdValue = 0;
|
||||
HAL_GPIO_WritePin(Frontend_Out_GPIO_Port, Frontend_Out_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
198
cube/User/Src/logger.c
Normal file
198
cube/User/Src/logger.c
Normal file
@ -0,0 +1,198 @@
|
||||
#include <main.h>
|
||||
#include <usart.h>
|
||||
#include <show.h>
|
||||
#include <PontCoopScheduler.h>
|
||||
#include <logger.h>
|
||||
#include <ringbuffer.h>
|
||||
#include <wizHelper.h>
|
||||
#include <socket.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
#include <stm32f103xe.h>
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
#ifndef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
#include <stm32f1xx_hal_uart.h>
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
|
||||
#define LOGBUFFER_SIZE 4096
|
||||
#define MSGBUFFER_SIZE 256
|
||||
|
||||
|
||||
static t_configBlock *config;
|
||||
|
||||
extern const uint8_t SYSLOG_SOCK;
|
||||
uint8_t syslogAddr[4];
|
||||
|
||||
uint8_t singleOctetTXBuffer;
|
||||
|
||||
static ringbuffer_t logBuffer;
|
||||
|
||||
void logInit() {
|
||||
config = getConfig();
|
||||
ringbufferInit(&logBuffer, LOGBUFFER_SIZE);
|
||||
}
|
||||
|
||||
void logFree() {
|
||||
ringbufferFree(&logBuffer);
|
||||
}
|
||||
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
void debugTxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
int c = ringbufferGetOne(&logBuffer);
|
||||
if (c > 0) {
|
||||
singleOctetTXBuffer = (uint8_t) c;
|
||||
HAL_UART_Transmit_IT(&debugUart, &singleOctetTXBuffer, 1);
|
||||
}
|
||||
}
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
#ifndef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
int logExec() {
|
||||
int c = -1;
|
||||
if (__HAL_UART_GET_FLAG(&debugUart, UART_FLAG_TXE)) { // is the TX channel free
|
||||
c = ringbufferGetOne(&logBuffer);
|
||||
if (c > 0) {
|
||||
// transfer to TX channel
|
||||
uint8_t cc = (uint8_t) c;
|
||||
HAL_UART_Transmit(&debugUart, &cc, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
void syslog(char *msg) {
|
||||
static uint8_t state = 0;
|
||||
int8_t res8 = 0;
|
||||
int32_t res32 = 0;
|
||||
|
||||
if (isNetworkAvailable()) {
|
||||
switch (state) {
|
||||
case 0:
|
||||
res8 = socket(SYSLOG_SOCK, Sn_MR_UDP, 514, SF_IO_NONBLOCK);
|
||||
if (res8 != SYSLOG_SOCK) {
|
||||
break;
|
||||
}
|
||||
state = 1;
|
||||
// no break
|
||||
case 1:
|
||||
if (! wizDnsQuery(config->syslogServerName, syslogAddr)) {
|
||||
disconnect(SYSLOG_SOCK);
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
state = 2;
|
||||
// no break
|
||||
case 2:
|
||||
res32 = sendto(SYSLOG_SOCK, (uint8_t*)msg, strlen(msg), syslogAddr, 514);
|
||||
if (res32 != strlen(msg)) {
|
||||
disconnect(SYSLOG_SOCK);
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int innerLogMsg(const char *pre, const char *post, bool syslogToo, const char *format, va_list vl) {
|
||||
const static char SYSLOG_HEADER[] = "<133>1 ";
|
||||
#define MAX_PREFIX_SIZE 20
|
||||
int res = -1;
|
||||
char msgBuffer[MSGBUFFER_SIZE+MAX_PREFIX_SIZE];
|
||||
char *bufferStart;
|
||||
|
||||
memset(msgBuffer, 0, MSGBUFFER_SIZE+MAX_PREFIX_SIZE);
|
||||
|
||||
uint16_t syslogHeaderSize = strlen(SYSLOG_HEADER);
|
||||
uint16_t preSize = (pre) ? strlen(pre) : 0;
|
||||
uint16_t prefixSize = (syslogHeaderSize > preSize) ? syslogHeaderSize : preSize;
|
||||
if (prefixSize > MAX_PREFIX_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
bufferStart = msgBuffer + prefixSize;
|
||||
|
||||
int vcnt = vsnprintf(bufferStart, MSGBUFFER_SIZE, format, vl);
|
||||
if (vcnt < MSGBUFFER_SIZE) {
|
||||
if (syslogToo) {
|
||||
memcpy(bufferStart - syslogHeaderSize, SYSLOG_HEADER, syslogHeaderSize);
|
||||
syslog(bufferStart - syslogHeaderSize);
|
||||
}
|
||||
|
||||
if (pre) {
|
||||
memcpy(bufferStart - preSize, pre, preSize);
|
||||
}
|
||||
if (post) {
|
||||
strcat(bufferStart - preSize, post);
|
||||
}
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
HAL_NVIC_DisableIRQ(UART4_IRQn);
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
res = ringbufferPut(&logBuffer, (uint8_t*) (bufferStart - preSize), strlen(bufferStart - preSize));
|
||||
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
HAL_NVIC_EnableIRQ(UART4_IRQn);
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
debugTxCpltCallback(NULL);
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int logMsg(const char *format, ...) {
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
int res = innerLogMsg(NULL, "\r\n", false, format, vl);
|
||||
va_end(vl);
|
||||
return res;
|
||||
}
|
||||
|
||||
int coloredMsg(const t_logColor color, bool syslogToo, const char *format, ...) {
|
||||
const static char POST[] = "\x1b[0m\r\n";
|
||||
const static char HIGH[] = "\x1b[1m";
|
||||
const static char RED[] = "\x1b[31;1m";
|
||||
const static char GREEN[] = "\x1b[32;1m";
|
||||
const static char BLUE[] = "\x1b[34;1m";
|
||||
const static char YELLOW[] = "\x1b[33;1m";
|
||||
const char *pre = NULL;
|
||||
switch (color) {
|
||||
case LOG_HIGH:
|
||||
pre = HIGH;
|
||||
break;
|
||||
case LOG_RED:
|
||||
pre = RED;
|
||||
break;
|
||||
case LOG_BLUE:
|
||||
pre = BLUE;
|
||||
break;
|
||||
case LOG_GREEN:
|
||||
pre = GREEN;
|
||||
break;
|
||||
case LOG_YELLOW:
|
||||
pre = YELLOW;
|
||||
break;
|
||||
case LOG_NORMAL:
|
||||
pre = NULL;
|
||||
break;
|
||||
}
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
int res = innerLogMsg(pre, POST, syslogToo, format, vl);
|
||||
va_end(vl);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
109
cube/User/Src/main2.c
Normal file
109
cube/User/Src/main2.c
Normal file
@ -0,0 +1,109 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <main.h>
|
||||
#include <usart.h>
|
||||
#include <adc.h>
|
||||
#include <spi.h>
|
||||
|
||||
#include <PontCoopScheduler.h>
|
||||
|
||||
#include <show.h>
|
||||
#include <loopCtrl.h>
|
||||
#include <mbusComm.h>
|
||||
#include <logger.h>
|
||||
#include <frontend.h>
|
||||
#include <eeprom.h>
|
||||
#include <wizHelper.h>
|
||||
#include <mqttComm.h>
|
||||
#include <cmdHandler.h>
|
||||
#include <oled.h>
|
||||
#include <config.h>
|
||||
|
||||
|
||||
void my_setup_1() {
|
||||
schInit();
|
||||
logInit();
|
||||
showInit();
|
||||
}
|
||||
|
||||
void my_errorHandler() {
|
||||
show(LED_RED, ON);
|
||||
}
|
||||
|
||||
|
||||
void my_setup_2() {
|
||||
show(LED_RED, OFF);
|
||||
show(LED_GREEN, BLINK);
|
||||
logMsg("Application starting");
|
||||
|
||||
oledInit();
|
||||
oledClearAllScreens();
|
||||
oledSetActiveScreen(OLED_SCREEN0);
|
||||
oledPrint(OLED_SCREEN0, "App starting");
|
||||
|
||||
eepromInit();
|
||||
oledPrint(OLED_SCREEN0, "eeprom init");
|
||||
|
||||
configInit();
|
||||
oledPrint(OLED_SCREEN0, "config init");
|
||||
|
||||
wizInit();
|
||||
oledPrint(OLED_SCREEN0, "network init");
|
||||
|
||||
mqttCommInit();
|
||||
oledPrint(OLED_SCREEN0, "mqtt init");
|
||||
cmdHandlerInit();
|
||||
oledPrint(OLED_SCREEN0, "cmdhandler init");
|
||||
|
||||
frontendInit();
|
||||
oledPrint(OLED_SCREEN0, "frontend init");
|
||||
|
||||
mbusCommInit();
|
||||
oledPrint(OLED_SCREEN0, "Meterbus init");
|
||||
oledPrint(OLED_SCREEN0, "App running");
|
||||
}
|
||||
|
||||
void my_loop() {
|
||||
// show(DEBUG_2, TOGGLE);
|
||||
|
||||
schExec();
|
||||
|
||||
#ifndef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
logExec();
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
|
||||
mbusCommExec();
|
||||
}
|
||||
|
||||
void SYSTICK_Callback() {
|
||||
schUpdate();
|
||||
}
|
||||
|
||||
void HAL_GPIO_EXTI_Callback(uint16_t pin) {
|
||||
if (pin == Loop_Status_Pin) {
|
||||
loopStatusCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
|
||||
if (hadc == &frontendAdc) {
|
||||
frontendAdcCallback(hadc);
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
||||
#ifdef LOGGER_OUTPUT_BY_INTERRUPT
|
||||
if (huart == &debugUart) {
|
||||
debugTxCpltCallback(huart);
|
||||
}
|
||||
#endif //LOGGER_OUTPUT_BY_INTERRUPT
|
||||
}
|
||||
|
||||
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
|
||||
if (hspi == &eepromSpi) {
|
||||
eepromSpiTxCpltCallback(hspi);
|
||||
}
|
||||
}
|
461
cube/User/Src/oled.c
Normal file
461
cube/User/Src/oled.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
* Code found at http://www.instructables.com/id/How-to-use-OLED-display-arduino-module/
|
||||
* Thank you very much!
|
||||
* Adapted from Arduino to STM32 HAL by wollud1969
|
||||
*/
|
||||
|
||||
#include <main.h>
|
||||
#include <spi.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <oled.h>
|
||||
#include <oled-fonts.h>
|
||||
#include <stm32f1xx_hal.h>
|
||||
|
||||
#include <logger.h>
|
||||
#include <PontCoopScheduler.h>
|
||||
|
||||
|
||||
#define HIGH GPIO_PIN_SET
|
||||
#define LOW GPIO_PIN_RESET
|
||||
|
||||
static void __LEDPIN_RST(GPIO_PinState v) {
|
||||
HAL_GPIO_WritePin(Display_RES_GPIO_Port, Display_RES_Pin, v);
|
||||
}
|
||||
|
||||
static void __LEDPIN_DC(GPIO_PinState v) {
|
||||
HAL_GPIO_WritePin(Display_DC_GPIO_Port, Display_DC_Pin, v);
|
||||
}
|
||||
|
||||
static void __LEDPIN_CS(GPIO_PinState v) {
|
||||
HAL_GPIO_WritePin(Display_CS_GPIO_Port, Display_CS_Pin, v);
|
||||
}
|
||||
|
||||
static void oled_WrDat(unsigned char data)
|
||||
{
|
||||
__LEDPIN_CS(LOW);
|
||||
__LEDPIN_DC(HIGH);
|
||||
|
||||
HAL_SPI_Transmit(&displaySpi, &data, 1, 0);
|
||||
|
||||
__LEDPIN_CS(HIGH);
|
||||
}
|
||||
|
||||
static void oled_WrCmd(unsigned char cmd)
|
||||
{
|
||||
__LEDPIN_CS(LOW);
|
||||
__LEDPIN_DC(LOW);
|
||||
|
||||
HAL_SPI_Transmit(&displaySpi, &cmd, 1, 0);
|
||||
|
||||
__LEDPIN_CS(HIGH);
|
||||
}
|
||||
|
||||
static void oled_Set_Pos(unsigned char x, unsigned char y)
|
||||
{
|
||||
oled_WrCmd(0xb0+y);
|
||||
oled_WrCmd(((x&0xf0)>>4)|0x10);
|
||||
oled_WrCmd((x&0x0f)|0x00);
|
||||
}
|
||||
|
||||
|
||||
static void oled_Fill(unsigned char bmp_data)
|
||||
{
|
||||
unsigned char y,x;
|
||||
|
||||
for(y=0;y<8;y++)
|
||||
{
|
||||
oled_WrCmd(0xb0+y);
|
||||
oled_WrCmd(0x00);
|
||||
oled_WrCmd(0x10);
|
||||
for(x=0;x<128;x++)
|
||||
oled_WrDat(bmp_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void oled_CLS(void)
|
||||
{
|
||||
unsigned char y,x;
|
||||
for(y=0;y<8;y++)
|
||||
{
|
||||
oled_WrCmd(0xb0+y);
|
||||
oled_WrCmd(0x00);
|
||||
oled_WrCmd(0x10);
|
||||
for(x=0;x<128;x++)
|
||||
oled_WrDat(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void oled_DLY_ms(unsigned int ms)
|
||||
{
|
||||
uint32_t start = HAL_GetTick();
|
||||
while (HAL_GetTick() < start + ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void SetStartColumn(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0x00+d%16); // Set Lower Column Start Address for Page Addressing Mode
|
||||
// Default => 0x00
|
||||
oled_WrCmd(0x10+d/16); // Set Higher Column Start Address for Page Addressing Mode
|
||||
// Default => 0x10
|
||||
}
|
||||
*/
|
||||
|
||||
static void SetAddressingMode(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0x20); // Set Memory Addressing Mode
|
||||
oled_WrCmd(d); // Default => 0x02
|
||||
// 0x00 => Horizontal Addressing Mode
|
||||
// 0x01 => Vertical Addressing Mode
|
||||
// 0x02 => Page Addressing Mode
|
||||
}
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void SetColumnAddress(unsigned char a, unsigned char b)
|
||||
{
|
||||
oled_WrCmd(0x21); // Set Column Address
|
||||
oled_WrCmd(a); // Default => 0x00 (Column Start Address)
|
||||
oled_WrCmd(b); // Default => 0x7F (Column End Address)
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* unused
|
||||
static void SetPageAddress(unsigned char a, unsigned char b)
|
||||
{
|
||||
oled_WrCmd(0x22); // Set Page Address
|
||||
oled_WrCmd(a); // Default => 0x00 (Page Start Address)
|
||||
oled_WrCmd(b); // Default => 0x07 (Page End Address)
|
||||
}
|
||||
*/
|
||||
|
||||
static void SetStartLine(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0x40|d); // Set Display Start Line
|
||||
// Default => 0x40 (0x00)
|
||||
}
|
||||
|
||||
static void SetContrastControl(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0x81); // Set Contrast Control
|
||||
oled_WrCmd(d); // Default => 0x7F
|
||||
}
|
||||
|
||||
static void Set_Charge_Pump(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0x8D); // Set Charge Pump
|
||||
oled_WrCmd(0x10|d); // Default => 0x10
|
||||
// 0x10 (0x00) => Disable Charge Pump
|
||||
// 0x14 (0x04) => Enable Charge Pump
|
||||
}
|
||||
|
||||
static void Set_Segment_Remap(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xA0|d); // Set Segment Re-Map
|
||||
// Default => 0xA0
|
||||
// 0xA0 (0x00) => Column Address 0 Mapped to SEG0
|
||||
// 0xA1 (0x01) => Column Address 0 Mapped to SEG127
|
||||
}
|
||||
|
||||
static void Set_Entire_Display(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xA4|d); // Set Entire Display On / Off
|
||||
// Default => 0xA4
|
||||
// 0xA4 (0x00) => Normal Display
|
||||
// 0xA5 (0x01) => Entire Display On
|
||||
}
|
||||
|
||||
static void Set_Inverse_Display(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xA6|d); // Set Inverse Display On/Off
|
||||
// Default => 0xA6
|
||||
// 0xA6 (0x00) => Normal Display
|
||||
// 0xA7 (0x01) => Inverse Display On
|
||||
}
|
||||
|
||||
static void Set_Multiplex_Ratio(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xA8); // Set Multiplex Ratio
|
||||
oled_WrCmd(d); // Default => 0x3F (1/64 Duty)
|
||||
}
|
||||
|
||||
static void Set_Display_On_Off(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xAE|d); // Set Display On/Off
|
||||
// Default => 0xAE
|
||||
// 0xAE (0x00) => Display Off
|
||||
// 0xAF (0x01) => Display On
|
||||
}
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void SetStartPage(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xB0|d); // Set Page Start Address for Page Addressing Mode
|
||||
// Default => 0xB0 (0x00)
|
||||
}
|
||||
*/
|
||||
|
||||
static void Set_Common_Remap(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xC0|d); // Set COM Output Scan Direction
|
||||
// Default => 0xC0
|
||||
// 0xC0 (0x00) => Scan from COM0 to 63
|
||||
// 0xC8 (0x08) => Scan from COM63 to 0
|
||||
}
|
||||
|
||||
static void Set_Display_Offset(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xD3); // Set Display Offset
|
||||
oled_WrCmd(d); // Default => 0x00
|
||||
}
|
||||
|
||||
static void Set_Display_Clock(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xD5); // Set Display Clock Divide Ratio / Oscillator Frequency
|
||||
oled_WrCmd(d); // Default => 0x80
|
||||
// D[3:0] => Display Clock Divider
|
||||
// D[7:4] => Oscillator Frequency
|
||||
}
|
||||
|
||||
static void Set_Precharge_Period(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xD9); // Set Pre-Charge Period
|
||||
oled_WrCmd(d); // Default => 0x22 (2 Display Clocks [Phase 2] / 2 Display Clocks [Phase 1])
|
||||
// D[3:0] => Phase 1 Period in 1~15 Display Clocks
|
||||
// D[7:4] => Phase 2 Period in 1~15 Display Clocks
|
||||
}
|
||||
|
||||
static void Set_Common_Config(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xDA); // Set COM Pins Hardware Configuration
|
||||
oled_WrCmd(0x02|d); // Default => 0x12 (0x10)
|
||||
// Alternative COM Pin Configuration
|
||||
// Disable COM Left/Right Re-Map
|
||||
}
|
||||
|
||||
static void Set_VCOMH(unsigned char d)
|
||||
{
|
||||
oled_WrCmd(0xDB); // Set VCOMH Deselect Level
|
||||
oled_WrCmd(d); // Default => 0x20 (0.77*VCC)
|
||||
}
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void Set_NOP(void)
|
||||
{
|
||||
oled_WrCmd(0xE3); // Command for No Operation
|
||||
}
|
||||
*/
|
||||
|
||||
void oledInit(void)
|
||||
{
|
||||
// LEDPIN_Init();
|
||||
// LED_PORT=0X0F;
|
||||
//LED_SCLH;;;
|
||||
//LED_RSTL;;;
|
||||
//digitalWrite(SCL_PIN,HIGH);;;
|
||||
__LEDPIN_RST(LOW);
|
||||
// for(i=0;i<100;i++)asm("nop");
|
||||
oled_DLY_ms(50);
|
||||
//LED_RSTH;;;
|
||||
__LEDPIN_RST(HIGH);
|
||||
|
||||
Set_Display_On_Off(0x00); // Display Off (0x00/0x01)
|
||||
Set_Display_Clock(0x80); // Set Clock as 100 Frames/Sec
|
||||
Set_Multiplex_Ratio(0x3F); // 1/64 Duty (0x0F~0x3F)
|
||||
Set_Display_Offset(0x00); // Shift Mapping RAM Counter (0x00~0x3F)
|
||||
SetStartLine(0x00); // Set Mapping RAM Display Start Line (0x00~0x3F)
|
||||
Set_Charge_Pump(0x04); // Enable Embedded DC/DC Converter (0x00/0x04)
|
||||
SetAddressingMode(0x02); // Set Page Addressing Mode (0x00/0x01/0x02)
|
||||
Set_Segment_Remap(0x01); // Set SEG/Column Mapping
|
||||
Set_Common_Remap(0x08); // Set COM/Row Scan Direction
|
||||
Set_Common_Config(0x10); // Set Sequential Configuration (0x00/0x10)
|
||||
SetContrastControl(0xCF); // Set SEG Output Current
|
||||
Set_Precharge_Period(0xF1); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
|
||||
Set_VCOMH(0x40); // Set VCOM Deselect Level
|
||||
Set_Entire_Display(0x00); // Disable Entire Display On (0x00/0x01)
|
||||
Set_Inverse_Display(0x00); // Disable Inverse Display On (0x00/0x01)
|
||||
Set_Display_On_Off(0x01); // Display On (0x00/0x01)
|
||||
oled_Fill(0x00); //clear all
|
||||
oled_Set_Pos(0,0);
|
||||
}
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void oled_P6x8Char(unsigned char x,unsigned char y,unsigned char ch)
|
||||
{
|
||||
unsigned char c=0,i=0;
|
||||
|
||||
c =ch-32;
|
||||
if(x>122)
|
||||
{
|
||||
x=0;
|
||||
y++;
|
||||
}
|
||||
oled_Set_Pos(x,y);
|
||||
for(i=0;i<6;i++)
|
||||
{
|
||||
oled_WrDat(F6x8[c][i]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static void oled_P6x8Str(unsigned char x,unsigned char y,char ch[])
|
||||
{
|
||||
// coloredMsg(LOG_BLUE, false, "OLED: %d %d %s", x, y, ch);
|
||||
|
||||
unsigned char c=0,i=0,j=0;
|
||||
while (ch[j]!='\0')
|
||||
{
|
||||
c =ch[j]-32;
|
||||
if(x>126)
|
||||
{
|
||||
x=0;
|
||||
y++;
|
||||
}
|
||||
oled_Set_Pos(x,y);
|
||||
for(i=0;i<6;i++)
|
||||
{
|
||||
oled_WrDat(F6x8[c][i]);
|
||||
}
|
||||
x+=6;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void oled_P8x16Str(unsigned char x,unsigned char y,char ch[])
|
||||
{
|
||||
unsigned char c=0,i=0,j=0;
|
||||
while (ch[j]!='\0')
|
||||
{
|
||||
c =ch[j]-32;
|
||||
if(x>120)
|
||||
{
|
||||
x=0;
|
||||
y++;
|
||||
}
|
||||
oled_Set_Pos(x,y);
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
oled_WrDat(F8X16[(c<<4)+i]);
|
||||
}
|
||||
oled_Set_Pos(x,y+1);
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
oled_WrDat(F8X16[(c<<4)+i+8]);
|
||||
}
|
||||
x+=8;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void oled_PrintBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char bmp[])
|
||||
{
|
||||
int ii=0;
|
||||
unsigned char x,y;
|
||||
for(y=y0;y<=y1;y++)
|
||||
{
|
||||
oled_Set_Pos(x0,y);
|
||||
for(x=x0;x<x1;x++)
|
||||
{
|
||||
oled_WrDat(bmp[ii++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* unused
|
||||
static void oled_Cursor(unsigned char cursor_column, unsigned char cursor_row)
|
||||
{
|
||||
if(cursor_row != 0)
|
||||
{
|
||||
if(cursor_column == 1) oled_Set_Pos(0, cursor_row + 2);
|
||||
else oled_Set_Pos(80 + (cursor_column - 2)*6, cursor_row + 2);
|
||||
oled_WrDat(0xFF);
|
||||
oled_WrDat(0xFF);
|
||||
oled_WrDat(0xFF);
|
||||
oled_WrDat(0xFF);
|
||||
oled_WrDat(0xFF);
|
||||
oled_WrDat(0xFF);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_LINES 8
|
||||
#define MAX_CHARS 21
|
||||
#define NUM_OF_SCREENS 2
|
||||
|
||||
static uint8_t currentLine = 0;
|
||||
static char lines[NUM_OF_SCREENS][MAX_LINES+1][MAX_CHARS+1];
|
||||
static oledScreen_t activeScreen = OLED_SCREEN0;
|
||||
|
||||
void oledClearActiveScreen() {
|
||||
oled_CLS();
|
||||
memset(lines[activeScreen], 0, sizeof(lines[activeScreen]));
|
||||
currentLine = 0;
|
||||
}
|
||||
|
||||
void oledClearAllScreens() {
|
||||
oled_CLS();
|
||||
memset(lines, 0, sizeof(lines));
|
||||
currentLine = 0;
|
||||
}
|
||||
|
||||
void oledPrint(oledScreen_t screen, char msg[]) {
|
||||
if (currentLine < MAX_LINES) {
|
||||
strncpy(lines[screen][currentLine], msg, MAX_CHARS);
|
||||
memset(lines[screen][currentLine] + strlen(msg), ' ', MAX_CHARS - strlen(msg) - 1);
|
||||
lines[screen][currentLine][MAX_CHARS - 1] = 0;
|
||||
currentLine++;
|
||||
} else {
|
||||
for (uint8_t i = 1; i < MAX_LINES; i++) {
|
||||
memcpy(lines[screen][i-1], lines[screen][i], MAX_CHARS);
|
||||
}
|
||||
strncpy(lines[screen][MAX_LINES - 1], msg, MAX_CHARS);
|
||||
memset(lines[screen][MAX_LINES - 1] + strlen(msg), ' ', MAX_CHARS - strlen(msg) - 1);
|
||||
lines[screen][MAX_LINES - 1][MAX_CHARS - 1] = 0;
|
||||
}
|
||||
|
||||
if (screen == activeScreen) {
|
||||
for (uint8_t line = 0; line < MAX_LINES; line++) {
|
||||
oled_P6x8Str(1, line, lines[activeScreen][line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void oledSwitchBackToScreen0(void *handle) {
|
||||
oledSetActiveScreen(OLED_SCREEN0);
|
||||
}
|
||||
|
||||
void oledSetActiveScreen(oledScreen_t screen) {
|
||||
activeScreen = screen;
|
||||
if (screen == OLED_SCREEN1) {
|
||||
schAdd(oledSwitchBackToScreen0, NULL, 10000, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void oledPrintf(oledScreen_t screen, const char *format, ...) {
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
char buf[MAX_CHARS+1];
|
||||
vsnprintf(buf, MAX_CHARS, format, vl);
|
||||
va_end(vl);
|
||||
oledPrint(screen, buf);
|
||||
}
|
11
cube/User/Src/ports.c
Normal file
11
cube/User/Src/ports.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
// on the W5500 there are eight ports available
|
||||
|
||||
const uint8_t DHCP_SOCK = 0;
|
||||
const uint8_t MQTT_SOCK = 1;
|
||||
const uint8_t CMD_SOCK = 2;
|
||||
const uint8_t SYSLOG_SOCK = 3;
|
||||
const uint8_t DNS_SOCK = 4;
|
57
cube/User/Src/regularCmds.c
Normal file
57
cube/User/Src/regularCmds.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <cmdHelper.h>
|
||||
#include <logger.h>
|
||||
|
||||
#include <mbusComm.h>
|
||||
#include <eeprom.h>
|
||||
|
||||
|
||||
static bool globalStatsCmd(uint8_t argc, char **args) {
|
||||
uint32_t uptime = HAL_GetTick() / 1000;
|
||||
sendFormatString(\
|
||||
"Current uptime: %ld\n\r" \
|
||||
"\n\r",
|
||||
uptime
|
||||
);
|
||||
|
||||
t_deviceStats *deviceStats = getGlobalDeviceStats();
|
||||
sendFormatString(\
|
||||
"Global Device statistics\n\r" \
|
||||
" Total running hours: %ld\n\r" \
|
||||
" Total power cycles: %ld\n\r" \
|
||||
" Total requests: %ld\n\r" \
|
||||
" Total failures: %ld\n\r" \
|
||||
"\n\r",
|
||||
deviceStats->totalRunningHours, deviceStats->totalPowercycles,
|
||||
deviceStats->totalRequests, deviceStats->totalFailures
|
||||
);
|
||||
|
||||
t_mbusCommStats *mbusStats = mbusCommGetStats();
|
||||
sendFormatString(\
|
||||
"Global Meterbus/UART statistics\n\r" \
|
||||
" Meterbus Requests: %ld\n\r" \
|
||||
" Meterbus Errors: %ld\n\r" \
|
||||
" UART Octets: %ld\n\r" \
|
||||
" UART Overruns: %ld\n\r" \
|
||||
" UART Framing Errs: %ld\n\r" \
|
||||
" UART Parity Errs: %ld\n\r" \
|
||||
" UART Noise Errs: %ld\n\r",
|
||||
mbusStats->mbusRequestCnt, mbusStats->mbusErrorCnt,
|
||||
mbusStats->uartOctetCnt, mbusStats->uartOverrunCnt, mbusStats->uartFramingErrCnt, mbusStats->uartParityErrCnt, mbusStats->uartNoiseErrCnt
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const cmd_t COMMANDS[] = {
|
||||
{ .name = "globalStats", .cmdFunc = globalStatsCmd,
|
||||
.help = \
|
||||
"globalStats .......................... Show the global statistics\n\r" \
|
||||
" counters requestCnt and errorCnt\n\r"
|
||||
},
|
||||
{ .name = "END_OF_CMDS", .help = "",.cmdFunc = NULL }
|
||||
};
|
||||
|
||||
const cmd_t *getRegularCommands() {
|
||||
return COMMANDS;
|
||||
}
|
75
cube/User/Src/ringbuffer.c
Normal file
75
cube/User/Src/ringbuffer.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ringbuffer.h>
|
||||
|
||||
|
||||
void ringbufferInit(ringbuffer_t *handle, uint32_t bufferSize) {
|
||||
handle->bufferSize = bufferSize;
|
||||
handle->buffer = (uint8_t*) malloc(handle->bufferSize);
|
||||
memset(handle->buffer, 0, handle->bufferSize);
|
||||
handle->bufferReadIdx = 0;
|
||||
handle->bufferWriteIdx = 0;
|
||||
}
|
||||
|
||||
void ringbufferFree(ringbuffer_t *handle) {
|
||||
free(handle->buffer);
|
||||
handle->buffer = NULL;
|
||||
handle->bufferSize = 0;
|
||||
handle->bufferReadIdx = 0;
|
||||
handle->bufferWriteIdx = 0;
|
||||
}
|
||||
|
||||
|
||||
int ringbufferPut(ringbuffer_t *handle, uint8_t *data, uint32_t dataLen) {
|
||||
uint32_t freeSpace = 0;
|
||||
if (handle->bufferReadIdx == handle->bufferWriteIdx) {
|
||||
freeSpace = handle->bufferSize;
|
||||
} else if (handle->bufferReadIdx > handle->bufferWriteIdx) {
|
||||
freeSpace = handle->bufferReadIdx - handle->bufferWriteIdx;
|
||||
} else {
|
||||
freeSpace = (handle->bufferSize - handle->bufferWriteIdx) + handle->bufferReadIdx;
|
||||
}
|
||||
|
||||
freeSpace--;
|
||||
|
||||
if (dataLen > freeSpace) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dataLen <= (handle->bufferSize - handle->bufferWriteIdx)) {
|
||||
memcpy(handle->buffer + handle->bufferWriteIdx, data, dataLen);
|
||||
handle->bufferWriteIdx += dataLen;
|
||||
if (handle->bufferWriteIdx == handle->bufferSize) {
|
||||
handle->bufferWriteIdx = 0;
|
||||
}
|
||||
} else {
|
||||
uint32_t remainingToTop = handle->bufferSize - handle->bufferWriteIdx;
|
||||
memcpy(handle->buffer + handle->bufferWriteIdx, data, remainingToTop);
|
||||
memcpy(handle->buffer, data + remainingToTop, dataLen - remainingToTop);
|
||||
handle->bufferWriteIdx = dataLen - remainingToTop;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ringbufferEmpty(ringbuffer_t *handle) {
|
||||
return handle->bufferReadIdx == handle->bufferWriteIdx;
|
||||
}
|
||||
|
||||
uint8_t *ringbufferGet(ringbuffer_t *handle, uint32_t dataLen) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ringbufferGetOne(ringbuffer_t *handle) {
|
||||
int res = -1;
|
||||
if (handle->bufferReadIdx != handle->bufferWriteIdx) {
|
||||
uint8_t r = *(handle->buffer + handle->bufferReadIdx);
|
||||
handle->bufferReadIdx += 1;
|
||||
if (handle->bufferReadIdx == handle->bufferSize) {
|
||||
handle->bufferReadIdx = 0;
|
||||
}
|
||||
res = (int) r;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
46
cube/User/Src/show.c
Normal file
46
cube/User/Src/show.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include <main.h>
|
||||
#include <show.h>
|
||||
#include <PontCoopScheduler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stm32f103xe.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef *port;
|
||||
uint16_t pin;
|
||||
signalAction_t currentState;
|
||||
} showElement_t;
|
||||
|
||||
showElement_t showElement[] = {
|
||||
{ .port = Debug_Signal_1_GPIO_Port, .pin = Debug_Signal_1_Pin, .currentState = OFF },
|
||||
{ .port = Debug_Signal_2_GPIO_Port, .pin = Debug_Signal_2_Pin, .currentState = OFF },
|
||||
{ .port = LED_Red_GPIO_Port, .pin = LED_Red_Pin, .currentState = OFF },
|
||||
{ .port = LED_Green_GPIO_Port, .pin = LED_Green_Pin, .currentState = OFF },
|
||||
{ .port = NULL, .pin = 0, .currentState = OFF }
|
||||
};
|
||||
|
||||
static void showHandler(void *handle) {
|
||||
uint8_t idx = 0;
|
||||
while (showElement[idx].port) {
|
||||
if (showElement[idx].currentState == BLINK) {
|
||||
HAL_GPIO_TogglePin(showElement[idx].port, showElement[idx].pin);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void show(signalPin_t signalPin, signalAction_t action) {
|
||||
showElement[signalPin].currentState = action;
|
||||
if (action == ON || action == OFF) {
|
||||
HAL_GPIO_WritePin(showElement[signalPin].port, showElement[signalPin].pin, ((action == ON) ? GPIO_PIN_SET : GPIO_PIN_RESET));
|
||||
} else if (action == TOGGLE) {
|
||||
HAL_GPIO_TogglePin(showElement[signalPin].port, showElement[signalPin].pin);
|
||||
}
|
||||
}
|
||||
|
||||
void showInit() {
|
||||
schAdd(showHandler, NULL, 0, 250);
|
||||
}
|
10
cube/User/Src/utils.c
Normal file
10
cube/User/Src/utils.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <utils.h>
|
||||
#include <main.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// active waiting, use only during initialization!
|
||||
void activeDelay(uint8_t delay_ms) {
|
||||
uint32_t startTime = HAL_GetTick();
|
||||
while (startTime + delay_ms > HAL_GetTick());
|
||||
}
|
232
cube/User/Src/wizHelper.c
Normal file
232
cube/User/Src/wizHelper.c
Normal file
@ -0,0 +1,232 @@
|
||||
#include <wizHelper.h>
|
||||
#include <stdint.h>
|
||||
#include <main2.h>
|
||||
#include <spi.h>
|
||||
#include <stdbool.h>
|
||||
#include <logger.h>
|
||||
#include <PontCoopScheduler.h>
|
||||
#include <utils.h>
|
||||
#include <wizchip_conf.h>
|
||||
#include <string.h>
|
||||
#include <dhcp.h>
|
||||
#include <show.h>
|
||||
#include <oled.h>
|
||||
#include <dns.h>
|
||||
#include <config.h>
|
||||
|
||||
|
||||
|
||||
static t_configBlock *config;
|
||||
|
||||
wiz_NetInfo netInfo;
|
||||
|
||||
#define DHCP_BUFFER_SIZE 2048
|
||||
static uint8_t dhcpBuffer[DHCP_BUFFER_SIZE];
|
||||
|
||||
#define DNS_BUFFER_SIZE MAX_DNS_BUF_SIZE
|
||||
static uint8_t dnsBuffer[DNS_BUFFER_SIZE];
|
||||
|
||||
extern const uint8_t DHCP_SOCK;
|
||||
extern const uint8_t DNS_SOCK;
|
||||
|
||||
static bool networkAvailable = false;
|
||||
|
||||
bool isNetworkAvailable() {
|
||||
return networkAvailable;
|
||||
}
|
||||
|
||||
uint8_t* wizGetIPAddress() {
|
||||
return netInfo.ip;
|
||||
}
|
||||
static void wiz_cs_select(void) {
|
||||
HAL_GPIO_WritePin(ETHER_CS_GPIO_Port, ETHER_CS_Pin, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
static void wiz_cs_deselect(void) {
|
||||
HAL_GPIO_WritePin(ETHER_CS_GPIO_Port, ETHER_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
static uint8_t wiz_spi_readbyte(void) {
|
||||
uint8_t rbuf;
|
||||
HAL_SPI_Receive(ðerSpi, &rbuf, 1, HAL_MAX_DELAY);
|
||||
return rbuf;
|
||||
}
|
||||
|
||||
static void wiz_spi_writebyte(uint8_t wb) {
|
||||
HAL_SPI_Transmit(ðerSpi, &wb, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
|
||||
static void wiz_spi_readburst(uint8_t* pBuf, uint16_t len) {
|
||||
HAL_SPI_Receive(ðerSpi, pBuf, len, HAL_MAX_DELAY);
|
||||
}
|
||||
|
||||
static void wiz_spi_writeburst(uint8_t* pBuf, uint16_t len) {
|
||||
HAL_SPI_Transmit(ðerSpi, pBuf, len, HAL_MAX_DELAY);
|
||||
}
|
||||
|
||||
static void wizReset(bool b) {
|
||||
HAL_GPIO_WritePin(ETHER_RES_GPIO_Port, ETHER_RES_Pin, b ? GPIO_PIN_RESET : GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
|
||||
static void wizDHCPAssign() {
|
||||
coloredMsg(LOG_BLUE, false, "wizda");
|
||||
getIPfromDHCP(netInfo.ip);
|
||||
coloredMsg(LOG_BLUE, false, "wizda, IP: %d.%d.%d.%d", netInfo.ip[0], netInfo.ip[1], netInfo.ip[2], netInfo.ip[3]);
|
||||
getGWfromDHCP(netInfo.gw);
|
||||
coloredMsg(LOG_BLUE, false, "wizda, GW: %d.%d.%d.%d", netInfo.gw[0], netInfo.gw[1], netInfo.gw[2], netInfo.gw[3]);
|
||||
getSNfromDHCP(netInfo.sn);
|
||||
coloredMsg(LOG_BLUE, false, "wizda, SN: %d.%d.%d.%d", netInfo.sn[0], netInfo.sn[1], netInfo.sn[2], netInfo.sn[3]);
|
||||
getDNSfromDHCP(netInfo.dns);
|
||||
coloredMsg(LOG_BLUE, false, "wizda, DNS: %d.%d.%d.%d", netInfo.dns[0], netInfo.dns[1], netInfo.dns[2], netInfo.dns[3]);
|
||||
|
||||
wizchip_setnetinfo(&netInfo);
|
||||
coloredMsg(LOG_BLUE, false, "wizda, set netinfo again");
|
||||
|
||||
networkAvailable = true;
|
||||
show(LED_GREEN, ON);
|
||||
coloredMsg(LOG_BLUE, false, "wizda, network is available");
|
||||
|
||||
oledPrintf(OLED_SCREEN0, "Addr:%d.%d.%d.%d", netInfo.ip[0], netInfo.ip[1], netInfo.ip[2], netInfo.ip[3]);
|
||||
}
|
||||
|
||||
static void wizDHCPUpdate() {
|
||||
coloredMsg(LOG_BLUE, false, "wizdu");
|
||||
getIPfromDHCP(netInfo.ip);
|
||||
coloredMsg(LOG_BLUE, false, "wizdu, IP: %d.%d.%d.%d", netInfo.ip[0], netInfo.ip[1], netInfo.ip[2], netInfo.ip[3]);
|
||||
getGWfromDHCP(netInfo.gw);
|
||||
coloredMsg(LOG_BLUE, false, "wizdu, GW: %d.%d.%d.%d", netInfo.gw[0], netInfo.gw[1], netInfo.gw[2], netInfo.gw[3]);
|
||||
getSNfromDHCP(netInfo.sn);
|
||||
coloredMsg(LOG_BLUE, false, "wizdu, SN: %d.%d.%d.%d", netInfo.sn[0], netInfo.sn[1], netInfo.sn[2], netInfo.sn[3]);
|
||||
getDNSfromDHCP(netInfo.dns);
|
||||
coloredMsg(LOG_BLUE, false, "wizdu, DNS: %d.%d.%d.%d", netInfo.dns[0], netInfo.dns[1], netInfo.dns[2], netInfo.dns[3]);
|
||||
|
||||
wizchip_setnetinfo(&netInfo);
|
||||
coloredMsg(LOG_BLUE, false, "wizdu, netinfo updated");
|
||||
}
|
||||
|
||||
static void wizDHCPHandler(void *handle) {
|
||||
static uint8_t lastDhcpRes = 255;
|
||||
|
||||
uint8_t res = DHCP_run();
|
||||
|
||||
if (lastDhcpRes != res) {
|
||||
coloredMsg(LOG_BLUE, false, "wizdh, dhcp state has changed: %d", res);
|
||||
lastDhcpRes = res;
|
||||
}
|
||||
}
|
||||
|
||||
bool wizDnsQuery(char *name, uint8_t *ip) {
|
||||
bool retCode = false;
|
||||
coloredMsg(LOG_BLUE, false, "wizdq, querying for %s", name);
|
||||
int8_t res = DNS_run(netInfo.dns, (uint8_t*) name, ip);
|
||||
coloredMsg(LOG_BLUE, false, "wizdq, DNS_run returns %d", res);
|
||||
retCode = (res == 1);
|
||||
if (retCode) {
|
||||
coloredMsg(LOG_BLUE, false, "wizdq, got address %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static void wizPhyLinkHandler(void *handle) {
|
||||
// this handler is anyhow called with a 1s period, so we reuse it for the DNS timer
|
||||
DNS_time_handler();
|
||||
|
||||
static uint8_t lastStablePhyLink = 255;
|
||||
static bool dhcpInitialized = false;
|
||||
|
||||
uint8_t phyLink = 0;
|
||||
int8_t res = ctlwizchip(CW_GET_PHYLINK, (void*) &phyLink);
|
||||
if (lastStablePhyLink != phyLink) {
|
||||
coloredMsg(LOG_BLUE, false, "wizplh, ctlwizchip returns %d, phy link changed to %d", res, phyLink);
|
||||
lastStablePhyLink = phyLink;
|
||||
|
||||
if (phyLink == PHY_LINK_ON) {
|
||||
oledPrint(OLED_SCREEN0, "Link available");
|
||||
// start DHCP handler
|
||||
memset(dhcpBuffer, 0, DHCP_BUFFER_SIZE);
|
||||
reg_dhcp_cbfunc(wizDHCPAssign, wizDHCPUpdate, NULL);
|
||||
DHCP_init(DHCP_SOCK, dhcpBuffer);
|
||||
coloredMsg(LOG_BLUE, false, "wizplh, DHCP initialized");
|
||||
|
||||
// run the dhcp handler the first time after 1s and then every 100ms
|
||||
schAdd(wizDHCPHandler, NULL, 1000, 1000);
|
||||
coloredMsg(LOG_BLUE, false, "wizplh, DHCP handler scheduled");
|
||||
|
||||
dhcpInitialized = true;
|
||||
} else {
|
||||
oledPrint(OLED_SCREEN0, "Link lost");
|
||||
|
||||
networkAvailable = false;
|
||||
show(LED_GREEN, BLINK);
|
||||
coloredMsg(LOG_BLUE, false, "wizplh, network is unavailable");
|
||||
|
||||
// stop DHCP handler
|
||||
if (dhcpInitialized) {
|
||||
DHCP_stop();
|
||||
coloredMsg(LOG_BLUE, false, "wizplh, DHCP stopped");
|
||||
|
||||
schDel(wizDHCPHandler, NULL);
|
||||
coloredMsg(LOG_BLUE, false, "wizplh, DHCP handler unscheduled");
|
||||
|
||||
dhcpInitialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wizInit() {
|
||||
config = getConfig();
|
||||
netInfo.dhcp = NETINFO_DHCP;
|
||||
memcpy(netInfo.mac, config->macAddress, 6);
|
||||
|
||||
coloredMsg(LOG_BLUE, false, "wizI, resetting Ethernet module");
|
||||
wizReset(true);
|
||||
activeDelay(2);
|
||||
wizReset(false);
|
||||
activeDelay(50);
|
||||
|
||||
coloredMsg(LOG_BLUE, false, "wizI, registering callbacks");
|
||||
reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, cs funcs registed");
|
||||
reg_wizchip_spi_cbfunc(wiz_spi_readbyte, wiz_spi_writebyte);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, spi funcs registed");
|
||||
reg_wizchip_spiburst_cbfunc(wiz_spi_readburst, wiz_spi_writeburst);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, spi burst funcs registed");
|
||||
|
||||
|
||||
coloredMsg(LOG_BLUE, false, "wizI, initializing Ethernet module");
|
||||
uint8_t bufSizes[] = { 2, 2, 2, 2, 2, 2, 2, 2 };
|
||||
int8_t res = wizchip_init(bufSizes, bufSizes);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, module driver returned %d", res);
|
||||
|
||||
wizphy_reset();
|
||||
activeDelay(5);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, reset phy");
|
||||
|
||||
wiz_PhyConf wpc;
|
||||
wpc.mode = PHY_MODE_MANUAL;
|
||||
wpc.speed = PHY_MODE_MANUAL;
|
||||
wpc.duplex = PHY_DUPLEX_FULL;
|
||||
wizphy_setphyconf(&wpc);
|
||||
activeDelay(5);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, phy config set");
|
||||
|
||||
wizchip_setnetinfo(&netInfo);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, netinfo set to Ethernet module");
|
||||
|
||||
res = wizchip_setnetmode(NM_FORCEARP); // and not NM_PINGBLOCK
|
||||
coloredMsg(LOG_BLUE, false, "wizI, set netmode, result is %d", res);
|
||||
|
||||
uint8_t buf[6];
|
||||
res = ctlwizchip(CW_GET_ID, (void*) buf);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, CW_GET_ID: %d %02x %02x %02x %02x %02x %02x", res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||||
|
||||
DNS_init(DNS_SOCK, dnsBuffer);
|
||||
|
||||
schAdd(wizPhyLinkHandler, NULL, 0, 1000);
|
||||
coloredMsg(LOG_BLUE, false, "wizI, PhyLink handler scheduled");
|
||||
|
||||
return 0;
|
||||
}
|
8
openocd.cfg
Normal file
8
openocd.cfg
Normal file
@ -0,0 +1,8 @@
|
||||
source /usr/share/openocd/scripts/interface/stlink-v2.cfg
|
||||
source /usr/share/openocd/scripts/target/stm32f1x.cfg
|
||||
reset_config srst_nogate
|
||||
# reset_config connect_assert_srst
|
||||
# reset_config none separate
|
||||
# set CONNECT_UNDER_RESET 0
|
||||
|
||||
|
62
readme.md
Normal file
62
readme.md
Normal file
@ -0,0 +1,62 @@
|
||||
## Build environment
|
||||
|
||||
On Ubuntu/Debian install
|
||||
|
||||
* ``gcc-arm-none-eabi``
|
||||
* ``openocd``
|
||||
|
||||
|
||||
Alternatively use a prepared Docker image
|
||||
|
||||
docker run -it --rm -u ${UID} -v ${PWD}:/mnt wollud1969/build-env-arm-none-eabi:1.1.0 bash
|
||||
|
||||
Start the container from the project root. Or use the script ``startBuildEnv.sh`` from the tools directory.
|
||||
|
||||
|
||||
Get the STM32CubeMX tool from the ST homepage. You may use this [link](https://www.st.com/en/development-tools/stm32cubemx.html).
|
||||
|
||||
|
||||
## Preparing generated code to include user code
|
||||
|
||||
After code generation in CubeMX the ``Makefile`` and the file ``main.c`` in ``Core/Src`` needs
|
||||
to be edited to include user code. From the ``cube`` directory in the project root run:
|
||||
|
||||
../tools/insertMyCode.sh
|
||||
|
||||
User code has to life in ``User/Src`` and ``User/Inc``. All ``*.c`` file from ``User/Src`` will be
|
||||
attached to the ``C_SOURCES`` variable in the ``Makefile``.
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
From the ``cube`` directory in the project root simply run
|
||||
|
||||
make
|
||||
|
||||
|
||||
## Uploading to the target
|
||||
|
||||
Start ``openocd`` from the project root using the existing configuration file (for derived projects
|
||||
adjust the configuration concerning the use MCU)
|
||||
|
||||
openocd -f openocd.cfg
|
||||
|
||||
Connect to the started ``openocd`` server using
|
||||
|
||||
nc localhost 4444
|
||||
|
||||
To upload a built binary enter
|
||||
|
||||
reset init
|
||||
reset halt
|
||||
flash write_image erase /home/wn/Workspaces/$PROJECT/cube/build/cube.elf
|
||||
reset run
|
||||
|
||||
Make sure to use the absolute path. Alternatively, use the script ``upload.sh`` from the tools directory.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
83
tools/insertMyCode.sh
Executable file
83
tools/insertMyCode.sh
Executable file
@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
MAIN_C=./Core/Src/main.c
|
||||
MAIN_C_BAK=${MAIN_C}-bak
|
||||
|
||||
IT_C=./Core/Src/stm32f1xx_it.c
|
||||
IT_C_BAK=${IT_C}-bak
|
||||
|
||||
MAKEFILE=./Makefile
|
||||
MAKEFILE_BAK=${MAKEFILE}-bak
|
||||
|
||||
PROCESSED="Processed by $0"
|
||||
|
||||
checkFile () {
|
||||
FILE=$1
|
||||
BAK_FILE=$2
|
||||
if [ ! -f $FILE ]; then
|
||||
echo "no $FILE available"
|
||||
exit 1
|
||||
fi
|
||||
if [ -f $BAK_FILE ]; then
|
||||
echo "$BAK_FILE already available, delete manually"
|
||||
exit 1
|
||||
fi
|
||||
grep -q "$PROCESSED" $FILE
|
||||
if [ "$?" = "0" ]; then
|
||||
echo "$FILE has already been processed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
checkFile $MAIN_C $MAIN_C_BAK
|
||||
checkFile $MAKEFILE $MAKEFILE_BAK
|
||||
checkFile $IT_C $IT_C_BAK
|
||||
|
||||
cp $MAIN_C $MAIN_C_BAK
|
||||
echo "// $PROCESSED" > $MAIN_C
|
||||
cat $MAIN_C_BAK | \
|
||||
sed -e 's,\(/\* USER CODE BEGIN Includes \*/\),\1\n#include "main2.h"\n,' \
|
||||
-e 's,\(/\* USER CODE BEGIN 1 \*/\),\1\n my_setup_1();\n,' \
|
||||
-e 's,\(/\* USER CODE BEGIN 2 \*/\),\1\n my_setup_2();\n,' \
|
||||
-e 's,\(/\* USER CODE BEGIN 3 \*/\),\1\n my_loop();\n,' \
|
||||
-e 's,\(/\* USER CODE BEGIN Error_Handler_Debug \*/\),\1\n my_errorHandler();\n,' \
|
||||
-e 's,\(/\* USER CODE END Error_Handler_Debug \*/\),\1\n while(1) { };\n,' \
|
||||
>> $MAIN_C
|
||||
|
||||
cp $IT_C $IT_C_BAK
|
||||
echo "// $PROCESSED" > $IT_C
|
||||
cat $IT_C_BAK | \
|
||||
sed -e 's,\(/\* USER CODE BEGIN Includes \*/\),\1\n#include "main2.h"\n,' \
|
||||
-e 's,\(/\* USER CODE BEGIN SysTick_IRQn 1 \*/\),\1\n SYSTICK_Callback();\n,' \
|
||||
>> $IT_C
|
||||
|
||||
|
||||
|
||||
SRC_EXT=''
|
||||
for I in User/Src/*.c; do
|
||||
SRC_EXT+="$I "
|
||||
done
|
||||
for I in hottislib/*.c; do
|
||||
SRC_EXT+="$I "
|
||||
done
|
||||
|
||||
cp $MAKEFILE $MAKEFILE_BAK
|
||||
echo "# $PROCESSED" > $MAKEFILE
|
||||
cat $MAKEFILE_BAK | \
|
||||
sed -e 's/\(-specs=nano.specs\)/\1 -u _printf_float/' \
|
||||
-e 's/\(-Wall\)/\1 -Werror/' \
|
||||
-e 's%\(# list of ASM program objects\)%OBJECTS += $(addprefix $(BUILD_DIR)/,w5500.a pubsubc.a)\n\1%' \
|
||||
-e 's,\($(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)\),$(BUILD_DIR)/w5500.a:\n\t(cd ioLibrary_Driver \&\& $(MAKE) \&\& cp w5500.a ../$(BUILD_DIR) \&\& cd ..)\n\n\1,' \
|
||||
-e 's,\(C_SOURCES = \\\),\1\n'"$SRC_EXT"' \\,' \
|
||||
-e 's,\(C_INCLUDES = \\\),\1\n-IioLibrary_Driver/Ethernet \\,' \
|
||||
-e 's,\(C_INCLUDES = \\\),\1\n-IioLibrary_Driver/Internet/DHCP \\,' \
|
||||
-e 's,\(C_INCLUDES = \\\),\1\n-IioLibrary_Driver/Internet/DNS \\,' \
|
||||
-e 's,\(C_INCLUDES = \\\),\1\n-IUser/Inc \\,' \
|
||||
-e 's,\(C_INCLUDES = \\\),\1\n-Ihottislib \\,' \
|
||||
>> $MAKEFILE
|
||||
|
||||
|
||||
|
||||
|
||||
|
3
tools/removeGeneratedCode.sh
Executable file
3
tools/removeGeneratedCode.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -rf build/ Core/ Drivers/ Makefile Makefile-bak startup_stm32f103xe.s STM32F103VCTx_FLASH.ld
|
1
tools/startBuildEnv.ps1
Normal file
1
tools/startBuildEnv.ps1
Normal file
@ -0,0 +1 @@
|
||||
docker run -it --rm -v ${PWD}:/mnt wollud1969/build-env-arm-none-eabi:1.1.0 bash
|
3
tools/startBuildEnv.sh
Executable file
3
tools/startBuildEnv.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker run -it --rm -u ${UID} -v ${PWD}:/mnt wollud1969/build-env-arm-none-eabi:1.1.0 bash
|
32
tools/startCompleteEnv.sh
Executable file
32
tools/startCompleteEnv.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
SESSIONNAME=mbusmaster-dev
|
||||
|
||||
screen -d -m -S $SESSIONNAME
|
||||
screen -S $SESSIONNAME -p 0 -X title main
|
||||
|
||||
screen -S $SESSIONNAME -X screen 1
|
||||
screen -S $SESSIONNAME -p 1 -X title build
|
||||
screen -S $SESSIONNAME -p 1 -X exec ./tools/startBuildEnv.sh
|
||||
|
||||
screen -S $SESSIONNAME -X screen 2
|
||||
screen -S $SESSIONNAME -p 2 -X title test
|
||||
screen -S $SESSIONNAME -p 2 -X exec ./tools/startTestEnv.sh
|
||||
|
||||
screen -S $SESSIONNAME -X screen 3
|
||||
screen -S $SESSIONNAME -p 3 -X title minicom
|
||||
screen -S $SESSIONNAME -p 3 -X exec minicom
|
||||
|
||||
screen -S $SESSIONNAME -X screen 4
|
||||
screen -S $SESSIONNAME -p 4 -X title openocd
|
||||
screen -S $SESSIONNAME -p 4 -X exec openocd -f ./openocd.cfg
|
||||
|
||||
screen -S $SESSIONNAME -X screen 5
|
||||
screen -S $SESSIONNAME -p 5 -X title upload
|
||||
|
||||
screen -S $SESSIONNAME -X screen 6
|
||||
screen -S $SESSIONNAME -p 6 -X title edit
|
||||
screen -S $SESSIONNAME -p 6 -X chdir ./cube
|
||||
|
||||
screen -r $SESSIONNAME
|
||||
|
1
tools/startTestEnv.ps1
Normal file
1
tools/startTestEnv.ps1
Normal file
@ -0,0 +1 @@
|
||||
docker run -it --rm -v ${PWD}:/work wollud1969/build-env-c:1.2.0 bash
|
3
tools/startTestEnv.sh
Executable file
3
tools/startTestEnv.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker run -it --rm -u ${UID} -v ${PWD}:/work wollud1969/build-env-c:1.2.0 bash
|
8
tools/upload.sh
Executable file
8
tools/upload.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
cat << EOF | nc localhost 4444
|
||||
reset halt
|
||||
flash write_image erase /home/wn/Workspaces/mbusgateway3variant/cube/build/cube.elf
|
||||
reset run
|
||||
exit
|
||||
EOF
|
Loading…
x
Reference in New Issue
Block a user