added ulp-pwm logic for timedlight

This commit is contained in:
Your Name
2021-12-05 02:36:03 +01:00
parent 80828eadd7
commit a745896643
9 changed files with 455 additions and 240 deletions

View File

@@ -1,112 +0,0 @@
/*
* DS2438.h
*
* by Joe Bechter
*
* (C) 2012, bechter.com
*
* All files, software, schematics and designs are provided as-is with no warranty.
* All files, software, schematics and designs are for experimental/hobby use.
* Under no circumstances should any part be used for critical systems where safety,
* life or property depends upon it. You are responsible for all use.
* You are free to use, modify, derive or otherwise extend for your own non-commercial purposes provided
* 1. No part of this software or design may be used to cause injury or death to humans or animals.
* 2. Use is non-commercial.
* 3. Credit is given to the author (i.e. portions © bechter.com), and provide a link to the original source.
*
*/
#ifndef DS2438_h
#define DS2438_h
#include <Arduino.h>
#include <OneWire.h>
#define DS2438_TEMPERATURE_CONVERSION_COMMAND 0x44
#define DS2438_VOLTAGE_CONVERSION_COMMAND 0xb4
#define DS2438_WRITE_SCRATCHPAD_COMMAND 0x4e
#define DS2438_COPY_SCRATCHPAD_COMMAND 0x48
#define DS2438_READ_SCRATCHPAD_COMMAND 0xbe
#define DS2438_RECALL_MEMORY_COMMAND 0xb8
#define PAGE_MIN 0
#define PAGE_MAX 7
#define DS2438_CHA 0
#define DS2438_CHB 1
#define DS2438_MODE_CHA 0x01
#define DS2438_MODE_CHB 0x02
#define DS2438_MODE_TEMPERATURE 0x04
#define DS2438_TEMPERATURE_DELAY 10
#define DS2438_VOLTAGE_CONVERSION_DELAY 8
#define DEFAULT_PAGE0(var) uint8_t var[8] { \
0b00001011 /* X, ADB=0, NVB=0, TB=0, AD=1, EE=0, CA=1, IAD=1 */, \
0, /* Temperatur */ \
0, /* Temperatur */ \
0, /* Voltage */ \
0, /* Voltage */ \
0, /* Current */ \
0, /* Current */ \
0 /* Threashold */ \
}
typedef struct PageOne {
uint8_t eleapsedTimerByte0; /**< LSB of timestamp */
uint8_t eleapsedTimerByte1;
uint8_t eleapsedTimerByte2;
uint8_t eleapsedTimerByte3; /**< MSB of timestamp */
uint8_t ICA; /**< Integrated Current Accumulator (current flowing into and out of the battery) */
uint8_t offsetRegisterByte0; /**< Offset for ADC calibdation */
uint8_t offsetRegisterByte1; /**< Offset for ADC calibdation */
uint8_t reserved;
} PageOne_t;
typedef struct PageSeven {
uint8_t userByte0;
uint8_t userByte1;
uint8_t userByte2;
uint8_t userByte3;
uint8_t CCA0; /**< Charging Current Accumulator (CCA) */
uint8_t CCA1; /**< Charging Current Accumulator (CCA) */
uint8_t DCA0; /**< Discharge Current Accumulator (DCA) */
uint8_t DCA1; /**< Discharge Current Accumulator (DCA) */
} PageSeven_t;
typedef uint8_t DeviceAddress[8];
class DS2438 {
public:
DS2438(OneWire *ow, float currentShunt);
DS2438(OneWire *ow, uint8_t *address);
void begin();
void update();
double getTemperature();
float getVoltage(int channel=DS2438_CHA);
float getCurrent();
boolean isError();
boolean isFound();
private:
bool validAddress(const uint8_t*);
bool validFamily(const uint8_t* deviceAddress);
bool deviceFound = false;
OneWire *_ow;
DeviceAddress _address;
uint8_t _mode;
double _temperature;
float _voltageA;
float _voltageB;
float _current;
float _currentShunt;
boolean _error;
boolean startConversion(int channel, boolean doTemperature);
boolean selectChannel(int channel);
void writePage(int page, uint8_t *data);
boolean readPage(int page, uint8_t *data);
};
#endif

View File

@@ -0,0 +1,187 @@
#ifndef ULP_PWM_h
#define ILP_PWM_h
#include <Arduino.h>
#include "driver/rtc_io.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc.h"
#include "esp32/ulp.h"
#define LBL_START 1
#define LBL_DELAY_ON 2
#define LBL_DELAY_OFF 3
#define LBL_SKIP_ON 4
#define LBL_SKIP_OFF 5
#define REGISTER_DELAY_LOOP_COUNTER R0
#define REGISTER_TICKS_ON R1
#define REGISTER_TICKS_OFF R2
#define TOTAL_TICKS_DELAY 255
#define PIN GPIO_NUM_12
//support 20 vars
const size_t ulp_var_offset = CONFIG_ULP_COPROC_RESERVE_MEM - 20;
//use the first for dimming
const size_t ulp_dimm_offset = ulp_var_offset + 1;
const size_t ulp_alive_offset = ulp_var_offset + 2;
//see https://github.com/perseus086/ESP32-notes
const uint32_t rtc_bit[40] = {
25, //gpio0
0, //gpio1
26, //gpio2
0, //gpio3
24, //gpio4
0, //gpio5
0, //gpio6
0, //gpio7
0, //gpio8
0, //gpio9
0, //gpio10
0, //gpio11
29, //gpio12
28, //gpio13
30, //gpio14
27, //gpio15
0, //gpio16
31, //gpio17
0, //gpio18
0, //gpio19
0, //gpio20
0, //gpio21
0, //gpio22
0, //gpio23
0, //gpio24
20, //gpio25
21, //gpio26
0, //gpio27
0, //gpio28
0, //gpio29
0, //gpio30
0, //gpio31
23, //gpio32
22, //gpio33
18, //gpio34
19, //gpio35
14, //gpio36
15, //gpio37
16, //gpio38
17 //gpio39
};
static inline void ulp_data_write(size_t offset, uint16_t value)
{
if (offset >= CONFIG_ULP_COPROC_RESERVE_MEM || offset <= ulp_var_offset)
{
Serial.print("Invalid ULP offset detected, refusing write!");
Serial.print(offset);
Serial.print("-");
Serial.print(ulp_var_offset);
Serial.print("-");
Serial.println(CONFIG_ULP_COPROC_RESERVE_MEM);
return;
}
else
{
RTC_SLOW_MEM[offset] = value;
}
}
static inline uint16_t ulp_data_read(size_t offset)
{
if (offset >= CONFIG_ULP_COPROC_RESERVE_MEM || offset <= ulp_var_offset)
{
Serial.print("Invalid ULP offset detected");
Serial.print(offset);
Serial.print("-");
Serial.print(ulp_var_offset);
Serial.print("-");
Serial.println(CONFIG_ULP_COPROC_RESERVE_MEM);
}
return RTC_SLOW_MEM[offset] & 0xffff;
}
static inline uint32_t rtc_io_number_get(gpio_num_t gpio_num)
{
assert(rtc_gpio_is_valid_gpio(gpio_num) && "Invalid GPIO for RTC");
uint32_t bit = rtc_bit[gpio_num];
Serial.print("Resolved GPIO ");
Serial.print(gpio_num);
Serial.print(" to rtc bit ");
Serial.println(bit);
return bit;
}
void ulp_pwm_start(void)
{
rtc_gpio_init(PIN);
rtc_gpio_set_direction(PIN, RTC_GPIO_MODE_OUTPUT_ONLY);
rtc_gpio_set_level(PIN, 0);
const uint32_t rtc_gpio = rtc_io_number_get(PIN);
// Define ULP program
const ulp_insn_t ulp_prog[] = {
M_LABEL(LBL_START),
I_MOVI(REGISTER_DELAY_LOOP_COUNTER, 1),
I_MOVI(REGISTER_TICKS_ON, 0),
I_ST(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_ON, ulp_alive_offset), //store 1 with 0 offset into alive
I_LD(REGISTER_TICKS_ON, REGISTER_TICKS_ON, ulp_dimm_offset), //REGISTER_TICKS_ON = RTC_DATA[0+ulp_dimm_offset]
//in total there is always 255 delay loop iterations, but in different duty cycle
I_MOVI(REGISTER_TICKS_OFF, TOTAL_TICKS_DELAY),
I_SUBR(REGISTER_TICKS_OFF, REGISTER_TICKS_OFF, REGISTER_TICKS_ON),
//on phase
I_MOVR(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_ON),
M_BL(LBL_SKIP_ON, 1), //if never on, skip on phase
I_WR_REG(RTC_GPIO_OUT_REG, rtc_gpio, rtc_gpio, HIGH), // on
M_LABEL(LBL_DELAY_ON),
I_DELAY(1), //wait 1 clock
I_SUBI(REGISTER_DELAY_LOOP_COUNTER, REGISTER_DELAY_LOOP_COUNTER, 1), // REGISTER_DELAY_LOOP_COUNTER--
M_BGE(LBL_DELAY_ON, 1), //if time left, goto start of on loop
M_LABEL(LBL_SKIP_ON),
//off phase
I_MOVR(REGISTER_DELAY_LOOP_COUNTER, REGISTER_TICKS_OFF),
M_BL(LBL_SKIP_OFF, 1), //if never off, skip on phase
I_WR_REG(RTC_GPIO_OUT_REG, rtc_gpio, rtc_gpio, LOW), // on
M_LABEL(3),
I_DELAY(1), //wait 1 clock
I_SUBI(REGISTER_DELAY_LOOP_COUNTER, REGISTER_DELAY_LOOP_COUNTER, 1), // REGISTER_DELAY_LOOP_COUNTER--
M_BGE(3, 1), //if time left, goto start of on loop
M_LABEL(LBL_SKIP_OFF),
M_BX(LBL_START),
};
// Run ULP program
size_t size = sizeof(ulp_prog) / sizeof(ulp_insn_t);
assert(size < ulp_var_offset && "ULP_DATA_OFFSET needs to be greater or equal to the program size");
esp_err_t error = ulp_process_macros_and_load(0, ulp_prog, &size);
Serial.print("ULP bootstrap status ");
Serial.println(error);
//allow glitchless start
ulp_data_write(ulp_alive_offset, 0);
error = ulp_run(0);
Serial.print("ULP start status ");
Serial.println(error);
}
static inline void ulp_pwm_set_level(uint8_t level)
{
ulp_data_write(ulp_dimm_offset, level);
}
static inline void ulp_pwm_init()
{
ulp_data_write(ulp_alive_offset, 0);
delay(10);
if (ulp_data_read(ulp_alive_offset) == 0)
{
ulp_pwm_start();
}
}
#endif