Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# set the project name
|
||||
project(umwc_comms VERSION 0.1)
|
||||
# specify the C++ standard
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
# add the executable
|
||||
add_library(umwc_comms STATIC)
|
||||
ev_register_library_target(umwc_comms)
|
||||
|
||||
target_sources(umwc_comms
|
||||
PRIVATE
|
||||
evSerial.cpp
|
||||
protobuf/umwc.pb.c
|
||||
)
|
||||
|
||||
target_include_directories(umwc_comms
|
||||
PUBLIC
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
protobuf
|
||||
)
|
||||
|
||||
target_link_libraries(umwc_comms
|
||||
PUBLIC
|
||||
date::date-tz
|
||||
everest::nanopb
|
||||
PRIVATE
|
||||
Pal::Sigslot
|
||||
everest::framework
|
||||
everest::gpio
|
||||
)
|
||||
@@ -0,0 +1,413 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest
|
||||
#include "evSerial.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <date/date.h>
|
||||
#include <date/tz.h>
|
||||
|
||||
#include <everest/3rd_party/nanopb/pb_decode.h>
|
||||
#include <everest/3rd_party/nanopb/pb_encode.h>
|
||||
|
||||
#include <everest/gpio/gpio.hpp>
|
||||
|
||||
#include "umwc.pb.h"
|
||||
|
||||
evSerial::evSerial() {
|
||||
fd = 0;
|
||||
baud = 0;
|
||||
reset_done_flag = false;
|
||||
forced_reset = false;
|
||||
cobsDecodeReset();
|
||||
}
|
||||
|
||||
evSerial::~evSerial() {
|
||||
if (fd)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
bool evSerial::openDevice(const char* device, int _baud) {
|
||||
|
||||
fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);
|
||||
if (fd < 0) {
|
||||
printf("Serial: error %d opening %s: %s\n", errno, device, strerror(errno));
|
||||
return false;
|
||||
} // else printf ("Serial: opened %s as %i\n", device, fd);
|
||||
cobsDecodeReset();
|
||||
|
||||
switch (_baud) {
|
||||
case 9600:
|
||||
baud = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
baud = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
baud = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
baud = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
baud = B115200;
|
||||
break;
|
||||
case 230400:
|
||||
baud = B230400;
|
||||
break;
|
||||
default:
|
||||
baud = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return setSerialAttributes();
|
||||
}
|
||||
|
||||
bool evSerial::setSerialAttributes() {
|
||||
struct termios tty;
|
||||
if (tcgetattr(fd, &tty) != 0) {
|
||||
printf("Serial: error %d from tcgetattr\n", errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
cfsetospeed(&tty, baud);
|
||||
cfsetispeed(&tty, baud);
|
||||
|
||||
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
||||
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
||||
// as \000 chars
|
||||
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
|
||||
tty.c_lflag = 0; // no signaling chars, no echo,
|
||||
// no canonical processing
|
||||
tty.c_oflag = 0; // no remapping, no delays
|
||||
tty.c_cc[VMIN] = 0; // read blocks
|
||||
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||||
|
||||
tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
|
||||
// enable reading
|
||||
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
|
||||
tty.c_cflag &= ~CSTOPB;
|
||||
tty.c_cflag &= ~CRTSCTS;
|
||||
|
||||
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
|
||||
printf("Serial: error %d from tcsetattr\n", errno);
|
||||
return false;
|
||||
}
|
||||
// printf ("Success setting tcsetattr\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void evSerial::cobsDecodeReset() {
|
||||
code = 0xff;
|
||||
block = 0;
|
||||
decode = msg;
|
||||
}
|
||||
|
||||
uint32_t evSerial::crc32(uint8_t* buf, int len) {
|
||||
int i, j;
|
||||
uint32_t crc, msk;
|
||||
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
while (i < len) {
|
||||
uint32_t b = buf[i];
|
||||
crc = crc ^ b;
|
||||
for (j = 7; j >= 0; j--) {
|
||||
msk = -(crc & 1);
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & msk);
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
// printf("%X",crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
void evSerial::handlePacket(uint8_t* buf, int len) {
|
||||
// printf ("packet received len %u\n", len);
|
||||
|
||||
// Check CRC32 (last 4 bytes)
|
||||
if (crc32(buf, len)) {
|
||||
printf("CRC mismatch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
len -= 4;
|
||||
|
||||
McuToEverest msg_in;
|
||||
pb_istream_t istream = pb_istream_from_buffer(buf, len);
|
||||
|
||||
if (pb_decode(&istream, McuToEverest_fields, &msg_in))
|
||||
switch (msg_in.which_payload) {
|
||||
|
||||
case McuToEverest_keep_alive_tag:
|
||||
// printf("Received keep_alive_lo\n");
|
||||
signalKeepAliveLo(msg_in.payload.keep_alive);
|
||||
// detect connection timeout if keep_alive packets stop coming...
|
||||
last_keep_alive_lo_timestamp = date::utc_clock::now();
|
||||
break;
|
||||
case McuToEverest_telemetry_tag:
|
||||
/*printf("Received telemetry cp_hi %f cp_lo %f relais_on %i pwm_dc %f\n", msg_in.payload.telemetry.cp_hi,
|
||||
msg_in.payload.telemetry.cp_lo, (int)msg_in.payload.telemetry.relais_on,
|
||||
msg_in.payload.telemetry.pwm_dc);*/
|
||||
signalTelemetry(msg_in.payload.telemetry);
|
||||
break;
|
||||
case McuToEverest_cp_state_tag:
|
||||
signalCPState(msg_in.payload.cp_state);
|
||||
break;
|
||||
case McuToEverest_relais_state_tag:
|
||||
signalRelaisState(msg_in.payload.relais_state);
|
||||
break;
|
||||
case McuToEverest_error_flags_tag:
|
||||
signalErrorFlags(msg_in.payload.error_flags);
|
||||
break;
|
||||
case McuToEverest_reset_tag:
|
||||
// printf("Received reset_done\n");
|
||||
reset_done_flag = true;
|
||||
if (!forced_reset)
|
||||
signalSpuriousReset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void evSerial::cobsDecode(uint8_t* buf, int len) {
|
||||
for (int i = 0; i < len; i++)
|
||||
cobsDecodeByte(buf[i]);
|
||||
}
|
||||
|
||||
void evSerial::cobsDecodeByte(uint8_t byte) {
|
||||
// check max length
|
||||
if ((decode - msg == 2048 - 1) && byte != 0x00) {
|
||||
printf("cobsDecode: Buffer overflow\n");
|
||||
cobsDecodeReset();
|
||||
}
|
||||
|
||||
if (block) {
|
||||
// we're currently decoding and should not get a 0
|
||||
if (byte == 0x00) {
|
||||
// probably found some garbage -> reset
|
||||
printf("cobsDecode: Garbage detected\n");
|
||||
cobsDecodeReset();
|
||||
return;
|
||||
}
|
||||
*decode++ = byte;
|
||||
} else {
|
||||
if (code != 0xff) {
|
||||
*decode++ = 0;
|
||||
}
|
||||
block = code = byte;
|
||||
if (code == 0x00) {
|
||||
// we're finished, reset everything and commit
|
||||
if (decode == msg) {
|
||||
// we received nothing, just a 0x00
|
||||
printf("cobsDecode: Received nothing\n");
|
||||
} else {
|
||||
// set back decode with one, as it gets post-incremented
|
||||
handlePacket(msg, decode - 1 - msg);
|
||||
}
|
||||
cobsDecodeReset();
|
||||
return; // need to return here, because of block--
|
||||
}
|
||||
}
|
||||
block--;
|
||||
}
|
||||
|
||||
void evSerial::run() {
|
||||
readThreadHandle = std::thread(&evSerial::readThread, this);
|
||||
timeoutDetectionThreadHandle = std::thread(&evSerial::timeoutDetectionThread, this);
|
||||
}
|
||||
|
||||
void evSerial::timeoutDetectionThread() {
|
||||
while (true) {
|
||||
sleep(1);
|
||||
if (timeoutDetectionThreadHandle.shouldExit())
|
||||
break;
|
||||
if (serial_timed_out())
|
||||
signalConnectionTimeout();
|
||||
// send keep alive to LO
|
||||
keepAlive();
|
||||
}
|
||||
}
|
||||
|
||||
void evSerial::readThread() {
|
||||
uint8_t buf[2048];
|
||||
|
||||
cobsDecodeReset();
|
||||
while (true) {
|
||||
if (readThreadHandle.shouldExit())
|
||||
break;
|
||||
if (fd > 0) {
|
||||
int n = read(fd, buf, sizeof buf);
|
||||
cobsDecode(buf, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool evSerial::linkWrite(EverestToMcu* m) {
|
||||
if (fd <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t tx_packet_buf[1024];
|
||||
uint8_t encode_buf[1500];
|
||||
pb_ostream_t ostream = pb_ostream_from_buffer(tx_packet_buf, sizeof(tx_packet_buf) - 4);
|
||||
bool status = pb_encode(&ostream, EverestToMcu_fields, m);
|
||||
|
||||
if (!status) {
|
||||
// couldn't encode
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t tx_payload_len = ostream.bytes_written;
|
||||
|
||||
// add crc32 (CRC-32/JAMCRC)
|
||||
uint32_t crc = crc32(tx_packet_buf, tx_payload_len);
|
||||
|
||||
for (int byte_pos = 0; byte_pos < 4; ++byte_pos) {
|
||||
tx_packet_buf[tx_payload_len] = (uint8_t)crc & 0xFF;
|
||||
crc = crc >> 8;
|
||||
tx_payload_len++;
|
||||
}
|
||||
|
||||
size_t tx_encode_len = cobsEncode(tx_packet_buf, tx_payload_len, encode_buf);
|
||||
// std::cout << "Write "<<tx_encode_len<<" bytes to serial port." << std::endl;
|
||||
write(fd, encode_buf, tx_encode_len);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t evSerial::cobsEncode(const void* data, size_t length, uint8_t* buffer) {
|
||||
uint8_t* encode = buffer; // Encoded byte pointer
|
||||
uint8_t* codep = encode++; // Output code pointer
|
||||
uint8_t code = 1; // Code value
|
||||
|
||||
for (const uint8_t* byte = (const uint8_t*)data; length--; ++byte) {
|
||||
if (*byte) // Byte not zero, write it
|
||||
*encode++ = *byte, ++code;
|
||||
|
||||
if (!*byte || code == 0xff) // Input is zero or block completed, restart
|
||||
{
|
||||
*codep = code, code = 1, codep = encode;
|
||||
if (!*byte || length)
|
||||
++encode;
|
||||
}
|
||||
}
|
||||
*codep = code; // Write final code value
|
||||
|
||||
// add final 0
|
||||
*encode++ = 0x00;
|
||||
|
||||
return encode - buffer;
|
||||
}
|
||||
|
||||
bool evSerial::serial_timed_out() {
|
||||
auto now = date::utc_clock::now();
|
||||
auto timeSinceLastKeepAlive =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(now - last_keep_alive_lo_timestamp).count();
|
||||
if (timeSinceLastKeepAlive >= 5000)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void evSerial::setPWM(uint32_t dc) {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_pwm_duty_cycle_tag;
|
||||
msg_out.payload.pwm_duty_cycle = dc;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void evSerial::allowPowerOn(bool p) {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_allow_power_on_tag;
|
||||
msg_out.payload.allow_power_on = p;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void evSerial::enable(bool en) {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_enable_tag;
|
||||
msg_out.payload.enable = en;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void evSerial::replug() {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_replug_tag;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void evSerial::firmwareUpdate(bool rom) {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_firmware_update_tag;
|
||||
msg_out.payload.firmware_update.invoke_rom_bootloader = rom;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
void evSerial::setOutputVoltageCurrent(float v, float c) {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_set_output_voltage_current_tag;
|
||||
msg_out.payload.set_output_voltage_current.voltage = v;
|
||||
msg_out.payload.set_output_voltage_current.current = c;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
bool evSerial::reset(const std::string& reset_chip, const int reset_line) {
|
||||
|
||||
reset_done_flag = false;
|
||||
forced_reset = true;
|
||||
|
||||
if (not reset_chip.empty()) {
|
||||
// Try to hardware reset Yeti controller to be in a known state
|
||||
Everest::Gpio reset_gpio;
|
||||
reset_gpio.open(reset_chip, reset_line);
|
||||
reset_gpio.set_output(true);
|
||||
reset_gpio.set(true);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
reset_gpio.set(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
reset_gpio.set(true);
|
||||
} else {
|
||||
// Try to soft reset Yeti controller to be in a known state
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_reset_tag;
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Wait for reset done message from uC
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (reset_done_flag) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
// Reset flag to detect run time spurious resets of uC from now on
|
||||
reset_done_flag = false;
|
||||
forced_reset = false;
|
||||
|
||||
// send some dummy packets to resync COBS etc.
|
||||
keepAlive();
|
||||
keepAlive();
|
||||
keepAlive();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void evSerial::keepAlive() {
|
||||
EverestToMcu msg_out = EverestToMcu_init_default;
|
||||
msg_out.which_payload = EverestToMcu_keep_alive_tag;
|
||||
msg_out.payload.keep_alive.time_stamp = 0;
|
||||
msg_out.payload.keep_alive.hw_type = 0;
|
||||
msg_out.payload.keep_alive.hw_revision = 0;
|
||||
strcpy(msg_out.payload.keep_alive.sw_version_string, "n/a");
|
||||
linkWrite(&msg_out);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest
|
||||
#ifndef YETI_SERIAL
|
||||
#define YETI_SERIAL
|
||||
|
||||
#include "umwc.pb.h"
|
||||
#include <date/date.h>
|
||||
#include <date/tz.h>
|
||||
#include <sigslot/signal.hpp>
|
||||
#include <stdint.h>
|
||||
#include <termios.h>
|
||||
#include <utils/thread.hpp>
|
||||
|
||||
class evSerial {
|
||||
|
||||
public:
|
||||
evSerial();
|
||||
~evSerial();
|
||||
|
||||
bool openDevice(const char* device, int baud);
|
||||
bool is_open() {
|
||||
return fd > 0;
|
||||
};
|
||||
|
||||
void readThread();
|
||||
void run();
|
||||
|
||||
void enable(bool en);
|
||||
void disable();
|
||||
void replug();
|
||||
bool reset(const std::string& reset_chip, const int reset_line);
|
||||
void firmwareUpdate(bool rom);
|
||||
void keepAlive();
|
||||
|
||||
void setPWM(uint32_t dc);
|
||||
void allowPowerOn(bool p);
|
||||
|
||||
void setOutputVoltageCurrent(float v, float c);
|
||||
|
||||
sigslot::signal<KeepAliveLo> signalKeepAliveLo;
|
||||
sigslot::signal<Telemetry> signalTelemetry;
|
||||
|
||||
sigslot::signal<CpState> signalCPState;
|
||||
sigslot::signal<ErrorFlags> signalErrorFlags;
|
||||
sigslot::signal<bool> signalRelaisState;
|
||||
|
||||
sigslot::signal<> signalSpuriousReset;
|
||||
sigslot::signal<> signalConnectionTimeout;
|
||||
|
||||
private:
|
||||
// Serial interface
|
||||
bool setSerialAttributes();
|
||||
int fd;
|
||||
int baud;
|
||||
|
||||
// COBS de-/encoder
|
||||
void cobsDecodeReset();
|
||||
void handlePacket(uint8_t* buf, int len);
|
||||
void cobsDecode(uint8_t* buf, int len);
|
||||
void cobsDecodeByte(uint8_t byte);
|
||||
size_t cobsEncode(const void* data, size_t length, uint8_t* buffer);
|
||||
uint8_t msg[2048];
|
||||
uint8_t code;
|
||||
uint8_t block;
|
||||
uint8_t* decode;
|
||||
uint32_t crc32(uint8_t* buf, int len);
|
||||
|
||||
// Read thread for serial port
|
||||
Everest::Thread readThreadHandle;
|
||||
Everest::Thread timeoutDetectionThreadHandle;
|
||||
|
||||
bool linkWrite(EverestToMcu* m);
|
||||
volatile bool reset_done_flag;
|
||||
volatile bool forced_reset;
|
||||
|
||||
bool serial_timed_out();
|
||||
void timeoutDetectionThread();
|
||||
std::chrono::time_point<date::utc_clock> last_keep_alive_lo_timestamp;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
nanopb_generator.py -L "#include <everest/3rd_party/nanopb/%s>" -I . -D . umwc.proto
|
||||
@@ -0,0 +1,2 @@
|
||||
KeepAlive.sw_version_string max_length:50
|
||||
KeepAliveLo.sw_version_string max_length:50
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.8 */
|
||||
|
||||
#include "umwc.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(EverestToMcu, EverestToMcu, 2)
|
||||
|
||||
|
||||
PB_BIND(McuToEverest, McuToEverest, 2)
|
||||
|
||||
|
||||
PB_BIND(SetOutputVoltageCurrent, SetOutputVoltageCurrent, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ErrorFlags, ErrorFlags, AUTO)
|
||||
|
||||
|
||||
PB_BIND(KeepAliveLo, KeepAliveLo, AUTO)
|
||||
|
||||
|
||||
PB_BIND(KeepAlive, KeepAlive, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Telemetry, Telemetry, AUTO)
|
||||
|
||||
|
||||
PB_BIND(FirmwareUpdate, FirmwareUpdate, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.8 */
|
||||
|
||||
#ifndef PB_UMWC_PB_H_INCLUDED
|
||||
#define PB_UMWC_PB_H_INCLUDED
|
||||
#include <everest/3rd_party/nanopb/pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _CpState {
|
||||
CpState_STATE_A = 0,
|
||||
CpState_STATE_B = 1,
|
||||
CpState_STATE_C = 2,
|
||||
CpState_STATE_D = 3,
|
||||
CpState_STATE_E = 4,
|
||||
CpState_STATE_F = 5
|
||||
} CpState;
|
||||
|
||||
typedef enum _ResetReason {
|
||||
ResetReason_USER = 0,
|
||||
ResetReason_WATCHDOG = 1
|
||||
} ResetReason;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _SetOutputVoltageCurrent {
|
||||
float voltage;
|
||||
float current;
|
||||
} SetOutputVoltageCurrent;
|
||||
|
||||
typedef struct _ErrorFlags {
|
||||
bool diode_fault;
|
||||
bool cp_signal_fault;
|
||||
} ErrorFlags;
|
||||
|
||||
typedef struct _KeepAliveLo {
|
||||
uint32_t time_stamp;
|
||||
uint32_t hw_type;
|
||||
uint32_t hw_revision;
|
||||
uint32_t protocol_version_major;
|
||||
uint32_t protocol_version_minor;
|
||||
char sw_version_string[51];
|
||||
float hwcap_max_current;
|
||||
float hwcap_min_current;
|
||||
uint32_t hwcap_max_phase_count;
|
||||
uint32_t hwcap_min_phase_count;
|
||||
bool supports_changing_phases_during_charging;
|
||||
} KeepAliveLo;
|
||||
|
||||
typedef struct _KeepAlive {
|
||||
uint32_t time_stamp;
|
||||
uint32_t hw_type;
|
||||
uint32_t hw_revision;
|
||||
char sw_version_string[51];
|
||||
} KeepAlive;
|
||||
|
||||
typedef struct _Telemetry {
|
||||
float cp_hi;
|
||||
float cp_lo;
|
||||
float pwm_dc;
|
||||
float relais_on;
|
||||
float voltage;
|
||||
} Telemetry;
|
||||
|
||||
/* This container message is send from MCU to EVerest and may contain any allowed message in that direction. */
|
||||
typedef struct _McuToEverest {
|
||||
pb_size_t which_payload;
|
||||
union {
|
||||
/* Needs to remain the same to allow firmware updates of older versions */
|
||||
KeepAliveLo keep_alive;
|
||||
/* Other IDs are 100+ to avoid compatibility issues with older firmware versions */
|
||||
ResetReason reset;
|
||||
CpState cp_state;
|
||||
bool relais_state; /* false: relais are off, true: relais are on */
|
||||
ErrorFlags error_flags;
|
||||
Telemetry telemetry;
|
||||
} payload;
|
||||
} McuToEverest;
|
||||
|
||||
typedef struct _FirmwareUpdate {
|
||||
bool invoke_rom_bootloader;
|
||||
} FirmwareUpdate;
|
||||
|
||||
/* This container message is send from EVerest to MCU and may contain any allowed message in that direction. */
|
||||
typedef struct _EverestToMcu {
|
||||
pb_size_t which_payload;
|
||||
union {
|
||||
/* Needs to remain the same to allow firmware updates of older versions */
|
||||
FirmwareUpdate firmware_update;
|
||||
SetOutputVoltageCurrent set_output_voltage_current;
|
||||
/* Other IDs are 100+ to avoid compatibility issues with older firmware versions */
|
||||
KeepAlive keep_alive;
|
||||
uint32_t pwm_duty_cycle; /* in 0.01 %, 0 = State F, 10000 = X1 */
|
||||
bool allow_power_on;
|
||||
bool reset;
|
||||
bool enable;
|
||||
bool replug;
|
||||
} payload;
|
||||
} EverestToMcu;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _CpState_MIN CpState_STATE_A
|
||||
#define _CpState_MAX CpState_STATE_F
|
||||
#define _CpState_ARRAYSIZE ((CpState)(CpState_STATE_F+1))
|
||||
|
||||
#define _ResetReason_MIN ResetReason_USER
|
||||
#define _ResetReason_MAX ResetReason_WATCHDOG
|
||||
#define _ResetReason_ARRAYSIZE ((ResetReason)(ResetReason_WATCHDOG+1))
|
||||
|
||||
|
||||
#define McuToEverest_payload_reset_ENUMTYPE ResetReason
|
||||
#define McuToEverest_payload_cp_state_ENUMTYPE CpState
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define EverestToMcu_init_default {0, {FirmwareUpdate_init_default}}
|
||||
#define McuToEverest_init_default {0, {KeepAliveLo_init_default}}
|
||||
#define SetOutputVoltageCurrent_init_default {0, 0}
|
||||
#define ErrorFlags_init_default {0, 0}
|
||||
#define KeepAliveLo_init_default {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0}
|
||||
#define KeepAlive_init_default {0, 0, 0, ""}
|
||||
#define Telemetry_init_default {0, 0, 0, 0, 0}
|
||||
#define FirmwareUpdate_init_default {0}
|
||||
#define EverestToMcu_init_zero {0, {FirmwareUpdate_init_zero}}
|
||||
#define McuToEverest_init_zero {0, {KeepAliveLo_init_zero}}
|
||||
#define SetOutputVoltageCurrent_init_zero {0, 0}
|
||||
#define ErrorFlags_init_zero {0, 0}
|
||||
#define KeepAliveLo_init_zero {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0}
|
||||
#define KeepAlive_init_zero {0, 0, 0, ""}
|
||||
#define Telemetry_init_zero {0, 0, 0, 0, 0}
|
||||
#define FirmwareUpdate_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define SetOutputVoltageCurrent_voltage_tag 1
|
||||
#define SetOutputVoltageCurrent_current_tag 2
|
||||
#define ErrorFlags_diode_fault_tag 1
|
||||
#define ErrorFlags_cp_signal_fault_tag 6
|
||||
#define KeepAliveLo_time_stamp_tag 1
|
||||
#define KeepAliveLo_hw_type_tag 2
|
||||
#define KeepAliveLo_hw_revision_tag 3
|
||||
#define KeepAliveLo_protocol_version_major_tag 4
|
||||
#define KeepAliveLo_protocol_version_minor_tag 5
|
||||
#define KeepAliveLo_sw_version_string_tag 6
|
||||
#define KeepAliveLo_hwcap_max_current_tag 7
|
||||
#define KeepAliveLo_hwcap_min_current_tag 8
|
||||
#define KeepAliveLo_hwcap_max_phase_count_tag 9
|
||||
#define KeepAliveLo_hwcap_min_phase_count_tag 10
|
||||
#define KeepAliveLo_supports_changing_phases_during_charging_tag 11
|
||||
#define KeepAlive_time_stamp_tag 1
|
||||
#define KeepAlive_hw_type_tag 2
|
||||
#define KeepAlive_hw_revision_tag 3
|
||||
#define KeepAlive_sw_version_string_tag 6
|
||||
#define Telemetry_cp_hi_tag 1
|
||||
#define Telemetry_cp_lo_tag 2
|
||||
#define Telemetry_pwm_dc_tag 3
|
||||
#define Telemetry_relais_on_tag 4
|
||||
#define Telemetry_voltage_tag 5
|
||||
#define McuToEverest_keep_alive_tag 3
|
||||
#define McuToEverest_reset_tag 101
|
||||
#define McuToEverest_cp_state_tag 102
|
||||
#define McuToEverest_relais_state_tag 103
|
||||
#define McuToEverest_error_flags_tag 104
|
||||
#define McuToEverest_telemetry_tag 105
|
||||
#define FirmwareUpdate_invoke_rom_bootloader_tag 1
|
||||
#define EverestToMcu_firmware_update_tag 16
|
||||
#define EverestToMcu_set_output_voltage_current_tag 50
|
||||
#define EverestToMcu_keep_alive_tag 100
|
||||
#define EverestToMcu_pwm_duty_cycle_tag 103
|
||||
#define EverestToMcu_allow_power_on_tag 104
|
||||
#define EverestToMcu_reset_tag 105
|
||||
#define EverestToMcu_enable_tag 106
|
||||
#define EverestToMcu_replug_tag 107
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define EverestToMcu_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,firmware_update,payload.firmware_update), 16) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,set_output_voltage_current,payload.set_output_voltage_current), 50) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 100) \
|
||||
X(a, STATIC, ONEOF, UINT32, (payload,pwm_duty_cycle,payload.pwm_duty_cycle), 103) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload,allow_power_on,payload.allow_power_on), 104) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload,reset,payload.reset), 105) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload,enable,payload.enable), 106) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload,replug,payload.replug), 107)
|
||||
#define EverestToMcu_CALLBACK NULL
|
||||
#define EverestToMcu_DEFAULT NULL
|
||||
#define EverestToMcu_payload_firmware_update_MSGTYPE FirmwareUpdate
|
||||
#define EverestToMcu_payload_set_output_voltage_current_MSGTYPE SetOutputVoltageCurrent
|
||||
#define EverestToMcu_payload_keep_alive_MSGTYPE KeepAlive
|
||||
|
||||
#define McuToEverest_FIELDLIST(X, a) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 3) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload,reset,payload.reset), 101) \
|
||||
X(a, STATIC, ONEOF, UENUM, (payload,cp_state,payload.cp_state), 102) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payload,relais_state,payload.relais_state), 103) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,error_flags,payload.error_flags), 104) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payload,telemetry,payload.telemetry), 105)
|
||||
#define McuToEverest_CALLBACK NULL
|
||||
#define McuToEverest_DEFAULT NULL
|
||||
#define McuToEverest_payload_keep_alive_MSGTYPE KeepAliveLo
|
||||
#define McuToEverest_payload_error_flags_MSGTYPE ErrorFlags
|
||||
#define McuToEverest_payload_telemetry_MSGTYPE Telemetry
|
||||
|
||||
#define SetOutputVoltageCurrent_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, voltage, 1) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, current, 2)
|
||||
#define SetOutputVoltageCurrent_CALLBACK NULL
|
||||
#define SetOutputVoltageCurrent_DEFAULT NULL
|
||||
|
||||
#define ErrorFlags_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, diode_fault, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, cp_signal_fault, 6)
|
||||
#define ErrorFlags_CALLBACK NULL
|
||||
#define ErrorFlags_DEFAULT NULL
|
||||
|
||||
#define KeepAliveLo_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \
|
||||
X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, hwcap_max_current, 7) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, hwcap_min_current, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hwcap_max_phase_count, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hwcap_min_phase_count, 10) \
|
||||
X(a, STATIC, SINGULAR, BOOL, supports_changing_phases_during_charging, 11)
|
||||
#define KeepAliveLo_CALLBACK NULL
|
||||
#define KeepAliveLo_DEFAULT NULL
|
||||
|
||||
#define KeepAlive_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \
|
||||
X(a, STATIC, SINGULAR, STRING, sw_version_string, 6)
|
||||
#define KeepAlive_CALLBACK NULL
|
||||
#define KeepAlive_DEFAULT NULL
|
||||
|
||||
#define Telemetry_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, cp_hi, 1) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, cp_lo, 2) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, pwm_dc, 3) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, relais_on, 4) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, voltage, 5)
|
||||
#define Telemetry_CALLBACK NULL
|
||||
#define Telemetry_DEFAULT NULL
|
||||
|
||||
#define FirmwareUpdate_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, invoke_rom_bootloader, 1)
|
||||
#define FirmwareUpdate_CALLBACK NULL
|
||||
#define FirmwareUpdate_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t EverestToMcu_msg;
|
||||
extern const pb_msgdesc_t McuToEverest_msg;
|
||||
extern const pb_msgdesc_t SetOutputVoltageCurrent_msg;
|
||||
extern const pb_msgdesc_t ErrorFlags_msg;
|
||||
extern const pb_msgdesc_t KeepAliveLo_msg;
|
||||
extern const pb_msgdesc_t KeepAlive_msg;
|
||||
extern const pb_msgdesc_t Telemetry_msg;
|
||||
extern const pb_msgdesc_t FirmwareUpdate_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define EverestToMcu_fields &EverestToMcu_msg
|
||||
#define McuToEverest_fields &McuToEverest_msg
|
||||
#define SetOutputVoltageCurrent_fields &SetOutputVoltageCurrent_msg
|
||||
#define ErrorFlags_fields &ErrorFlags_msg
|
||||
#define KeepAliveLo_fields &KeepAliveLo_msg
|
||||
#define KeepAlive_fields &KeepAlive_msg
|
||||
#define Telemetry_fields &Telemetry_msg
|
||||
#define FirmwareUpdate_fields &FirmwareUpdate_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ErrorFlags_size 4
|
||||
#define EverestToMcu_size 73
|
||||
#define FirmwareUpdate_size 2
|
||||
#define KeepAliveLo_size 106
|
||||
#define KeepAlive_size 70
|
||||
#define McuToEverest_size 108
|
||||
#define SetOutputVoltageCurrent_size 10
|
||||
#define Telemetry_size 25
|
||||
#define UMWC_PB_H_MAX_SIZE McuToEverest_size
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,95 @@
|
||||
syntax = "proto3";
|
||||
|
||||
/*
|
||||
This container message is send from EVerest to MCU and may contain any allowed message in that direction.
|
||||
*/
|
||||
message EverestToMcu {
|
||||
oneof payload {
|
||||
// Needs to remain the same to allow firmware updates of older versions
|
||||
FirmwareUpdate firmware_update = 16;
|
||||
|
||||
SetOutputVoltageCurrent set_output_voltage_current = 50;
|
||||
|
||||
// Other IDs are 100+ to avoid compatibility issues with older firmware versions
|
||||
KeepAlive keep_alive = 100;
|
||||
uint32 pwm_duty_cycle = 103; // in 0.01 %, 0 = State F, 10000 = X1
|
||||
bool allow_power_on = 104;
|
||||
bool reset = 105;
|
||||
bool enable = 106;
|
||||
bool replug = 107;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This container message is send from MCU to EVerest and may contain any allowed message in that direction.
|
||||
*/
|
||||
message McuToEverest {
|
||||
oneof payload {
|
||||
// Needs to remain the same to allow firmware updates of older versions
|
||||
KeepAliveLo keep_alive = 3;
|
||||
|
||||
// Other IDs are 100+ to avoid compatibility issues with older firmware versions
|
||||
ResetReason reset = 101;
|
||||
CpState cp_state = 102;
|
||||
bool relais_state = 103; // false: relais are off, true: relais are on
|
||||
ErrorFlags error_flags = 104;
|
||||
Telemetry telemetry = 105;
|
||||
}
|
||||
}
|
||||
|
||||
enum CpState {
|
||||
STATE_A = 0;
|
||||
STATE_B = 1;
|
||||
STATE_C = 2;
|
||||
STATE_D = 3;
|
||||
STATE_E = 4;
|
||||
STATE_F = 5;
|
||||
}
|
||||
|
||||
message SetOutputVoltageCurrent {
|
||||
float voltage = 1;
|
||||
float current = 2;
|
||||
}
|
||||
|
||||
message ErrorFlags {
|
||||
bool diode_fault = 1;
|
||||
bool cp_signal_fault = 6;
|
||||
}
|
||||
|
||||
enum ResetReason {
|
||||
USER = 0;
|
||||
WATCHDOG = 1;
|
||||
}
|
||||
|
||||
message KeepAliveLo {
|
||||
uint32 time_stamp = 1;
|
||||
uint32 hw_type = 2;
|
||||
uint32 hw_revision = 3;
|
||||
uint32 protocol_version_major = 4;
|
||||
uint32 protocol_version_minor = 5;
|
||||
string sw_version_string = 6;
|
||||
float hwcap_max_current = 7;
|
||||
float hwcap_min_current = 8;
|
||||
uint32 hwcap_max_phase_count = 9;
|
||||
uint32 hwcap_min_phase_count = 10;
|
||||
bool supports_changing_phases_during_charging = 11;
|
||||
}
|
||||
|
||||
message KeepAlive {
|
||||
uint32 time_stamp = 1;
|
||||
uint32 hw_type = 2;
|
||||
uint32 hw_revision = 3;
|
||||
string sw_version_string = 6;
|
||||
}
|
||||
|
||||
message Telemetry {
|
||||
float cp_hi = 1;
|
||||
float cp_lo = 2;
|
||||
float pwm_dc = 3;
|
||||
float relais_on = 4;
|
||||
float voltage = 5;
|
||||
}
|
||||
|
||||
message FirmwareUpdate {
|
||||
bool invoke_rom_bootloader = 1;
|
||||
}
|
||||
Reference in New Issue
Block a user