226 lines
7.5 KiB
C
226 lines
7.5 KiB
C
#include "pico/stdlib.h"
|
|
#include "pulse_generator.h"
|
|
#include "CC_Charger.h"
|
|
#include "hardware/pwm.h"
|
|
#include "hardware/adc.h"
|
|
|
|
#define OUTPUT_EN_PIN 2
|
|
#define OUTPUT_CURRENT_TRIP_PIN 10
|
|
#define SPARK_THRESHOLD_PWM_PIN 14
|
|
#define SHORT_ALERT_PIN 1
|
|
|
|
#define PULSE_COUNTER_PWM_PIN 24
|
|
|
|
#define CAP_VSENSE_PIN 27
|
|
|
|
#define SHORT_THRESHOLD 410
|
|
|
|
bool cutting_enabled = false;
|
|
bool short_tripped = false;
|
|
|
|
//Enum to keep track of where we are in the pulse sequence
|
|
enum pulse_state{ WAITING_FOR_IGNITION,
|
|
SPARK_ON,
|
|
SPARK_OFF};
|
|
|
|
enum pulse_state output_state = SPARK_OFF;
|
|
|
|
//Pulse definition waveforms
|
|
uint32_t pulse_on_time = 0;
|
|
uint32_t pulse_off_time = 0;
|
|
bool iso_pulse_mode = false;
|
|
uint32_t pulse_timeout_time = 0; //time in us
|
|
|
|
alarm_id_t timeout_alarm_id;
|
|
|
|
//Pulse history tracking (512 cycles, 1 bit per cycle)
|
|
uint32_t pulse_history[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
uint32_t pulse_counter = 0;
|
|
|
|
uint8_t pulses_to_attempt = 0;
|
|
uint8_t pulse_attempt_counter = 0;
|
|
|
|
//Prototype functions
|
|
int64_t begin_off_time(alarm_id_t id, void *user_data);
|
|
|
|
//Set the CC timing to the standard charging parameters
|
|
int64_t change_CC_timing(alarm_id_t id, void *user_data){
|
|
|
|
LIMIT_set_timing(185, 7, true);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void short_alert_off() {
|
|
|
|
gpio_put(SHORT_ALERT_PIN, false);
|
|
|
|
}
|
|
|
|
void output_current_trip_irq(void) {
|
|
|
|
if (gpio_get_irq_event_mask(OUTPUT_CURRENT_TRIP_PIN) & GPIO_IRQ_EDGE_RISE) {
|
|
|
|
gpio_acknowledge_irq(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE);
|
|
|
|
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, false); //Turn off the interrupt on the ignition sense
|
|
|
|
output_state = SPARK_ON; //Update the pulse generator state
|
|
|
|
if(iso_pulse_mode == true){
|
|
|
|
cancel_alarm(timeout_alarm_id); //Turn off timeout alarm
|
|
add_alarm_in_us(pulse_on_time, begin_off_time, NULL, true); //Set alarm to turn off the pulse after the pulse on time
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int64_t begin_on_time(alarm_id_t id, void *user_data){
|
|
|
|
disable_CC_timing(); //Turn off the CC Charger
|
|
|
|
if(cutting_enabled) { //Check that cutting is still enabled
|
|
|
|
pulse_attempt_counter += 1;
|
|
|
|
output_state = WAITING_FOR_IGNITION; //Update pulse generator state
|
|
|
|
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, true); //Configure detection of the spark
|
|
|
|
if(iso_pulse_mode) { //Check pulse mode is iso-pulse
|
|
|
|
timeout_alarm_id = add_alarm_in_us(pulse_timeout_time, begin_off_time, NULL, true); //Set the alarm in case of pulse timeout
|
|
|
|
} else { //If pulse mode is iso-tonic
|
|
|
|
add_alarm_in_us(pulse_on_time, begin_off_time, NULL, true); //Set alarm for the off transition
|
|
|
|
}
|
|
|
|
gpio_put(OUTPUT_EN_PIN, true); //Turn on output FET
|
|
|
|
} else {
|
|
|
|
gpio_put(OUTPUT_EN_PIN, false);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
int64_t begin_off_time(alarm_id_t id, void *user_data){
|
|
|
|
gpio_put(OUTPUT_EN_PIN, false); //Turn off output MOSFET
|
|
|
|
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, false); //Disable the ignition sense irq
|
|
|
|
LIMIT_set_timing(97, 7, false); //Limit CC Charger PWM duty cycle to avoid inrush (was 97)
|
|
|
|
enable_CC_timing(true); //Start CC Charger
|
|
|
|
add_alarm_in_us(15, change_CC_timing, NULL, true); //Setup the alarm to correct CC charger timing
|
|
add_alarm_in_us(pulse_off_time-11, begin_on_time, NULL, true); //Setup the alarm to turn on the output MOSFET after the off time
|
|
|
|
pulse_counter -= pulse_history[0] & (uint32_t)0x1; //Subtract the 512th pulse state from the counter
|
|
|
|
for(int i = 0; i < 15; i++) {
|
|
|
|
pulse_history[i] = ((pulse_history[i+1] & (uint32_t)0x1) << 31) + (pulse_history[i] >> 1); //Binary shift the whole array (left shift each int and load in the first bit of the one above it)
|
|
|
|
}
|
|
|
|
pulse_history[15] = pulse_history[15] >> 1; //Binary shift the last value, done outside the for loop because nowhere to pull the MSB from
|
|
|
|
if(output_state == SPARK_ON) { //If successful spark then load a 1 into the MSB of the shift register and increment pulse counter
|
|
|
|
pulse_history[15] = pulse_history[15] + (1 << 31);
|
|
|
|
pulse_counter += 1;
|
|
|
|
}
|
|
|
|
output_state = SPARK_OFF; //Set state machine state to SPARK_OFF
|
|
|
|
if(pulse_counter > 513 || pulse_attempt_counter >= pulses_to_attempt) {
|
|
cutting_enabled = false;
|
|
short_tripped = true;
|
|
disable_CC_timing();
|
|
disable_gate_driver();
|
|
gpio_put(SHORT_ALERT_PIN, true);
|
|
}
|
|
|
|
pwm_set_gpio_level(PULSE_COUNTER_PWM_PIN, pulse_counter<<2);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void first_off_time(){
|
|
|
|
gpio_put(OUTPUT_EN_PIN, false); //Turn off output MOSFET
|
|
|
|
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, false); //Disable the ignition sense irq
|
|
|
|
LIMIT_set_timing(97, 7, false); //Limit CC Charger PWM duty cycle to avoid inrush (was 97)
|
|
|
|
enable_CC_timing(true); //Start CC Charger
|
|
|
|
add_alarm_in_us(15, change_CC_timing, NULL, true); //Setup the alarm to correct CC charger timing
|
|
add_alarm_in_us(pulse_off_time-11, begin_on_time, NULL, true); //Setup the alarm to turn on the output MOSFET after the off time
|
|
|
|
}
|
|
|
|
void begin_output_pulses(uint32_t on_time, uint32_t off_time, bool iso_pulse, uint8_t pulse_count) {
|
|
|
|
//Load in the pulse parameters
|
|
pulse_on_time = on_time;
|
|
pulse_off_time = off_time;
|
|
pulse_timeout_time = pulse_on_time / 2;
|
|
iso_pulse_mode = iso_pulse;
|
|
|
|
pulses_to_attempt = pulse_count;
|
|
pulse_attempt_counter = 0;
|
|
|
|
for (int i = 0; i < 15; i++)
|
|
pulse_history[i] = 0;
|
|
pulse_counter = 0;
|
|
|
|
first_off_time();
|
|
|
|
}
|
|
|
|
void pulse_generator_init(uint32_t trip_current) {
|
|
|
|
gpio_init(OUTPUT_EN_PIN);
|
|
gpio_set_dir(OUTPUT_EN_PIN, GPIO_OUT);
|
|
|
|
gpio_init(OUTPUT_CURRENT_TRIP_PIN);
|
|
gpio_set_dir(OUTPUT_CURRENT_TRIP_PIN, GPIO_IN);
|
|
|
|
gpio_init(SHORT_ALERT_PIN);
|
|
gpio_set_dir(SHORT_ALERT_PIN, GPIO_OUT);
|
|
|
|
gpio_set_function(SPARK_THRESHOLD_PWM_PIN, GPIO_FUNC_PWM);
|
|
|
|
pwm_set_wrap(pwm_gpio_to_slice_num(SPARK_THRESHOLD_PWM_PIN), 1000);
|
|
|
|
pwm_set_gpio_level(SPARK_THRESHOLD_PWM_PIN, trip_current);
|
|
|
|
pwm_set_enabled(pwm_gpio_to_slice_num(SPARK_THRESHOLD_PWM_PIN), true);
|
|
|
|
gpio_set_function(PULSE_COUNTER_PWM_PIN, GPIO_FUNC_PWM);
|
|
pwm_set_wrap(pwm_gpio_to_slice_num(PULSE_COUNTER_PWM_PIN), 2500);
|
|
|
|
pwm_set_enabled(pwm_gpio_to_slice_num(PULSE_COUNTER_PWM_PIN), true);
|
|
|
|
gpio_add_raw_irq_handler(OUTPUT_CURRENT_TRIP_PIN, &output_current_trip_irq);
|
|
|
|
adc_gpio_init(CAP_VSENSE_PIN);
|
|
|
|
} |