221 lines
8.2 KiB
C
221 lines
8.2 KiB
C
#include "pico/stdlib.h"
|
|
#include "hardware/pio.h"
|
|
#include "hardware/pwm.h"
|
|
#include "CC_Charger.h"
|
|
|
|
// Our assembled programs:
|
|
#include "CLK.pio.h"
|
|
#include "TIMING.pio.h"
|
|
|
|
//Pinout Definitions
|
|
|
|
//CC_Charger Timing:
|
|
#define CLK_PIN 6
|
|
#define LIMIT_PIN 9
|
|
#define BLANKING_PIN 15
|
|
|
|
//CC_Charger Control:
|
|
#define CC_CHARGER_EN_PIN 5
|
|
|
|
//Ideal Diode Controls:
|
|
#define DIODE_ON_PIN 4
|
|
|
|
//Gate Bias PWM:
|
|
#define GATE_BIAS_CLK_PIN 3
|
|
|
|
//PWM Voltage Sets:
|
|
#define CC_I_LIMIT_PIN 13
|
|
#define V_CAP_SET_PIN 12
|
|
|
|
//Telemetry:
|
|
#define VSENSE_TRIP_PIN 11
|
|
#define CAP_VSENSE_PIN 27
|
|
|
|
PIO pio;
|
|
|
|
int sm, sm_clk, sm_limit, sm_blanking;
|
|
uint offset_clk, offset_timing;
|
|
|
|
uint32_t default_clk_period = 133; //3.216usec
|
|
uint32_t default_limit_wait_time = 185; //3.024usec
|
|
uint32_t default_limit_on_time = 7; //0.136usec
|
|
uint32_t default_blanking_wait_time = 185; //0.112usec
|
|
uint32_t default_blanking_on_time = 12; //3.032usec
|
|
|
|
bool caps_charged = false;
|
|
|
|
void VSENSE_TRIP_callback(void) {
|
|
|
|
if(gpio_get_irq_event_mask(VSENSE_TRIP_PIN) & GPIO_IRQ_EDGE_RISE) {
|
|
|
|
gpio_acknowledge_irq(VSENSE_TRIP_PIN, GPIO_IRQ_EDGE_RISE);
|
|
|
|
//Flag that the caps have been charged
|
|
caps_charged = true;
|
|
|
|
//Turn off the CC_Charger
|
|
disable_CC_timing();
|
|
}
|
|
|
|
if(gpio_get_irq_event_mask(VSENSE_TRIP_PIN) & GPIO_IRQ_EDGE_FALL) {
|
|
|
|
gpio_acknowledge_irq(VSENSE_TRIP_PIN, GPIO_IRQ_EDGE_FALL);
|
|
|
|
//Flag that the caps are not fully charged
|
|
caps_charged = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void disable_gate_driver() {
|
|
gpio_put(CC_CHARGER_EN_PIN, false);
|
|
}
|
|
|
|
void disable_CC_timing() {
|
|
|
|
gpio_put(DIODE_ON_PIN, false); //Turn off ideal diode
|
|
|
|
pio_sm_set_enabled(pio, sm_clk, false); //Disable CC Charger Clock
|
|
pio_sm_exec(pio, sm_clk, pio_encode_nop() | pio_encode_sideset_opt(1, 0)); //Set Clock output to 0
|
|
pio_sm_exec(pio, sm_clk, pio_encode_irq_set(false, 0));
|
|
|
|
pio_sm_set_enabled(pio, sm_limit, false); //Disable PWM limit SM
|
|
pio_sm_exec(pio, sm_limit, pio_encode_nop() | pio_encode_sideset_opt(1, 1)); //Set PWM limit to 1 (keeps !CLR on Flip Flop low)
|
|
|
|
pio_sm_set_enabled(pio, sm_blanking, false); //Disable Slope blanking/reset
|
|
pio_sm_exec(pio, sm_blanking, pio_encode_nop() | pio_encode_sideset_opt(1, 1)); //Set Slope blanking to (Allows the compensated current limit to decay to 0)
|
|
|
|
}
|
|
|
|
void enable_CC_timing() {
|
|
|
|
//Don't start the charger if the caps are already charged
|
|
if(caps_charged == false){
|
|
|
|
//Reset all PIOs to the start of the program:
|
|
pio_sm_exec(pio, sm_clk, pio_encode_jmp(offset_clk ));
|
|
pio_sm_exec(pio, sm_blanking, pio_encode_jmp(offset_timing));
|
|
pio_sm_exec(pio, sm_limit, pio_encode_jmp(offset_timing));
|
|
|
|
//Renable PIOs
|
|
pio_sm_set_enabled(pio, sm_limit, true);
|
|
pio_sm_set_enabled(pio, sm_blanking, true);
|
|
pio_sm_set_enabled(pio, sm_clk, true);
|
|
|
|
gpio_put(CC_CHARGER_EN_PIN, true); //Enable the CC Charger gate driver
|
|
|
|
gpio_put(DIODE_ON_PIN, true); //Turn on the ideal diode
|
|
}
|
|
|
|
}
|
|
|
|
void CLK_set_period(uint32_t period) {
|
|
|
|
pio_sm_put_blocking(pio, sm_clk, period); //Load new period into FIFO
|
|
pio_sm_exec(pio, sm_clk, pio_encode_pull(false, false)); //Pull new period into OSR
|
|
pio_sm_exec(pio, sm_clk, pio_encode_out(pio_isr, 32)); //Shift new period from OSR to ISR
|
|
|
|
pio_sm_put_blocking(pio, sm_clk, period/2); //Load new on time into FIFO
|
|
pio_sm_exec(pio, sm_clk, pio_encode_pull(false, false)); //Pull new on time into OSR
|
|
pio_sm_exec(pio, sm_clk, pio_encode_out(pio_x, 32)); //Shift new on time into X register
|
|
|
|
}
|
|
|
|
void SM_set_timing(PIO pio, uint sm, uint32_t wait_time, uint32_t on_time, bool enabled) {
|
|
|
|
pio_set_sm_mask_enabled(pio, sm_clk | sm_blanking | sm_limit, false);
|
|
// pio_sm_set_enabled(pio, sm, false); //Temporarily freeze SM
|
|
|
|
pio_sm_put_blocking(pio, sm, wait_time); //Load new wait time into FIFO
|
|
pio_sm_exec(pio, sm, pio_encode_pull(false, false)); //Pull new wait time into OSR
|
|
pio_sm_exec(pio, sm, pio_encode_out(pio_isr, 32)); //Shift new wait time into ISR
|
|
|
|
pio_sm_put_blocking(pio, sm, on_time); //Load new on time into FIFO
|
|
pio_sm_exec(pio, sm, pio_encode_pull(false, false)); //Pull new wait time into OSR
|
|
|
|
// pio_sm_set_enabled(pio, sm, enabled); //Renable SM
|
|
pio_set_sm_mask_enabled(pio, sm_clk | sm_blanking | sm_limit, enabled);
|
|
|
|
}
|
|
|
|
void LIMIT_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled) {
|
|
|
|
SM_set_timing(pio, sm_limit, wait_time, on_time, enabled); //Update timing registers in SM
|
|
|
|
}
|
|
|
|
void BLANKING_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled) {
|
|
|
|
SM_set_timing(pio, sm_blanking, wait_time, on_time, enabled); //Update timing registers in SM
|
|
|
|
}
|
|
|
|
void CC_Charger_init(int charger_current, int cap_voltage) {
|
|
|
|
//Select a PIO bank
|
|
pio = pio0;
|
|
|
|
//Load programs into PIO memory
|
|
offset_clk = pio_add_program(pio, &CLK_program);
|
|
offset_timing = pio_add_program(pio, &TIMING_program);
|
|
|
|
//Select state machines for each output
|
|
sm_clk = pio_claim_unused_sm(pio, true);
|
|
sm_limit = pio_claim_unused_sm(pio, true);
|
|
sm_blanking = pio_claim_unused_sm(pio, true);
|
|
|
|
//Initialize each state machine
|
|
CLK_program_init (pio, sm_clk, offset_clk, CLK_PIN );
|
|
TIMING_program_init (pio, sm_limit, offset_timing, LIMIT_PIN );
|
|
TIMING_program_init (pio, sm_blanking, offset_timing, BLANKING_PIN );
|
|
|
|
//Load in default timing
|
|
CLK_set_period (default_clk_period);
|
|
LIMIT_set_timing (default_limit_wait_time, default_limit_on_time, false);
|
|
BLANKING_set_timing (default_blanking_wait_time, default_blanking_on_time, false);
|
|
|
|
//Setup VSENSE_TRIP pin
|
|
gpio_init(VSENSE_TRIP_PIN);
|
|
gpio_set_dir(VSENSE_TRIP_PIN, GPIO_IN);
|
|
gpio_set_pulls(VSENSE_TRIP_PIN, false, true);
|
|
|
|
gpio_set_irq_enabled(VSENSE_TRIP_PIN, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true);
|
|
gpio_add_raw_irq_handler(VSENSE_TRIP_PIN, &VSENSE_TRIP_callback);
|
|
|
|
//Setup CC_CHARGER_EN pin
|
|
gpio_init(CC_CHARGER_EN_PIN);
|
|
gpio_set_dir(CC_CHARGER_EN_PIN, GPIO_OUT);
|
|
|
|
gpio_put(CC_CHARGER_EN_PIN, false);
|
|
|
|
//Setup PWM -> Analog pins
|
|
gpio_set_function(CC_I_LIMIT_PIN, GPIO_FUNC_PWM);
|
|
gpio_set_function(V_CAP_SET_PIN, GPIO_FUNC_PWM);
|
|
|
|
uint v_i_set_pwm_slice = pwm_gpio_to_slice_num(V_CAP_SET_PIN);
|
|
|
|
pwm_set_wrap(v_i_set_pwm_slice, 1000);
|
|
|
|
pwm_set_gpio_level(CC_I_LIMIT_PIN, charger_current);
|
|
pwm_set_gpio_level(V_CAP_SET_PIN, cap_voltage);
|
|
|
|
pwm_set_enabled(v_i_set_pwm_slice, true);
|
|
|
|
//Setup Ideal Diode driver
|
|
gpio_init(DIODE_ON_PIN);
|
|
gpio_set_dir(DIODE_ON_PIN, GPIO_OUT);
|
|
|
|
gpio_put(DIODE_ON_PIN, false);
|
|
|
|
//Setup Gate Bias Charge Pump
|
|
gpio_set_function(GATE_BIAS_CLK_PIN, GPIO_FUNC_PWM);
|
|
|
|
uint bias_pwm_slice_num = pwm_gpio_to_slice_num(GATE_BIAS_CLK_PIN);
|
|
pwm_set_wrap(bias_pwm_slice_num, 2500);
|
|
|
|
pwm_set_gpio_level(GATE_BIAS_CLK_PIN, 1250);
|
|
|
|
pwm_set_enabled(bias_pwm_slice_num, true);
|
|
|
|
} |