diff --git a/Makefile b/Makefile index 0e6a479..7dcfedd 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: test test-root test-tempo build-v1 build-v2 build-hw1_0 build-hw1_1 build-hw1_3 build-all clean dist-clean +.PHONY: test test-root test-tempo build-v2 build-hw1_0 build-hw1_1 build-hw1_3 build-all clean dist-clean .DEFAULT_GOAL := test @@ -25,10 +25,6 @@ test-root: test-tempo: pio test -e native -d lib/tempo -build-v1: - pio run -e HW1_3 - $(call copy_uf2,HW1_3,1.0.0) - build-v2: pio run -e HW1_3_V2 $(call copy_uf2,HW1_3_V2,$(FIRMWARE_VERSION)) diff --git a/include/v1/AP33772_PocketPD.h b/include/v1/AP33772_PocketPD.h deleted file mode 100644 index 9703993..0000000 --- a/include/v1/AP33772_PocketPD.h +++ /dev/null @@ -1,204 +0,0 @@ -/* Structs and Resgister list ported from "AP33772 I2C Command Tester" by Joseph Liang - * Created 11 April 2022 - * Added class and class functions by VicentN for PicoPD evaluation board - */ -#ifndef __AP33772_POCKETPD__ -#define __AP33772_POCKETPD__ - -#include -#include - -#define CMD_SRCPDO 0x00 -#define CMD_PDONUM 0x1C -#define CMD_STATUS 0x1D -#define CMD_MASK 0x1E -#define CMD_VOLTAGE 0x20 -#define CMD_CURRENT 0x21 -#define CMD_TEMP 0x22 -#define CMD_OCPTHR 0x23 -#define CMD_OTPTHR 0x24 -#define CMD_DRTHR 0x25 -#define CMD_RDO 0x30 - -#define AP33772_ADDRESS 0x51 -#define READ_BUFF_LENGTH 30 -#define WRITE_BUFF_LENGTH 6 -#define SRCPDO_LENGTH 28 - -typedef enum -{ - READY_EN = 1 << 0, // 0000 0001 - SUCCESS_EN = 1 << 1, // 0000 0010 - NEWPDO_EN = 1 << 2, // 0000 0100 - OVP_EN = 1 << 4, // 0001 0000 - OCP_EN = 1 << 5, // 0010 0000 - OTP_EN = 1 << 6, // 0100 0000 - DR_EN = 1 << 7 // 1000 0000 -} AP33772_MASK; - -typedef struct -{ - union - { - struct - { - byte isReady : 1; - byte isSuccess : 1; - byte isNewpdo : 1; - byte reserved : 1; - byte isOvp : 1; - byte isOcp : 1; - byte isOtp : 1; - byte isDr : 1; - }; - byte readStatus; - }; - byte readVolt; // LSB: 80mV - byte readCurr; // LSB: 24mA - byte readTemp; // unit: 1C -} AP33772_STATUS_T; - -typedef struct -{ - union - { - struct - { - byte newNegoSuccess : 1; - byte newNegoFail : 1; - byte negoSuccess : 1; - byte negoFail : 1; - byte reserved_1 : 4; - }; - byte negoEvent; - }; - union - { - struct - { - byte ovp : 1; - byte ocp : 1; - byte otp : 1; - byte dr : 1; - byte reserved_2 : 4; - }; - byte protectEvent; - }; -} EVENT_FLAG_T; - -typedef struct -{ - union - { - struct - { - unsigned int maxCurrent : 10; // unit: 10mA - unsigned int voltage : 10; // unit: 50mV - unsigned int reserved_1 : 10; - unsigned int type : 2; - } fixed; - struct - { - unsigned int maxCurrent : 7; // unit: 50mA - unsigned int reserved_1 : 1; - unsigned int minVoltage : 8; // unit: 100mV - unsigned int reserved_2 : 1; - unsigned int maxVoltage : 8; // unit: 100mV - unsigned int reserved_3 : 3; - unsigned int apdo : 2; - unsigned int type : 2; - } pps; - struct - { - byte byte0; - byte byte1; - byte byte2; - byte byte3; - }; - unsigned long data; - }; -} PDO_DATA_T; - -typedef struct -{ - union - { - struct - { - unsigned int maxCurrent : 10; // unit: 10mA - unsigned int opCurrent : 10; // unit: 10mA - unsigned int reserved_1 : 8; - unsigned int objPosition : 3; - unsigned int reserved_2 : 1; - } fixed; - struct - { - unsigned int opCurrent : 7; // unit: 50mA - unsigned int reserved_1 : 2; - unsigned int voltage : 11; // unit: 20mV - unsigned int reserved_2 : 8; - unsigned int objPosition : 3; - unsigned int reserved_3 : 1; - } pps; - struct - { - byte byte0; - byte byte1; - byte byte2; - byte byte3; - }; - unsigned long data; - }; -} RDO_DATA_T; - -class AP33772 -{ -public: - AP33772(TwoWire &wire = Wire); - void begin(); - void setVoltage(int targetVoltage); // Unit in mV - void setPDO(uint8_t PDOindex); - void setMaxCurrent(int targetMaxCurrent); // Unit in mA - void setNTC(int TR25, int TR50, int TR75, int TR100); - void setDeratingTemp(int temperature); - void setMask(AP33772_MASK flag); - void clearMask(AP33772_MASK flag); - void writeRDO(); - int readVoltage(); - int readCurrent(); - int getMaxCurrent() const; - int readTemp(); - void printPDO(); - void reset(); - - int getNumPDO(); - int getPPSIndex(); - int getPDOMaxcurrent(uint8_t PDOindex); - int getPDOVoltage(uint8_t PDOindex); - int getPPSMinVoltage(uint8_t PPSindex); - int getPPSMaxVoltage(uint8_t PPSindex); - int getPPSMaxCurrent(uint8_t PPSindex); - void setSupplyVoltageCurrent(int targetVoltage, int targetCurrent); - byte existPPS = 0; // PPS flag for setVoltage() - - void checkVoltageCurrent(int &targetVoltage, int &targetCurrent); - -private: - void i2c_read(byte slvAddr, byte cmdAddr, byte len); - void i2c_write(byte slvAddr, byte cmdAddr, byte len); - TwoWire *_i2cPort; - byte readBuf[READ_BUFF_LENGTH] = {0}; - byte writeBuf[WRITE_BUFF_LENGTH] = {0}; - byte numPDO = 0; // source PDO number - byte indexPDO = 0; // PDO index, start from index 0 - int reqPpsVolt = 0; // requested PPS voltage, unit:20mV - - int8_t PPSindex = 8; - - AP33772_STATUS_T ap33772_status = {0}; - EVENT_FLAG_T event_flag = {0}; - RDO_DATA_T rdoData = {0}; - PDO_DATA_T pdoData[7] = {0}; -}; - -#endif diff --git a/include/v1/Button.h b/include/v1/Button.h deleted file mode 100644 index 392a49d..0000000 --- a/include/v1/Button.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Implement long press detection using ezButton library - */ - -#include - -#ifndef BUTTON_H -#define BUTTON_H - -class Button -{ -public: - int isButtonPressed(void); - Button(int buttonNum, int mode) : button(buttonNum, mode) { button.setDebounceTime(debounceTime); } - Button(int buttonNum) : button(buttonNum, INPUT_PULLUP) { button.setDebounceTime(debounceTime); } - void clearLongPressedFlag(void) { longPressedFlag = false; } // Call after a succesful long press trigger - void setDebounceTime(unsigned long time); - bool longPressedFlag = false; - void loop(); - -private: - ezButton button; - unsigned long pressedTime = 0; - unsigned long releasedTime = 0; - bool isPressing = false; - bool isLongDetected = false; - const int debounceTime = 50; // Set default debounce time to 50ms - const unsigned long SHORT_PRESS_TIME = 1000; // Short is less than 1s, more than 50ms - const unsigned long LONG_PRESS_TIME = 1500; // Long is longer than 1.5s -}; - -#endif \ No newline at end of file diff --git a/include/v1/Image.h b/include/v1/Image.h deleted file mode 100644 index d8c867a..0000000 --- a/include/v1/Image.h +++ /dev/null @@ -1,307 +0,0 @@ -#include - -#ifndef IMAGE_H -#define IMAGE_H - -static const unsigned char image_check_contour_bits[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0a,0x04,0x11,0x8a,0x08,0x51,0x04,0x22,0x02,0x04,0x01,0x88,0x00,0x50,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -static const unsigned char image_cross_contour_bits[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x01,0x8a,0x02,0x51,0x04,0x22,0x02,0x04,0x01,0x88,0x00,0x04,0x01,0x22,0x02,0x51,0x04,0x8a,0x02,0x04,0x01,0x00,0x00,0x00,0x00}; -// 'PocketPD_Logo', 128x64px -const unsigned char image_PocketPD_Logo [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0x80, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x9f, 0xf0, 0x3f, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x83, 0xff, 0xfe, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x3f, 0xf0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0xfe, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0xff, 0xc1, 0xff, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x0c, 0x00, 0x07, 0xff, 0xc1, 0xff, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x07, 0x80, 0x0c, 0x00, 0x07, 0x83, 0xe1, 0xe0, 0x3f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x07, 0x80, 0x0c, 0x00, 0x07, 0x81, 0xe1, 0xe0, 0x0f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x0c, 0x00, 0x07, 0x80, 0xf1, 0xe0, 0x07, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0xf1, 0xe0, 0x07, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0xf1, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x81, 0xe1, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x81, 0xe1, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0xff, 0xe1, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0xff, 0xc1, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0xff, 0x01, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0xf8, 0x01, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xe0, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xe0, 0x07, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xe0, 0x0f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xe0, 0x3f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x80, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - -// '_a_frm0,40', 20x20px -const unsigned char arrow_bitmap_a_frm0_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x60, 0x0c, 0x00, 0xc0, - 0x0c, 0x00, 0x80, 0x31, 0x00, 0x00, 0x33, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8c, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x33, 0x00, 0x80, 0x31, 0x00, 0xc0, 0x0c, 0x00, 0x60, 0x0c, 0x00, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm1,40', 20x20px -const unsigned char arrow_bitmap_a_frm1_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x98, 0x01, 0x00, 0x30, 0x03, 0x00, 0x30, - 0x02, 0x00, 0x60, 0x04, 0x00, 0xc0, 0x0c, 0x00, 0x80, 0x19, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, - 0x00, 0x80, 0x19, 0x00, 0xc0, 0x0c, 0x00, 0x60, 0x04, 0x00, 0x30, 0x02, 0x00, 0x30, 0x03, 0x00, - 0x98, 0x01, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm2,50', 20x20px -const unsigned char arrow_bitmap_a_frm2_50 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x64, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x98, - 0x01, 0x00, 0x30, 0x03, 0x00, 0x20, 0x03, 0x00, 0x40, 0x06, 0x00, 0xc0, 0x0c, 0x00, 0xc0, 0x0c, - 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x00, 0x30, 0x03, 0x00, 0x98, 0x01, 0x00, 0xcc, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm3,40', 20x20px -const unsigned char arrow_bitmap_a_frm3_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x6c, 0x00, 0x00, 0xc8, - 0x00, 0x00, 0x98, 0x01, 0x00, 0x30, 0x01, 0x00, 0x20, 0x03, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, - 0x00, 0x20, 0x03, 0x00, 0x30, 0x01, 0x00, 0x98, 0x01, 0x00, 0xc8, 0x00, 0x00, 0x6c, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm4,40', 20x20px -const unsigned char arrow_bitmap_a_frm4_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x64, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x98, - 0x01, 0x00, 0x30, 0x01, 0x00, 0x20, 0x03, 0x00, 0x40, 0x06, 0x00, 0xc0, 0x0c, 0x00, 0xc0, 0x0c, - 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x00, 0x30, 0x01, 0x00, 0x98, 0x01, 0x00, 0xcc, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm5,40', 20x20px -const unsigned char arrow_bitmap_a_frm5_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x98, 0x00, 0x00, 0x30, 0x01, 0x00, 0x30, - 0x03, 0x00, 0x40, 0x06, 0x00, 0xc0, 0x0c, 0x00, 0x80, 0x19, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, - 0x00, 0x80, 0x19, 0x00, 0xc0, 0x0c, 0x00, 0x40, 0x06, 0x00, 0x30, 0x03, 0x00, 0x30, 0x01, 0x00, - 0x98, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm6,40', 20x20px -const unsigned char arrow_bitmap_a_frm6_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x60, 0x06, 0x00, 0xc0, - 0x0c, 0x00, 0x80, 0x39, 0x00, 0x00, 0x33, 0x00, 0x00, 0xce, 0x00, 0x00, 0x98, 0x01, 0x00, 0x98, - 0x01, 0x00, 0xce, 0x00, 0x00, 0x33, 0x00, 0x80, 0x39, 0x00, 0xc0, 0x0c, 0x00, 0x60, 0x06, 0x00, - 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm7,40', 20x20px -const unsigned char arrow_bitmap_a_frm7_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x00, 0x80, - 0x33, 0x00, 0x00, 0xe6, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x30, 0x03, 0x00, 0x60, 0x0e, 0x00, 0x60, - 0x0e, 0x00, 0x30, 0x03, 0x00, 0xcc, 0x01, 0x00, 0xe6, 0x00, 0x80, 0x33, 0x00, 0xc0, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm8,50', 20x20px -const unsigned char arrow_bitmap_a_frm8_50 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x66, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0xcc, 0x01, 0x00, 0x66, 0x00, 0x00, 0x33, 0x00, - 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm9,40', 20x20px -const unsigned char arrow_bitmap_a_frm9_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x63, 0x00, 0x00, 0xc6, 0x00, 0x00, - 0x8c, 0x00, 0x00, 0x18, 0x01, 0x00, 0x30, 0x03, 0x00, 0x20, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x40, - 0x0c, 0x00, 0x60, 0x06, 0x00, 0x30, 0x03, 0x00, 0x18, 0x01, 0x00, 0x8c, 0x00, 0x00, 0xc6, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm10,40', 20x20px -const unsigned char arrow_bitmap_a_frm10_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x46, 0x00, 0x00, 0xcc, 0x00, 0x00, - 0x88, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x03, 0x00, 0x60, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x40, - 0x0c, 0x00, 0x60, 0x06, 0x00, 0x30, 0x03, 0x00, 0x18, 0x03, 0x00, 0x88, 0x01, 0x00, 0xcc, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm11,40', 20x20px -const unsigned char arrow_bitmap_a_frm11_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x63, 0x00, 0x00, 0xc6, 0x00, 0x00, - 0x8c, 0x00, 0x00, 0x18, 0x01, 0x00, 0x30, 0x03, 0x00, 0x60, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x40, - 0x0c, 0x00, 0x60, 0x06, 0x00, 0x30, 0x03, 0x00, 0x18, 0x01, 0x00, 0x8c, 0x00, 0x00, 0xc6, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm12,40', 20x20px -const unsigned char arrow_bitmap_a_frm12_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm13,40', 20x20px -const unsigned char arrow_bitmap_a_frm13_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm14,50', 20x20px -const unsigned char arrow_bitmap_a_frm14_50 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm15,40', 20x20px -const unsigned char arrow_bitmap_a_frm15_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm18,40', 20x20px -const unsigned char arrow_bitmap_a_frm18_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm19,40', 20x20px -const unsigned char arrow_bitmap_a_frm19_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm16,40', 20x20px -const unsigned char arrow_bitmap_a_frm16_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm17,40', 20x20px -const unsigned char arrow_bitmap_a_frm17_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm21,40', 20x20px -const unsigned char arrow_bitmap_a_frm21_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm20,50', 20x20px -const unsigned char arrow_bitmap_a_frm20_50 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm22,40', 20x20px -const unsigned char arrow_bitmap_a_frm22_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm23,40', 20x20px -const unsigned char arrow_bitmap_a_frm23_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm25,40', 20x20px -const unsigned char arrow_bitmap_a_frm25_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm24,40', 20x20px -const unsigned char arrow_bitmap_a_frm24_40 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, - 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x60, - 0x0c, 0x00, 0x30, 0x06, 0x00, 0x18, 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm26,50', 20x20px -const unsigned char arrow_bitmap_a_frm26_50 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x66, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x98, 0x01, 0x00, 0x30, 0x03, 0x00, 0x60, 0x06, 0x00, 0x60, - 0x06, 0x00, 0x30, 0x03, 0x00, 0x98, 0x01, 0x00, 0xcc, 0x00, 0x00, 0x66, 0x00, 0x00, 0x33, 0x00, - 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -// '_a_frm27,50', 20x20px -const unsigned char arrow_bitmap_a_frm27_50 [] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0c, 0x00, 0xc0, 0x18, 0x00, 0x80, - 0x31, 0x00, 0x00, 0x63, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x18, 0x03, 0x00, 0x18, - 0x03, 0x00, 0x8c, 0x01, 0x00, 0xc6, 0x00, 0x00, 0x63, 0x00, 0x80, 0x31, 0x00, 0xc0, 0x18, 0x00, - 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 2240) -const int arrow_bitmapallArray_LEN = 28; -static const unsigned char* arrow_bitmapallArray[28] = { - arrow_bitmap_a_frm0_40, - arrow_bitmap_a_frm1_40, - arrow_bitmap_a_frm2_50, - arrow_bitmap_a_frm3_40, - arrow_bitmap_a_frm4_40, - arrow_bitmap_a_frm5_40, - arrow_bitmap_a_frm6_40, - arrow_bitmap_a_frm7_40, - arrow_bitmap_a_frm8_50, - arrow_bitmap_a_frm9_40, - arrow_bitmap_a_frm10_40, - arrow_bitmap_a_frm11_40, - arrow_bitmap_a_frm12_40, - arrow_bitmap_a_frm13_40, - arrow_bitmap_a_frm14_50, - arrow_bitmap_a_frm15_40, - arrow_bitmap_a_frm16_40, - arrow_bitmap_a_frm17_40, - arrow_bitmap_a_frm18_40, - arrow_bitmap_a_frm19_40, - arrow_bitmap_a_frm20_50, - arrow_bitmap_a_frm21_40, - arrow_bitmap_a_frm22_40, - arrow_bitmap_a_frm23_40, - arrow_bitmap_a_frm24_40, - arrow_bitmap_a_frm25_40, - arrow_bitmap_a_frm26_50, - arrow_bitmap_a_frm27_50, -}; - -#endif \ No newline at end of file diff --git a/include/v1/Menu.h b/include/v1/Menu.h deleted file mode 100644 index 7aff13a..0000000 --- a/include/v1/Menu.h +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include - -#ifndef MENU_H -#define MENU_H - -/** - * Need to pass through - * u8g2 instance - * button and encoder detection for menu interaction - */ - -/** - * How do I build a menu list - * Ref code: https://github.com/shuzonudas/monoview/blob/master/U8g2/Examples/Menu/simpleMenu/simpleMenu.ino#L278 - */ - -class Menu -{ -public: - Menu(U8G2_SSD1306_128X64_NONAME_F_HW_I2C *oled, AP33772 *usb, RotaryEncoder *encoder, Button *button_encoder, Button *button_output, Button *button_selectVI); - uint8_t numPDO; // include both fixed PDO and PPS - int menuPosition; - // void get_numPDO(); - void set_qc3flag(bool flag); - void page_selectCapability(); - void page_bootProfile(); - void checkMenuPosition(bool wrapAround); // Check if menuPosition is within range, wrap around if not - -private: - U8G2_SSD1306_128X64_NONAME_F_HW_I2C *u8g2; - AP33772 *usbpd; - RotaryEncoder *_encoder; - Button *_button_encoder; - Button *_button_output; - Button *_button_selectVI; - - bool qc3_0available; -}; - -#endif \ No newline at end of file diff --git a/include/v1/StateMachine.h b/include/v1/StateMachine.h deleted file mode 100644 index 61a5ab2..0000000 --- a/include/v1/StateMachine.h +++ /dev/null @@ -1,175 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ALARM_NUM0 0 // Timer 0 -#define ALARM_IRQ0 TIMER_IRQ_0 -#define DELAY0 33000 // In usecond , 33ms, used for OLED update - -#define ALARM_NUM1 1 // Timer 1 -#define ALARM_IRQ1 TIMER_IRQ_1 -#define DELAY1 500000 // In usecond , 500ms, used for cursor - -enum class State -{ - BOOT, - OBTAIN, - CAPDISPLAY, - NORMAL_PPS, - NORMAL_PDO, - NORMAL_QC, - MENU -}; -enum Supply_Profile -{ - PROFILE_PPS, - PROFILE_PDO, - PROFILE_QC -}; -enum Supply_Mode -{ - MODE_CV, - MODE_CC -}; -enum Supply_Capability -{ - NON_PPS, - WITH_PPS -}; -enum Supply_Adjust_Mode -{ - VOTLAGE_ADJUST, - CURRENT_ADJUST -}; -enum Output_Display_Mode -{ - OUTPUT_NORMAL, - OUTPUT_ENERGY -}; - -#ifndef STATEMACHINE_H -#define STATEMACHINE_H - -class StateMachine -{ -public: - StateMachine() : ina226(0x40), - u8g2(U8G2_R0, U8X8_PIN_NONE), - state(State::BOOT), - startTime(millis()), - bootInitialized(false), - obtainInitialized(false), - displayCapInitialized(false), - normalPPSInitialized(false), - normalPDOInitialized(false), - normalQCInitialized(false), - button_encoder(pin_encoder_SW), - button_output(pin_button_outputSW), - button_selectVI(pin_button_selectVI), - supply_mode(MODE_CV), - voltageIncrement{20, 100, 1000}, - currentIncrement{50, 100, 1000}, - menu(&u8g2, &usbpd, &encoder, &button_encoder, &button_output, &button_selectVI), - eepromHandler(), - forceSave(false), - saveStamp(0) {}; - - void update(); - const char *getState(); - -private: - State state; - INA226 ina226; - AP33772 usbpd; - static RotaryEncoder encoder; //"static" Make sure there is only 1 copy for all object, shared variable - U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2; - Button button_encoder; - Button button_output; - Button button_selectVI; - Menu menu; - EEPROMHandler eepromHandler; - bool forceSave; - uint32_t saveStamp; - - unsigned long startTime; - bool bootInitialized; - bool obtainInitialized; - bool displayCapInitialized; - bool normalPPSInitialized; - bool normalPDOInitialized; - bool normalQCInitialized; - bool buttonPressed; - - static bool timerFlag0; - static bool timerFlag1; - - int targetVoltage; // Unit mV - int targetCurrent; // Unit mA - int voltageIncrementIndex; // just 0,1, or 2 - int currentIncrementIndex; // just 0,1, or 2 - int voltageIncrement[3]; - int currentIncrement[3]; - float ina_current_ma; // Unit - float vbus_voltage_mv; // Unit mV - int encoder_position; - int encoder_newPos; - Supply_Mode supply_mode; - Supply_Adjust_Mode supply_adjust_mode; - Output_Display_Mode output_display_mode; - - static constexpr long BOOT_TO_OBTAIN_TIMEOUT = 500; // Timeout for BOOT to OBTAIN state in seconds - static constexpr long OBTAIN_TO_CAPDISPLAY_TIMEOUT = 1500; // Timeout for OBTAIN to DISPLAYCAP state in seconds - static constexpr long DISPLAYCCAP_TO_NORMAL_TIMEOUT = 3000; // Timeout for DISPLAYCAP to NORMAL state in seconds - static constexpr int voltage_cursor_position[] = {40, 33, 26}; - static constexpr int current_cursor_position[] = {41, 34, 27}; - void componentInit(); - - void handleBootState(); - void handleObtainState(); - void handleDisplayCapState(); - void handleNormalPPSState(); - void handleNormalPDOState(); - void handleNormalQCState(); - void handleMenuState(); - - void transitionTo(State newState); - void printBootingScreen(); - void printProfile(); - void printOLED_fixed(); - void updateOLED(float voltage, float current, uint8_t requestEN); - void update_supply_mode(); - - void process_request_voltage_current(); - void process_encoder_input(); - void process_output_button(); - static void encoderISR(); - static void timerISR0(); // 100ms - static void timerISR1(); // 1s - char buffer[10]; - - int counter_gif = 0; //Count up to 27 - - // Energy tracking - double accumulatedWh = 0.0; // Accumulated watt-hours - double accumulatedAh = 0.0; // Accumulated amp-hours - unsigned long lastEnergyUpdate = 0; // Last time energy was calculated - unsigned long energyStartTime = 0; // Time when device was powered on - unsigned long historicalOutputTime = 0; // Total seconds output has been enabled (across sessions) - unsigned long currentSessionStartTime = 0; // millis() when current output session started - - void handleInitialMode(); - bool saveSettingsToEEPROM(); - bool loadSettingsFromEEPROM(bool vc); - void updateSaveStamp(); - void updateEnergyAccumulation(float voltage, float current); - void updateOLED_Energy(float voltage, float current); -}; - -#endif // STATEMACHINE_H diff --git a/include/v2/pocketpd.h b/include/v2/pocketpd.h index 5b2cdea..d56eec0 100644 --- a/include/v2/pocketpd.h +++ b/include/v2/pocketpd.h @@ -35,8 +35,7 @@ namespace pocketpd { /** * @brief Encoder increment tables (mV / mA). * - * Short-press encoder cycles the active index. Mirrors v1 - * voltageIncrement[3] / currentIncrement[3] in StateMachine. + * Short-press encoder cycles the active index. */ constexpr std::array VOLTAGE_INCREMENTS_MV = {1000, 100, 20}; constexpr std::array CURRENT_INCREMENTS_MA = {1000, 100, 50}; diff --git a/platformio.ini b/platformio.ini index 4374310..6e9a437 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -default_envs = HW1_3, HW1_3_V2 +default_envs = HW1_3_V2 extra_configs = scripts/fmt_flags.ini ; Shared values. Use as ${common.xx}. @@ -38,28 +38,6 @@ lib_deps = mathertel/RotaryEncoder@^1.5.3 khoih-prog/RPI_PICO_TimerInterrupt@^1.3.1 -[env:HW1_0] -extends = pico_base -extra_scripts = pre:scripts/configure_fmt_header_only.py -build_flags = - ${pico_base.build_flags} - -DHW1_0 - -DVERSION="\"1.0.0\"" -build_src_filter = - -<*> - + - -[env:HW1_3] -extends = pico_base -extra_scripts = pre:scripts/configure_fmt_header_only.py -build_flags = - ${pico_base.build_flags} - -DHW1_3 - -DVERSION="\"1.0.0\"" -build_src_filter = - -<*> - + - [env:HW1_0_V2] extends = pico_base extra_scripts = diff --git a/src/v1/AP33772_PocketPD.cpp b/src/v1/AP33772_PocketPD.cpp deleted file mode 100644 index 300b47c..0000000 --- a/src/v1/AP33772_PocketPD.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* Structs and Resgister list ported from "AP33772 I2C Command Tester" by Joseph Liang - * Created 11 April 2022 - * Added class and class functions by VicentN for PicoPD evaluation board - * Created 8 August 2023 - */ - -#include - -/** - * @brief Class constuctor - * @param &wire reference of Wire class. Pass in Wire or Wire1 - */ -AP33772::AP33772(TwoWire &wire) -{ - _i2cPort = &wire; -} - -/** - * @brief Check if power supply is good and fetch the PDO profile - */ -void AP33772::begin() -{ - i2c_read(AP33772_ADDRESS, CMD_STATUS, 1); // CMD: Read Status - ap33772_status.readStatus = readBuf[0]; - - if (ap33772_status.isOvp) - event_flag.ovp = 1; - if (ap33772_status.isOcp) - event_flag.ocp = 1; - - if (ap33772_status.isReady) // negotiation finished - { - if (ap33772_status.isNewpdo) // new PDO - { - if (ap33772_status.isSuccess) // negotiation success - event_flag.newNegoSuccess = 1; - else - event_flag.newNegoFail = 1; - } - else - { - if (ap33772_status.isSuccess) - event_flag.negoSuccess = 1; - else - event_flag.negoFail = 1; - } - } - delay(10); - - // If negotiation is good, let's load in some PDOs from charger - if (event_flag.newNegoSuccess | event_flag.negoSuccess) - { - event_flag.newNegoSuccess = 0; - - i2c_read(AP33772_ADDRESS, CMD_PDONUM, 1); // CMD: Read PDO Number - numPDO = readBuf[0]; - - i2c_read(AP33772_ADDRESS, CMD_SRCPDO, SRCPDO_LENGTH); // CMD: Read PDOs - // copy PDOs to pdoData[] - for (byte i = 0; i < numPDO; i++) - { - pdoData[i].byte0 = readBuf[i * 4]; - pdoData[i].byte1 = readBuf[i * 4 + 1]; - pdoData[i].byte2 = readBuf[i * 4 + 2]; - pdoData[i].byte3 = readBuf[i * 4 + 3]; - - if ((pdoData[i].byte3 & 0xF0) == 0xC0) // PPS profile found - { - PPSindex = i; // Store index - existPPS = 1; // Turn on flag - } - } - } -} - -/** - * @brief Check if target voltage and current are in range - * - * @param targetVoltage - * @param targetCurrent - */ -void AP33772::checkVoltageCurrent(int& targetVoltage, int& targetCurrent) -{ int maxVoltage = pdoData[PPSindex].pps.maxVoltage * 100; - int minVoltage = pdoData[PPSindex].pps.minVoltage * 100; - // Check if target voltage is in range - if(targetVoltage < minVoltage) - targetVoltage = minVoltage; // Minimum 5V - else if (targetVoltage > maxVoltage) - targetVoltage = maxVoltage; // Maximum 20V - - int maxCurrent = pdoData[PPSindex].pps.maxCurrent * 50; // Convert to mA - // Check if target current is in range - if(targetCurrent > maxCurrent) - targetCurrent = maxCurrent; // Maximum 3000mA -} - -/** - * @brief Set VBUS voltage and max current - * Current will automatically be in limit mode - * @param targetVoltage, targetCurrent, - mV and mA - */ -void AP33772::setSupplyVoltageCurrent(int targetVoltage, int targetCurrent) -{ - if ((existPPS) && (pdoData[PPSindex].pps.maxVoltage * 100 >= targetVoltage) && (pdoData[PPSindex].pps.minVoltage * 100 <= targetVoltage)) - { - indexPDO = PPSindex; - reqPpsVolt = targetVoltage / 20; // Unit in 20mV/LBS - rdoData.pps.objPosition = PPSindex + 1; // index 1 - // rdoData.pps.opCurrent = pdoData[PPSindex].pps.maxCurrent; - rdoData.pps.opCurrent = targetCurrent / 50; // Current limit - rdoData.pps.voltage = reqPpsVolt; - writeRDO(); - return; - } -} - -/** - * @brief Set VBUS voltage - * Current is set to MAX all the time - * @param targetVoltage in mV - */ -void AP33772::setVoltage(int targetVoltage) -{ - /* - Step 1: Check if PPS can satify request voltage - Step 2: Scan PDOs to see what is the lower closest voltage to request - Step 3: Compare found PDOs votlage and PPS max voltage - */ - byte tempIndex = 0; - if ((existPPS) && (pdoData[PPSindex].pps.maxVoltage * 100 >= targetVoltage) && (pdoData[PPSindex].pps.minVoltage * 100 <= targetVoltage)) - { - indexPDO = PPSindex; - reqPpsVolt = targetVoltage / 20; // Unit in 20mV/LBS - rdoData.pps.objPosition = PPSindex + 1; // index 1 - rdoData.pps.opCurrent = pdoData[PPSindex].pps.maxCurrent; - rdoData.pps.voltage = reqPpsVolt; - writeRDO(); - return; - } - else - { - // Step 2: Scan PDOs to see what is the lower closest voltage to request - for (byte i = 0; i < numPDO - existPPS; i++) - { - if (pdoData[i].fixed.voltage * 50 <= targetVoltage) - tempIndex = i; - } - // Step 3: Compare found PDOs votlage and PPS max voltage - if (pdoData[tempIndex].fixed.voltage * 50 > pdoData[PPSindex].pps.maxVoltage * 100) - { - indexPDO = tempIndex; - rdoData.fixed.objPosition = tempIndex + 1; // Index 0 to Index 1 - rdoData.fixed.maxCurrent = pdoData[indexPDO].fixed.maxCurrent; - rdoData.fixed.opCurrent = pdoData[indexPDO].fixed.maxCurrent; - writeRDO(); - return; - } - else // If PPS voltage larger or equal to Fixed PDO - { - indexPDO = PPSindex; - reqPpsVolt = pdoData[PPSindex].pps.maxVoltage * 5; // Convert unit: 100mV -> 20mV - rdoData.pps.objPosition = PPSindex + 1; // index 1 - rdoData.pps.opCurrent = pdoData[PPSindex].pps.maxCurrent; - rdoData.pps.voltage = reqPpsVolt; - writeRDO(); - return; - } - } -} - -/** - * @brief Request PDO profile. - * @param PDOindex start from index 0 to (PDONum - 1) if no PPS, (PDONum -2) if PPS found - */ -void AP33772::setPDO(uint8_t PDOindex) -{ - uint8_t guarding; - - if (PPSindex == 1) - {guarding = numPDO - 2;} - else - guarding = numPDO - 1; // Example array[4] only exist index 0,1,2,3 - - if (PDOindex <= guarding) - { - rdoData.fixed.objPosition = PDOindex + 1; // Index 0 to Index 1 - rdoData.fixed.maxCurrent = pdoData[PDOindex].fixed.maxCurrent; - rdoData.fixed.opCurrent = pdoData[PDOindex].fixed.maxCurrent; - writeRDO(); - } -} - -/** - * @brief Set max current before tripping at wall plug - * @param targetMaxCurrent in mA - */ -void AP33772::setMaxCurrent(int targetMaxCurrent) -{ - /* - Step 1: Check if current profile is PPS, check if max current is lower than request - If yes, set new max current - If no, report fault - Step 2: If profile is PDO, check if max current is lower than request - If yes, set new max current - If no, report fault - */ - if (indexPDO == PPSindex) - { - if (targetMaxCurrent <= pdoData[PPSindex].pps.maxCurrent * 50) - { - rdoData.pps.objPosition = PPSindex + 1; // index 1 - rdoData.pps.opCurrent = targetMaxCurrent / 50; // 50mA/LBS - rdoData.pps.voltage = reqPpsVolt; - writeRDO(); - } - else - { - } // Do nothing - } - else - { - if (targetMaxCurrent <= pdoData[indexPDO].fixed.maxCurrent * 10) - { - rdoData.fixed.objPosition = indexPDO + 1; // Index 0 to Index 1 - rdoData.fixed.maxCurrent = targetMaxCurrent / 10; // 10mA/LBS - rdoData.fixed.opCurrent = targetMaxCurrent / 10; // 10mA/LBS - writeRDO(); - } - else - { - } // Do nothing - } -} - -/** - * @brief Set resistance value of 10K NTC at 25C, 50C, 75C and 100C. - * Default is 10000, 4161, 1928, 974Ohm - * @param TR25, TR50, TR75, TR100 unit in Ohm - * @attention Blocking function due to long I2C write, min blocking time 15ms - */ -void AP33772::setNTC(int TR25, int TR50, int TR75, int TR100) // Parameter NOT DONE -{ - writeBuf[0] = TR25 & 0xff; - writeBuf[1] = (TR25 >> 8) & 0xff; - i2c_write(AP33772_ADDRESS, 0x28, 2); - delay(5); - writeBuf[0] = TR50 & 0xff; - writeBuf[1] = (TR50 >> 8) & 0xff; - i2c_write(AP33772_ADDRESS, 0x2A, 2); - delay(5); - writeBuf[0] = TR75 & 0xff; - writeBuf[1] = (TR75 >> 8) & 0xff; - i2c_write(AP33772_ADDRESS, 0x2C, 2); - delay(5); - writeBuf[0] = TR100 & 0xff; - writeBuf[1] = (TR100 >> 8) & 0xff; - i2c_write(AP33772_ADDRESS, 0x2E, 2); -} - -/** - * @brief Set target temperature (C) when output power through USB-C is reduced - * Default is 120 C - * @param temperature (unit in Celcius) - */ -void AP33772::setDeratingTemp(int temperature) -{ - writeBuf[0] = temperature; - i2c_write(AP33772_ADDRESS, CMD_DRTHR, 1); -} - -void AP33772::setMask(AP33772_MASK flag) -{ - // First read in what is currently in the MASK - i2c_read(AP33772_ADDRESS, CMD_MASK, 1); - writeBuf[0] = readBuf[0] | flag; - delay(5); // Short break between read/write - i2c_write(AP33772_ADDRESS, CMD_MASK, 1); -} - -void AP33772::clearMask(AP33772_MASK flag) -{ - // First read in what is currently in the MASK - i2c_read(AP33772_ADDRESS, CMD_MASK, 1); - writeBuf[0] = readBuf[0] & ~flag; - delay(5); // Short break between read/write - i2c_write(AP33772_ADDRESS, CMD_MASK, 1); -} - -void AP33772::i2c_read(byte slvAddr, byte cmdAddr, byte len) -{ - // clear readBuffer - for (byte i = 0; i < READ_BUFF_LENGTH; i++) - { - readBuf[i] = 0; - } - byte i = 0; - Wire.beginTransmission(slvAddr); // transmit to device SLAVE_ADDRESS - Wire.write(cmdAddr); // sets the command register - Wire.endTransmission(); // stop transmitting - - Wire.requestFrom(slvAddr, len); // request len bytes from peripheral device - if (len <= Wire.available()) - { // if len bytes were received - while (Wire.available()) - { - readBuf[i] = (byte)Wire.read(); - i++; - } - } -} - -void AP33772::i2c_write(byte slvAddr, byte cmdAddr, byte len) -{ - Wire.beginTransmission(slvAddr); // transmit to device SLAVE_ADDRESS - Wire.write(cmdAddr); // sets the command register - Wire.write(writeBuf, len); // write data with len - Wire.endTransmission(); // stop transmitting - - // clear readBuffer - for (byte i = 0; i < WRITE_BUFF_LENGTH; i++) - { - writeBuf[i] = 0; - } -} - -/** - * @brief Write the desire power profile back to the power source - */ -void AP33772::writeRDO() -{ - writeBuf[3] = rdoData.byte3; - writeBuf[2] = rdoData.byte2; - writeBuf[1] = rdoData.byte1; - writeBuf[0] = rdoData.byte0; - i2c_write(AP33772_ADDRESS, CMD_RDO, 4); // CMD: Write RDO -} - -/** - * @brief Read VBUS voltage - * @return voltage in mV - */ -int AP33772::readVoltage() -{ - i2c_read(AP33772_ADDRESS, CMD_VOLTAGE, 1); - return readBuf[0] * 80; // I2C read return 80mV/LSB -} - -/** - * @brief Read VBUS current - * @return current in mA - */ -int AP33772::readCurrent() -{ - i2c_read(AP33772_ADDRESS, CMD_CURRENT, 1); - return readBuf[0] * 16; // I2C read return 24mA/LSB -} - -/** - * @brief Read maximum VBUS current - * @return current in mA - */ -int AP33772::getMaxCurrent() const -{ - if (indexPDO == PPSindex) - { - return pdoData[PPSindex].pps.maxCurrent * 50; - } - else - { - return pdoData[indexPDO].fixed.maxCurrent * 10; - } -} - -/** - * @brief Read NTC temperature - * @return tempearture in C - */ -int AP33772::readTemp() -{ - i2c_read(AP33772_ADDRESS, CMD_TEMP, 1); - return readBuf[0]; // I2C read return 1C/LSB -} - -/** - * @brief Hard reset the power supply. Will temporary cause power outage - */ -void AP33772::reset() -{ - writeBuf[0] = 0x00; - writeBuf[1] = 0x00; - writeBuf[2] = 0x00; - writeBuf[3] = 0x00; - i2c_write(AP33772_ADDRESS, CMD_RDO, 4); -} - -/** - * @brief Debug code to quickly check power supply profile PDOs - */ -void AP33772::printPDO() -{ - Serial.print("Source PDO Number = "); - Serial.print(numPDO); - Serial.println(); - - for (byte i = 0; i < numPDO; i++) - { - if ((pdoData[i].byte3 & 0xF0) == 0xC0) // PPS PDO - { - Serial.print("PDO["); - Serial.print(i + 1); // PDO position start from 1 - Serial.print("] - PPS : "); - Serial.print((float)(pdoData[i].pps.minVoltage) * 100 / 1000); - Serial.print("V~"); - Serial.print((float)(pdoData[i].pps.maxVoltage) * 100 / 1000); - Serial.print("V @ "); - Serial.print((float)(pdoData[i].pps.maxCurrent) * 50 / 1000); - Serial.println("A"); - } - else if ((pdoData[i].byte3 & 0xC0) == 0x00) // Fixed PDO - { - Serial.print("PDO["); - Serial.print(i + 1); - Serial.print("] - Fixed : "); - Serial.print((float)(pdoData[i].fixed.voltage) * 50 / 1000); - Serial.print("V @ "); - Serial.print((float)(pdoData[i].fixed.maxCurrent) * 10 / 1000); - Serial.println("A"); - } - } - Serial.println("==============================================="); -} - -/** - * Add on for PPS Bench Power Supply - */ - -/** - * @brief Get the number of power profile, include PPS if exist - */ -int AP33772::getNumPDO() -{ - return numPDO; -} - -/** - * @brief Get index of PPS profile - */ -int AP33772::getPPSIndex() -{ - return PPSindex; -} - -/** - * @brief MaxCurrent for fixed voltage PDO - * @return Current in mAmp - */ -int AP33772::getPDOMaxcurrent(uint8_t PDOindex) -{ - return pdoData[PDOindex].fixed.maxCurrent * 10; -} - -/** - * @brief Get fixed PDO voltage - * @return Voltage in mVolt - */ -int AP33772::getPDOVoltage(uint8_t PDOindex) -{ - return pdoData[PDOindex].fixed.voltage * 50; -} - -/** - * @brief Get PPS min votlage - * @return Voltage in mVolt - */ -int AP33772::getPPSMinVoltage(uint8_t PPSindex) -{ - return pdoData[PPSindex].pps.minVoltage * 100; -} - -/** - * @brief Get PPS max votlage - * @return Voltage in mVolt - */ -int AP33772::getPPSMaxVoltage(uint8_t PPSindex) -{ - return pdoData[PPSindex].pps.maxVoltage * 100; -} - -/** - * @brief Get PPS max current - * @return Current in mAmp - */ -int AP33772::getPPSMaxCurrent(uint8_t PPSindex) -{ - return pdoData[PPSindex].pps.maxCurrent * 50; -} \ No newline at end of file diff --git a/src/v1/Button.cpp b/src/v1/Button.cpp deleted file mode 100644 index ce05058..0000000 --- a/src/v1/Button.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include - -/** - * Return 0 if button not pressed - * 1 if button is short pressed - * 2 if button is long pressed - */ -int Button::isButtonPressed(void) -{ - button.loop(); // Must call first - - if (button.isPressed()) - { - pressedTime = millis(); - isPressing = true; - isLongDetected = false; - } - - if (button.isReleased()) - { - isPressing = false; - releasedTime = millis(); - - long pressDuration = releasedTime - pressedTime; - - if (pressDuration < SHORT_PRESS_TIME) - return 1; - } - - // TODO: Trim implementation, right now you have two way of signaling longpress - // One is the return of the function, one is the longPressedFlag - if (isPressing == true && isLongDetected == false) - { - long pressDuration = millis() - pressedTime; - - if (pressDuration > LONG_PRESS_TIME) - { - isLongDetected = true; - longPressedFlag = true; - return 2; - } - } - return 0; -} - -void Button::loop() -{ - button.loop(); -} - -// Pass through function -void Button::setDebounceTime(unsigned long time) -{ - button.setDebounceTime(time); -} \ No newline at end of file diff --git a/src/v1/Menu.cpp b/src/v1/Menu.cpp deleted file mode 100644 index cb103dc..0000000 --- a/src/v1/Menu.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include - -/** - * Constructor - * Pass in pointer to local variable to simplified future funtion calls - */ -Menu::Menu(U8G2_SSD1306_128X64_NONAME_F_HW_I2C *oled, AP33772 *usb, RotaryEncoder *encoder, Button *button_encoder, Button *button_output, Button *button_selectVI) -{ - u8g2 = oled; - usbpd = usb; - _encoder = encoder; - _button_encoder = button_encoder; - _button_output = button_output; - _button_selectVI = button_selectVI; - - menuPosition = 0; - numPDO = 0; - qc3_0available = 0; -} - -/** - * @brief Check if menuPosition is within range, wrap around if not - * - * @param wrapAround - */ -void Menu::checkMenuPosition(bool wrapAround) { - if(usbpd) numPDO = usbpd->getNumPDO(); - if (menuPosition < 0) { - if(wrapAround) menuPosition = numPDO + qc3_0available - 1; // wrap around - else menuPosition = 0; // reset to 0 if not wrapping around - } - if(menuPosition > (numPDO + qc3_0available - 1)) { - menuPosition = 0; // wrap around - } -} - -/** - * @brief Handle main menu page for selecting capability - * - */ -void Menu::page_selectCapability() -{ - uint8_t linelocation; - static int val; - - if (val = (int8_t)_encoder->getDirection()) - { - menuPosition = menuPosition - val; - checkMenuPosition(true); - } - - u8g2->clearBuffer(); - for (byte i = 0; i < usbpd->getNumPDO(); i++) - { - if (i != usbpd->getPPSIndex()) - { - linelocation = 9 * (i + 1); - u8g2->setCursor(5, linelocation); - u8g2->print("PDO: "); - u8g2->print(usbpd->getPDOVoltage(i) / 1000.0, 0); - u8g2->print("V @ "); - u8g2->print(usbpd->getPDOMaxcurrent(i) / 1000.0, 0); - u8g2->print("A"); - } - else if (usbpd->existPPS) - { - linelocation = 9 * (i + 1); - u8g2->setCursor(5, linelocation); - u8g2->print("PPS: "); - u8g2->print(usbpd->getPPSMinVoltage(i) / 1000.0, 1); - u8g2->print("V~"); - u8g2->print(usbpd->getPPSMaxVoltage(i) / 1000.0, 1); - u8g2->print("V @ "); - u8g2->print(usbpd->getPPSMaxCurrent(i) / 1000.0, 0); - u8g2->print("A"); - } - if (i == menuPosition) - { - u8g2->setCursor(0, linelocation); - u8g2->print(">"); - } - } - - u8g2->sendBuffer(); -} - -void Menu::page_bootProfile() -{ -} - -// /** -// * Call this function after usbpd.begin() -// */ -// void Menu::getnumPDO() -// { -// //Pass in AP33772 flag -// numPDO = usbpd->getNumPDO(); -// } \ No newline at end of file diff --git a/src/v1/StateMachine.cpp b/src/v1/StateMachine.cpp deleted file mode 100644 index e6dc4f2..0000000 --- a/src/v1/StateMachine.cpp +++ /dev/null @@ -1,1095 +0,0 @@ -#include -#include - -// Static object require separate implementation -RotaryEncoder StateMachine::encoder(pin_encoder_A, pin_encoder_B, RotaryEncoder::LatchMode::FOUR3); -bool StateMachine::timerFlag0 = false; // Need to initilize Static variable -bool StateMachine::timerFlag1 = false; // Need to initilize Static variable - -/** - * @brief Transistion conditions between states. Call in main.cpp - */ -void StateMachine::update() -{ - auto now = millis(); - auto elapsed = now - startTime; - - switch (state) - { - case State::BOOT: - handleBootState(); - if (elapsed >= BOOT_TO_OBTAIN_TIMEOUT) - transitionTo(State::OBTAIN); - - break; - - case State::OBTAIN: - handleObtainState(); - if(encoder.getDirection() != RotaryEncoder::Direction::NOROTATION) { // Encoder rotation - transitionTo(State::MENU); - } else if (button_encoder.isButtonPressed() | button_output.isButtonPressed() | button_selectVI.isButtonPressed()) // Short press - handleInitialMode(); - else if (elapsed >= OBTAIN_TO_CAPDISPLAY_TIMEOUT) - transitionTo(State::CAPDISPLAY); - - break; - - case State::CAPDISPLAY: - handleDisplayCapState(); - if(encoder.getDirection() != RotaryEncoder::Direction::NOROTATION) { // Encoder rotation - transitionTo(State::MENU); - } else if ((button_encoder.isButtonPressed() | button_output.isButtonPressed() | button_selectVI.isButtonPressed() | elapsed >= DISPLAYCCAP_TO_NORMAL_TIMEOUT)) // Short press + timeout - handleInitialMode(); - - break; - - case State::NORMAL_PPS: - handleNormalPPSState(); - if (button_selectVI.longPressedFlag) // Long press isButtonPressed() is called inside the state - { - button_selectVI.clearLongPressedFlag(); - transitionTo(State::MENU); - } - saveSettingsToEEPROM(); - break; - case State::NORMAL_PDO: - handleNormalPDOState(); - button_selectVI.isButtonPressed(); // Call to update long press flag - if (button_selectVI.longPressedFlag) // Long press isButtonPressed() is called inside the state - { - button_selectVI.clearLongPressedFlag(); - transitionTo(State::MENU); - } - saveSettingsToEEPROM(); - break; - case State::NORMAL_QC: - handleNormalQCState(); - if (button_selectVI.longPressedFlag) // Long press isButtonPressed() is called inside the state - { - button_selectVI.clearLongPressedFlag(); - transitionTo(State::MENU); - } - saveSettingsToEEPROM(); - break; - - case State::MENU: - if(usbpd.getNumPDO() == 0) { - transitionTo(State::NORMAL_PDO); - break; // No PDO available, go back to NORMAL_PDO state - } - handleMenuState(); - - button_encoder.isButtonPressed(); - button_output.isButtonPressed(); - button_selectVI.isButtonPressed(); - - if (button_selectVI.longPressedFlag) // Long press - { - button_selectVI.clearLongPressedFlag(); - if (menu.menuPosition == usbpd.getPPSIndex()) { - transitionTo(State::NORMAL_PPS); - } else { - forceSave = true; - transitionTo(State::NORMAL_PDO); - } - } - if (button_encoder.longPressedFlag) // Long press - { - button_encoder.clearLongPressedFlag(); - if (menu.menuPosition == usbpd.getPPSIndex()) { - transitionTo(State::NORMAL_PPS); - } else { - forceSave = true; - transitionTo(State::NORMAL_PDO); - } - } - break; - } -} - -/** - * @return Return current state in string - */ -const char *StateMachine::getState() -{ - switch (state) - { - case State::BOOT: - return "BOOT"; - case State::OBTAIN: - return "OBTAIN"; - case State::CAPDISPLAY: - return "CAPABILITY"; - case State::NORMAL_PPS: - return "NORMAL_PPS"; - case State::NORMAL_PDO: - return "NORMAL_PDO"; - case State::NORMAL_QC: - return "NORMAL_QC"; - case State::MENU: - return "MENU"; - default: - return "UNKNOWN"; - } -} - -void StateMachine::componentInit() -{ - Wire.setSDA(pin_SDA); - Wire.setSCL(pin_SCL); - - attachInterrupt(digitalPinToInterrupt(pin_encoder_A), encoderISR, CHANGE); - attachInterrupt(digitalPinToInterrupt(pin_encoder_B), encoderISR, CHANGE); - - pinMode(pin_button_outputSW, INPUT_PULLUP); - pinMode(pin_button_selectVI, INPUT_PULLUP); - - pinMode(pin_output_Enable, OUTPUT); // Load Switch - digitalWrite(pin_output_Enable, LOW); - output_display_mode = OUTPUT_NORMAL; - - button_encoder.setDebounceTime(50); // set debounce time to 50 milliseconds - button_output.setDebounceTime(50); - button_selectVI.setDebounceTime(50); - - u8g2.begin(); - ina226.begin(); - // ina226.setMaxCurrentShunt(6, SENSERESISTOR); - // configure(shunt, current_LSB_mA, current_zero_offset_mA, bus_V_scaling_e4) - #ifdef HW1_0 - ina226.configure(0.01023, 0.25, 6.4, 9972); //Factory calibration - #endif - - #ifdef HW1_3 - ina226.configure(0.00528, 0.25, 10.4, 9972); //Factory calibration - #endif - - voltageIncrementIndex = 2; // 0= 20mV, 1 = 100mV, 2 = 1000mV - currentIncrementIndex = 2; // 0= 50mA, 1 = 100mA, 2 = 1000mA - - // Set up 100ms timer using timer0 - hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM0); - // Associate an interrupt handler with the ALARM_IRQ - irq_set_exclusive_handler(ALARM_IRQ0, timerISR0); - // Enable the alarm interrupt - irq_set_enabled(ALARM_IRQ0, true); - // Write the lower 32 bits of the target time to the alarm register, arming it. - timer_hw->alarm[ALARM_NUM0] = timer_hw->timerawl + DELAY0; - - // Set up 1s timer using timer1 - hw_set_bits(&timer_hw->inte, 1u << ALARM_NUM1); - // Associate an interrupt handler with the ALARM_IRQ - irq_set_exclusive_handler(ALARM_IRQ1, timerISR1); - // Enable the alarm interrupt - irq_set_enabled(ALARM_IRQ1, true); - // Write the lower 32 bits of the target time to the alarm register, arming it. - timer_hw->alarm[ALARM_NUM1] = timer_hw->timerawl + DELAY1; - - // Init EEPROM - EEPROM.begin(EEPROM_SIZE); -} - -// Only need to declare static in header files -void StateMachine::encoderISR() -{ - encoder.tick(); -} - -// ISR for 33ms timer -void StateMachine::timerISR0() -{ - // Clear the alarm irq - hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM0); - - // Reset the alarm register - timer_hw->alarm[ALARM_NUM0] = timer_hw->timerawl + DELAY0; - - timerFlag0 = true; -} - -// ISR for 500ms timer -void StateMachine::timerISR1() -{ - // Clear the alarm irq - hw_clear_bits(&timer_hw->intr, 1u << ALARM_NUM1); - - // Reset the alarm register - timer_hw->alarm[ALARM_NUM1] = timer_hw->timerawl + DELAY1; - - timerFlag1 = !timerFlag1; // toggle -} - -/** - * @brief Tasks for Boot state - */ -void StateMachine::handleBootState() -{ - if (!bootInitialized) - { - //* BEGIN Only run once when entering the state */ - // led.turnOn(); // Turn on the LED when entering the BOOT state - componentInit(); - printBootingScreen(); - // ADD Check if connected to PC here - //* END Only run once when entering the state */ - bootInitialized = true; // Mark BOOT state as initialized - Serial.println("Initialized BOOT state"); - } - //* BEGIN state routine */ - // Add additional BOOT state routines here - - //* END state routine */ - //Serial.println("Handling BOOT state"); -} - -/** - * @brief Tasks for Obtain state - */ -void StateMachine::handleObtainState() -{ - if (!obtainInitialized) - { - //* BEGIN Only run once when entering the state */ - usbpd.begin(); // Start pulling the PDOs from power supply - menu.numPDO = usbpd.getNumPDO(); // Call after usbpd.begin() - // ADD check QC3.0 code here - //* END Only run once when entering the state */ - bootInitialized = true; // Mark BOOT state as initialized - Serial.println("Initialized BOOT state"); - } - //* BEGIN state routine */ - // Add additional BOOT state routines here - - //* END state routine */ - // Serial.println( "Handling BOOT state" ); -} - -/** - * @brief Tasks for DisplayCapability state - */ -void StateMachine::handleDisplayCapState() -{ - if (!displayCapInitialized) - { - //* BEGIN Only run once when entering the state */ - // led.turnOn(); // Turn on the LED when entering the BOOT state - printProfile(); - usbpd.setSupplyVoltageCurrent(targetVoltage, targetCurrent); - - //* END Only run once when entering the state */ - displayCapInitialized = true; - } - // Add CAPABILITY state routines here - // Serial.println( "Handling CAPABILITY state" ); -} - -/** - * @brief Tasks for Normal with PPS state - */ -void StateMachine::handleNormalPPSState() -{ - // Run once - if (!normalPPSInitialized) - { - //* BEGIN Only run once when entering the state */ - - - // Load settings from EEPROM - if(loadSettingsFromEEPROM(true)) { - usbpd.checkVoltageCurrent(targetVoltage, targetCurrent); - } else { - targetVoltage = 5000; // Default start up voltage - targetCurrent = 1000; // Default start up current - } - supply_adjust_mode = VOTLAGE_ADJUST; - usbpd.setSupplyVoltageCurrent(targetVoltage, targetCurrent); - - //* END Only run once when entering the state */ - normalPPSInitialized = true; - Serial.println("Initialized NORMAL_PPS state"); - } - - //* BEGIN state routine */ - if (timerFlag0) // Timer with DELAY0 - { - ina_current_ma = abs(ina226.getCurrent_mA()); - vbus_voltage_mv = ina226.getBusVoltage_mV(); - - //Place before updateOLED to prevent voltage/current go out of bound, then recover. - - process_request_voltage_current(); - - float currentReading = 0; - float voltageReading = 0; - if (digitalRead(pin_output_Enable)){ - currentReading = ina_current_ma / 1000.0; - voltageReading = vbus_voltage_mv / 1000.0; - } else { - currentReading = 0; - voltageReading = usbpd.readVoltage() / 1000.0; - } - - // Update energy accumulation - updateEnergyAccumulation(voltageReading, currentReading); - - if (output_display_mode == OUTPUT_ENERGY) - { - // Show energy tracking display - updateOLED_Energy(voltageReading, currentReading); - } - else if (output_display_mode == OUTPUT_NORMAL) - { - // Show normal display with output enabled - updateOLED(voltageReading, currentReading,true); - } - - - update_supply_mode(); - timerFlag0 = false; - } - - // Disable encoder button and selectVI button in energy display mode - if (output_display_mode != OUTPUT_ENERGY) - { - if (button_encoder.isButtonPressed() == 1) - { - if (supply_adjust_mode == VOTLAGE_ADJUST) - { - // Make sure the valve loop around - voltageIncrementIndex = (voltageIncrementIndex + 1) % (sizeof(voltageIncrement) / sizeof(int)); - } - else - { - currentIncrementIndex = (currentIncrementIndex + 1) % (sizeof(currentIncrement) / sizeof(int)); - } - } - if (button_selectVI.isButtonPressed() == 1) - { - if (supply_adjust_mode == VOTLAGE_ADJUST) - supply_adjust_mode = CURRENT_ADJUST; - else - supply_adjust_mode = VOTLAGE_ADJUST; - } - - process_encoder_input(); - } - - process_output_button(); - - //* END state routine */ - // Serial.println( "Handling NORMAL_PPS state" ); -} - -/** - * @brief Tasks for Normal with fixed PDO state - */ -void StateMachine::handleNormalPDOState() -{ - // Run once - if (!normalPDOInitialized) - { - //* BEGIN Only run once when entering the state */ - usbpd.setPDO(menu.menuPosition); - // Now targetVoltage/targetCurrent is just for display. Do not pass over to AP33772 - targetVoltage = usbpd.getPDOVoltage(menu.menuPosition); // For display - targetCurrent = usbpd.getPDOMaxcurrent(menu.menuPosition); // For display - supply_adjust_mode = VOTLAGE_ADJUST; - - //* END Only run once when entering the state */ - normalPDOInitialized = true; - Serial.println(usbpd.getNumPDO()); - Serial.println("Initialized NORMAL_PDO state"); - } - - //* BEGIN state routine */ - float ina_current_ma = abs(ina226.getCurrent_mA()); - - if (timerFlag0) - { - ina_current_ma = abs(ina226.getCurrent_mA()); - vbus_voltage_mv = ina226.getBusVoltage_mV(); - - float currentReading = 0; - float voltageReading = 0; - if (digitalRead(pin_output_Enable)){ - currentReading = ina_current_ma / 1000.0; - voltageReading = vbus_voltage_mv / 1000.0; - } else { - currentReading = 0; - voltageReading = usbpd.readVoltage() / 1000.0; - } - // Update energy accumulation - updateEnergyAccumulation(voltageReading, currentReading); - - if (output_display_mode == OUTPUT_ENERGY) - { - // Show energy tracking display - updateOLED_Energy(voltageReading, currentReading); - } - else if (output_display_mode == OUTPUT_NORMAL) - { - // Show normal display with output enabled - updateOLED(voltageReading, currentReading,true); - } - update_supply_mode(); - timerFlag0 = false; - } - - process_output_button(); - - //* END state routine */ - // Serial.println( "Handling NORMAL_PDO state" ); -} - -/** - * @brief tasks for Normal with QC3.0 state - */ -void StateMachine::handleNormalQCState() -{ - // Run once - if (!normalQCInitialized) - { - //* BEGIN Only run once when entering the state */ - // TODO QC implmentation - //* END Only run once when entering the state */ - normalQCInitialized = true; - Serial.println("Initialized NORMAL_QC state"); - } - - //* BEGIN state routine */ - float ina_current_ma = abs(ina226.getCurrent_mA()); - - if (timerFlag0) - { - - vbus_voltage_mv = ina226.getBusVoltage_mV(); - - // Update energy accumulation - float currentReading = 0; - float voltageReading = 0; - if (digitalRead(pin_output_Enable)){ - currentReading = ina_current_ma / 1000.0; - voltageReading = vbus_voltage_mv / 1000.0; - } else { - currentReading = 0; - voltageReading = usbpd.readVoltage() / 1000.0; - } - // Update energy accumulation - updateEnergyAccumulation(voltageReading, currentReading); - - if (output_display_mode == OUTPUT_ENERGY) - { - // Show energy tracking display - updateOLED_Energy(voltageReading, currentReading); - } - else if (output_display_mode == OUTPUT_NORMAL) - { - // Show normal display with output enabled - updateOLED(voltageReading, currentReading,true); - } - timerFlag0 = false; - } - - process_output_button(); - // TODO QC implmentation - - //* END state routine */ - // Serial.println( "Handling NORMAL_QC state" ); -} - -/** - * @brief Tasks for Menu state. Just a wrapper function - */ -void StateMachine::handleMenuState() -{ - //* BEGIN state routine */ - menu.page_selectCapability(); - //* END state routine */ - // Check out https://github.com/shuzonudas/monoview/blob/master/U8g2/Examples/Menu/simpleMenu/simpleMenu.ino - // Serial.println( "Handling MENU state" ); -} - -/** - * @brief transitionTo perform flags clear before transisiton. Enable entry tasks in each state. - * @param State::newstate input the next state to transistion - */ -void StateMachine::transitionTo(State newState) -{ - // Ex: Print: Transitioning from BOOT to CAPABILITY - Serial.print("Transitioning from "); - Serial.print(getState()); - Serial.print("to "); - Serial.println((newState == State::BOOT ? "BOOT" : newState == State::CAPDISPLAY ? "CAPABILITY" - : newState == State::NORMAL_PPS ? "NORMAL" - : "MENU")); - - state = newState; - startTime = millis(); - - if (newState == State::BOOT) - { - bootInitialized = false; // Reset the initialization flag when entering BOOT - } - if (newState == State::OBTAIN) - { - obtainInitialized = false; // Reset the initialization flag when entering OBTAIN - } - if (newState == State::CAPDISPLAY) - { - displayCapInitialized = false; // Reset the initialization flag when entering CAPDISPLAY - } - if (newState == State::NORMAL_PPS || - newState == State::NORMAL_PDO || - newState == State::NORMAL_QC || - newState == State::MENU) - { - normalPPSInitialized = false; // Reset the initialization flag when entering CAPDISPLAY - normalPDOInitialized = false; - normalQCInitialized = false; - } - buttonPressed = false; // Reset button press flag when transitioning to another state -} - -void StateMachine::printBootingScreen() -{ - u8g2.clearBuffer(); - u8g2.drawBitmap(0, 0, 128 / 8, 64, image_PocketPD_Logo); - u8g2.setFont(u8g2_font_profont12_tr); - u8g2.drawStr(67,64, "FW: "); - u8g2.drawStr(87,64, VERSION); - u8g2.sendBuffer(); -} - -/** - * @brief Update value on OLED screen - * @param voltage voltage (mV) to display, big text - * @param current current (mA) to display, big text - * @param requestEN flag to show/not show smaller text. Used for PPS request. - */ -void StateMachine::updateOLED(float voltage, float current, uint8_t requestEN) -{ - // TODO Can optimize away requestEN - u8g2.clearBuffer(); - u8g2.setFontMode(1); - u8g2.setBitmapMode(1); - - // Start-Fixed Component - u8g2.setFont(u8g2_font_profont22_tr); - u8g2.drawStr(1, 14, "V"); - u8g2.drawStr(1, 47, "A"); - u8g2.setFont(u8g2_font_profont12_tr); - switch (state) - { - case State::NORMAL_PPS: - u8g2.drawStr(110, 62, "PPS"); - break; - case State::NORMAL_PDO: - u8g2.drawStr(110, 62, "PDO"); - break; - case State::NORMAL_QC: - u8g2.drawStr(110, 62, "QC3.0"); - break; - } - // End-Fixed Component - - // Start-Dynamic component - u8g2.setFont(u8g2_font_profont22_tr); - sprintf(buffer, "%.2f", voltage); - u8g2.drawStr(75 - u8g2.getStrWidth(buffer), 14, buffer); // Right adjust - sprintf(buffer, "%.2f", current); - u8g2.drawStr(75 - u8g2.getStrWidth(buffer), 47, buffer); // Right adjust - - // https://github.com/olikraus/u8g2/discussions/2028 - if (requestEN == 1) - { - u8g2.setFont(u8g2_font_profont15_tr); - sprintf(buffer, "%d mV", targetVoltage); - u8g2.drawStr(75 - u8g2.getStrWidth(buffer), 27, buffer); // Right adjust - sprintf(buffer, "%d mA", targetCurrent); - u8g2.drawStr(75 - u8g2.getStrWidth(buffer), 62, buffer); // Right adjust - } - - if (supply_mode) // CV = 0, CC = 1 - { - u8g2.setFont(u8g2_font_profont12_tr); - u8g2.drawStr(110, 10, "CV"); - u8g2.drawStr(110, 23, "CC"); - u8g2.setDrawColor(2); - u8g2.drawBox(104, 13, 23, 12); // CC - } - else - { - u8g2.setFont(u8g2_font_profont12_tr); - u8g2.drawStr(110, 10, "CV"); - u8g2.drawStr(110, 23, "CC"); - u8g2.setDrawColor(2); - u8g2.drawBox(104, 0, 23, 12); // CV - } - // End-Dynamic component - - // Blinking cursor - if (timerFlag1 && (state == State::NORMAL_PPS || state == State::NORMAL_QC)) - { - if (supply_adjust_mode == VOTLAGE_ADJUST) - u8g2.drawLine(voltage_cursor_position[voltageIncrementIndex], 28, voltage_cursor_position[voltageIncrementIndex] + 5, 28); - else - u8g2.drawLine(current_cursor_position[currentIncrementIndex], 63, current_cursor_position[currentIncrementIndex] + 5, 63); - } - - // Blinking output arrow - if(digitalRead(pin_output_Enable) == 1) - { - u8g2.drawXBMP(105, 28, 20, 20, arrow_bitmapallArray[counter_gif]); // draw arrow animation - counter_gif = (counter_gif + 1) % 28; - } - - u8g2.sendBuffer(); -} - -/** - * @brief Update energy accumulation (Wh and Ah) - continuous tracking, only resets on power cycle - */ -void StateMachine::updateEnergyAccumulation(float voltage, float current) -{ - if (digitalRead(pin_output_Enable) == 1) - { - unsigned long currentTime = millis(); - - // Start new session if needed - if (currentSessionStartTime == 0) - { - currentSessionStartTime = currentTime; - lastEnergyUpdate = currentTime; - return; - } - - // Accumulate energy since last update - ALWAYS accumulate when output enabled - unsigned long deltaMs = currentTime - lastEnergyUpdate; - - // Only accumulate if we have a reasonable delta (not first call edge case, not huge jump) - if (deltaMs > 0 && deltaMs < 1000) - { // Between 0ms and 1 second - if (!isfinite(voltage) || !isfinite(current)) - { - lastEnergyUpdate = currentTime; - return; - } - - double voltage_v = static_cast(voltage); - double current_a = static_cast(current); - - if (voltage_v >= 0.0 && current_a >= 0.0) - { - double power_w = voltage_v * current_a; - double deltaHours = static_cast(deltaMs) / 3600000.0; - - accumulatedWh += power_w * deltaHours; - accumulatedAh += current_a * deltaHours; - } - } - - lastEnergyUpdate = currentTime; - } - else - { - // Output disabled - save current session time to historical - if (currentSessionStartTime > 0) - { - unsigned long sessionDuration = (millis() - currentSessionStartTime) / 1000; - historicalOutputTime += sessionDuration; - currentSessionStartTime = 0; - } - lastEnergyUpdate = 0; - } -} - -/** - * @brief Energy tracking display - shows Wh/Ah with compact V/A at top - */ -void StateMachine::updateOLED_Energy(float voltage, float current) -{ - u8g2.clearBuffer(); - u8g2.setDrawColor(1); - u8g2.setFontMode(1); - u8g2.setBitmapMode(1); - - // Top section - Compact real-time V/A - u8g2.setFont(u8g2_font_profont12_tr); - sprintf(buffer, "%.2fV", voltage); - u8g2.drawStr(2, 10, buffer); - sprintf(buffer, "%.2fA", current); - u8g2.drawStr(48, 10, buffer); - - // CV/CC indicator (same size and alignment as V/A) - if (supply_mode == MODE_CC) - { - u8g2.drawStr(94, 10, "CC"); - } - else - { - u8g2.drawStr(94, 10, "CV"); - } - - // Animated arrow (only when output is enabled) - if (digitalRead(pin_output_Enable) == 1) - { - u8g2.drawXBMP(108, 0, 20, 20, arrow_bitmapallArray[counter_gif]); - counter_gif = (counter_gif + 1) % 28; - } - - // Calculate total time: historical + current session - unsigned long totalSeconds = historicalOutputTime; - if (currentSessionStartTime > 0) - { - totalSeconds += (millis() - currentSessionStartTime) / 1000; - } - - // Format time based on totalSeconds (only increments when outputting) - char timeBuffer[10]; - if (totalSeconds < 60) - { - // Under 1 minute: "00:SS" - sprintf(timeBuffer, "00:%02lu", totalSeconds); - } - else if (totalSeconds < 3600) - { - // Under 1 hour: "MM:SS" - sprintf(timeBuffer, "%02lu:%02lu", totalSeconds / 60, totalSeconds % 60); - } - else if (totalSeconds < 86400) - { - // Under 1 day: "#h##m" (e.g., "2h45m") - unsigned long hours = totalSeconds / 3600; - unsigned long minutes = (totalSeconds % 3600) / 60; - sprintf(timeBuffer, "%luh%02lum", hours, minutes); - } - else - { - // 1+ days: "#d##h" (e.g., "3d12h") - unsigned long days = totalSeconds / 86400; - unsigned long hours = (totalSeconds % 86400) / 3600; - sprintf(timeBuffer, "%lud%02luh", days, hours); - } - - // Use larger font for main data rows - u8g2.setFont(u8g2_font_profont17_tr); - - // Left column: Watts (no decimal when >= 100) - float watts = voltage * current; - if (watts >= 100.0) - { - sprintf(buffer, "%.0f", watts); - } - else - { - sprintf(buffer, "%.1f", watts); - } - u8g2.drawStr(2, 35, buffer); - int watts_width = u8g2.getStrWidth(buffer); - u8g2.drawStr(2 + watts_width + 2, 35, "W"); // 2px spacing - - // Time (more spacing from watts) - u8g2.drawStr(2, 55, timeBuffer); - - const double totalWh = accumulatedWh; - const double totalAh = accumulatedAh; - - // Right column: Wh with proper significant digits - if (totalWh < 10.0) - { - sprintf(buffer, "%.2f", totalWh); - } - else if (totalWh < 100.0) - { - sprintf(buffer, "%.1f", totalWh); - } - else - { - sprintf(buffer, "%.0f", totalWh); - } - u8g2.drawStr(70, 35, buffer); - int wh_width = u8g2.getStrWidth(buffer); - u8g2.drawStr(70 + wh_width + 2, 35, "Wh"); // 2px spacing - - // Ah with proper significant digits (more spacing) - if (totalAh < 10.0) - { - sprintf(buffer, "%.2f", totalAh); - } - else if (totalAh < 100.0) - { - sprintf(buffer, "%.1f", totalAh); - } - else - { - sprintf(buffer, "%.0f", totalAh); - } - u8g2.drawStr(70, 55, buffer); - int ah_width = u8g2.getStrWidth(buffer); - u8g2.drawStr(70 + ah_width + 2, 55, "Ah"); // 2px spacing - - // Reset font to default - u8g2.setFont(u8g2_font_profont12_tr); - u8g2.sendBuffer(); -} - -/** Need fixing */ -void StateMachine::update_supply_mode() -{ - //Serial.println("Dumping start "); - //Serial.println(targetVoltage); - //Serial.println(vbus_voltage_mv); - //Serial.println(ina_current_ma); - //Serial.println(targetCurrent); - if(state == State::NORMAL_PPS && digitalRead(pin_output_Enable) && - (targetVoltage >= vbus_voltage_mv + 50 + ina_current_ma*(0.166 + 0.022 + 0.005)) && - (ina_current_ma >= targetCurrent - 150 && ina_current_ma <= targetCurrent + 150)) //Current read when hitting limit, need to be around 85-115% limit set - supply_mode = MODE_CC; - else // Other state only display CV mode - supply_mode = MODE_CV; -} - -/** - * @brief Print out PPS/PDO profiles onto OLED - */ -void StateMachine::printProfile() -{ - int linelocation = 9; - /** - * Print out PPS if exist, else, print out PDOs - * Missing: cannot display multiple PPS profile - */ - u8g2.clearBuffer(); - - if (usbpd.getNumPDO() == 0) - { - u8g2.setFontMode(1); - u8g2.setFont(u8g2_font_6x13_tr); - u8g2.drawStr(8, 34, "No Profile Detected"); - u8g2.sendBuffer(); - return; - } - - u8g2.setFontMode(1); - u8g2.setBitmapMode(1); - u8g2.setFont(u8g2_font_profont11_tr); - // Print PDOs onto OLED - for (byte i = 0; i < usbpd.getNumPDO(); i++) - { - if (i != usbpd.getPPSIndex()) - { - linelocation = 9 * (i + 1); - u8g2.setCursor(5, linelocation); - u8g2.print("PDO: "); - u8g2.print(usbpd.getPDOVoltage(i) / 1000.0, 0); - u8g2.print("V @ "); - u8g2.print(usbpd.getPDOMaxcurrent(i) / 1000.0, 0); - u8g2.print("A"); - } - else if (usbpd.existPPS) - { - linelocation = 9 * (i + 1); - u8g2.setCursor(5, linelocation); - u8g2.print("PPS: "); - u8g2.print(usbpd.getPPSMinVoltage(i) / 1000.0, 1); - u8g2.print("V~"); - u8g2.print(usbpd.getPPSMaxVoltage(i) / 1000.0, 1); - u8g2.print("V @ "); - u8g2.print(usbpd.getPPSMaxCurrent(i) / 1000.0, 0); - u8g2.print("A"); - } - } - u8g2.sendBuffer(); -} - -/** - * @brief Read changes from encoder, compute target voltage/current - * Just update targetVoltage and targetCurrent - */ -void StateMachine::process_encoder_input() -{ - static int val; - if (val = (int8_t)encoder.getDirection()) - { - if (supply_adjust_mode == VOTLAGE_ADJUST) //If cursor is at voltage - { - targetVoltage = targetVoltage + val * voltageIncrement[voltageIncrementIndex]; - } - else //If cursor is at current - { - targetCurrent = targetCurrent + val * currentIncrement[currentIncrementIndex]; - } - updateSaveStamp(); // Update the save stamp to current time to debounce too many writes to EEPROM - } -} - -/** - * @brief Handle output button press - * Short press: Toggle output on/off (never changes display mode) - * Long press: Toggle between NORMAL and ENERGY display modes (never changes output) - */ -void StateMachine::process_output_button() -{ - int buttonState = button_output.isButtonPressed(); - - // Check for long press flag first - if (button_output.longPressedFlag) - { - button_output.clearLongPressedFlag(); - // Toggle between NORMAL and ENERGY display modes (output state unchanged) - - if (output_display_mode == OUTPUT_NORMAL) - { // Ignore all encoder turning - output_display_mode = OUTPUT_ENERGY; - detachInterrupt(digitalPinToInterrupt(pin_encoder_A)); - detachInterrupt(digitalPinToInterrupt(pin_encoder_B)); - } - else // In OUTPUT_ENERGY - { // Now read all encoder turning - output_display_mode = OUTPUT_NORMAL; - attachInterrupt(digitalPinToInterrupt(pin_encoder_A), encoderISR, CHANGE); - attachInterrupt(digitalPinToInterrupt(pin_encoder_B), encoderISR, CHANGE); - } - } - else if (buttonState == 1) // Short press - { - // Toggle output on/off (display mode unchanged) - if (digitalRead(pin_output_Enable) == LOW) // Currently off - { - digitalWrite(pin_output_Enable, HIGH); - } - else // Currently on - { - digitalWrite(pin_output_Enable, LOW); - } - } -} - -/** - * @brief Read changes from encoder, compute request voltage/current - * Sent request to AP33772 to update - */ -void StateMachine::process_request_voltage_current() -{ - static int val; - if (supply_adjust_mode == VOTLAGE_ADJUST) - { - if (usbpd.existPPS) - { - if ((float)usbpd.getPPSMinVoltage(usbpd.getPPSIndex()) <= targetVoltage && (float)usbpd.getPPSMaxVoltage(usbpd.getPPSIndex()) >= targetVoltage) - // usbpd.setVoltage(targetVoltage); - usbpd.setSupplyVoltageCurrent(targetVoltage, targetCurrent); - else if (usbpd.getPPSMinVoltage(usbpd.getPPSIndex()) > targetVoltage) - targetVoltage = usbpd.getPPSMinVoltage(usbpd.getPPSIndex()); // No change - else if (usbpd.getPPSMaxVoltage(usbpd.getPPSIndex()) < targetVoltage) - targetVoltage = usbpd.getPPSMaxVoltage(usbpd.getPPSIndex()); // No change - } - else - { // PDOs only has profile between 5V and 20V - if (targetVoltage > 20000) - targetVoltage = 20000; - else if (targetVoltage < 5000) - targetVoltage = 5000; - usbpd.setVoltage(targetVoltage); - } - } - else - { - if (usbpd.existPPS) - { - if (targetCurrent <= 1000) - targetCurrent = 1000; // Cap at 100mA minimum, no current update - else if (usbpd.getPPSMaxCurrent(usbpd.getPPSIndex()) >= targetCurrent) - // usbpd.setMaxCurrent(targetCurrent); - usbpd.setSupplyVoltageCurrent(targetVoltage, targetCurrent); - else if (usbpd.getPPSMaxCurrent(usbpd.getPPSIndex()) < targetCurrent) - targetCurrent = usbpd.getPPSMaxCurrent(usbpd.getPPSIndex()); // No change - } - else - targetCurrent = usbpd.getMaxCurrent(); // Pull current base on current PDO - } -} - -/** - * @brief Handle the initial mode when the device starts up - * This function checks if settings can be loaded from EEPROM and transitions to the appropriate state. - */ -void StateMachine::handleInitialMode() { - if(loadSettingsFromEEPROM(false)) { - if(menu.menuPosition == usbpd.getPPSIndex()) - transitionTo(State::NORMAL_PPS); - else - transitionTo(State::NORMAL_PDO); - } else { - if(usbpd.existPPS) - transitionTo(State::NORMAL_PPS); - else - transitionTo(State::NORMAL_PDO); - } -} - -/** - * @brief Save settings to EEPROM - * @return true if settings were saved successfully, false otherwise - */ -bool StateMachine::saveSettingsToEEPROM() { - uint32_t currentTime = millis(); - bool ret = false; - bool saveVC = state == State::NORMAL_PPS; // Check if we are in NORMAL_PPS state to save PPS settings - - if(forceSave || (currentTime - saveStamp >= EEPROM_SAVE_INTERVAL)) { - saveStamp = currentTime; - if(usbpd.getNumPDO() == 0) { - Serial.println("No PDOs available, cannot save settings."); - return false; // No PDOs available, cannot save settings - } - Settings newSettings = { 0 }; - eepromHandler.loadSettings(newSettings); // Load current settings from EEPROM - if(saveVC) { - newSettings.targetVoltage = targetVoltage; - newSettings.targetCurrent = targetCurrent; - int32_t menuIndex = menu.menuPosition; - if(menuIndex == 0) { menuIndex = usbpd.getPPSIndex(); } // If menu position is 0, use PPS index - newSettings.menuPosition = menuIndex; // Save current menu position - } else { - newSettings.menuPosition = menu.menuPosition; // Save current menu position - } - - ret = eepromHandler.saveSettings(newSettings); - Serial.printf("Settings saved to EEPROM: %d\n\r", ret); - forceSave = !ret; // If save failed, set forceSave to true to retry next time - } - return ret; -} - -/** - * @brief Load settings from EEPROM - * @param vc If true, load Voltage/Current settings, otherwise load menu position - * @return true if settings were loaded successfully, false otherwise - */ -bool StateMachine::loadSettingsFromEEPROM(bool vc) { - Settings loadedSettings; - bool ret = eepromHandler.loadSettings(loadedSettings); - if(ret) { - if(!vc) { - menu.menuPosition = loadedSettings.menuPosition; // Load menu position - menu.checkMenuPosition(false); - } else { - targetVoltage = loadedSettings.targetVoltage; - targetCurrent = loadedSettings.targetCurrent; - } - Serial.printf("Settings loaded from EEPROM: mV=%4d, mI=%4d, Menu position=%d\n\r", - targetVoltage, targetCurrent, menu.menuPosition); - } else { - Serial.println("Failed to load settings from EEPROM."); - } - return ret; -} - -/** - * @brief Debounce the save stamp - * - */ -void StateMachine::updateSaveStamp() { - saveStamp = millis(); // Update the save stamp to current time -} \ No newline at end of file diff --git a/src/v1/main.cpp b/src/v1/main.cpp deleted file mode 100644 index 1d0f47a..0000000 --- a/src/v1/main.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include "v1/StateMachine.h" - -static StateMachine statemachine; - -void setup() {} - -void loop() { - statemachine.update(); -}