Firmware Update
Firmware updated with appropriate pinouts for Rev3 boards. Timings also accelerated to
This commit is contained in:
parent
e205849774
commit
4e116eae4f
|
@ -0,0 +1 @@
|
||||||
|
build/
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Pico",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"${env:PICO_SDK_PATH}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "${env:PICO_INSTALL_PATH}/gcc-arm-none-eabi/bin/arm-none-eabi-gcc.exe",
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++11",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm",
|
||||||
|
"configurationProvider": "ms-vscode.cmake-tools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Pico ARM GCC",
|
||||||
|
"description": "Pico SDK Toolchain with GCC arm-none-eabi",
|
||||||
|
"toolchainFile": "${env:PICO_SDK_PATH}/cmake/preload/toolchains/pico_arm_gcc.cmake"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"marus25.cortex-debug",
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"ms-vscode.cpptools-extension-pack",
|
||||||
|
"ms-vscode.vscode-serial-monitor"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Pico Debug (Cortex-Debug)",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"executable": "${command:cmake.launchTargetPath}",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"servertype": "openocd",
|
||||||
|
"gdbPath": "arm-none-eabi-gdb",
|
||||||
|
"device": "RP2040",
|
||||||
|
"configFiles": [
|
||||||
|
"interface/cmsis-dap.cfg",
|
||||||
|
"target/rp2040.cfg"
|
||||||
|
],
|
||||||
|
"svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
|
||||||
|
"runToEntryPoint": "main",
|
||||||
|
"openOCDLaunchCommands": [
|
||||||
|
"adapter speed 5000"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pico Debug (Cortex-Debug with external OpenOCD)",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"executable": "${command:cmake.launchTargetPath}",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"servertype": "external",
|
||||||
|
"gdbTarget": "localhost:3333",
|
||||||
|
"gdbPath": "arm-none-eabi-gdb",
|
||||||
|
"device": "RP2040",
|
||||||
|
"svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
|
||||||
|
"runToEntryPoint": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pico Debug (C++ Debugger)",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"program": "${command:cmake.launchTargetPath}",
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerPath": "arm-none-eabi-gdb",
|
||||||
|
"miDebuggerServerAddress": "localhost:3333",
|
||||||
|
"debugServerPath": "openocd",
|
||||||
|
"debugServerArgs": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"",
|
||||||
|
"serverStarted": "Listening on port .* for gdb connections",
|
||||||
|
"filterStderr": true,
|
||||||
|
"stopAtEntry": true,
|
||||||
|
"hardwareBreakpoints": {
|
||||||
|
"require": true,
|
||||||
|
"limit": 4
|
||||||
|
},
|
||||||
|
"preLaunchTask": "Flash",
|
||||||
|
"svdPath": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
// These settings tweaks to the cmake plugin will ensure
|
||||||
|
// that you debug using cortex-debug instead of trying to launch
|
||||||
|
// a Pico binary on the host
|
||||||
|
"cmake.statusbar.advanced": {
|
||||||
|
"debug": {
|
||||||
|
"visibility": "hidden"
|
||||||
|
},
|
||||||
|
"launch": {
|
||||||
|
"visibility": "hidden"
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"visibility": "hidden"
|
||||||
|
},
|
||||||
|
"buildTarget": {
|
||||||
|
"visibility": "hidden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cmake.buildBeforeRun": true,
|
||||||
|
"cmake.configureOnOpen": true,
|
||||||
|
"cmake.configureSettings": {
|
||||||
|
"CMAKE_MODULE_PATH": "${env:PICO_INSTALL_PATH}/pico-sdk-tools"
|
||||||
|
},
|
||||||
|
"cmake.generator": "Ninja",
|
||||||
|
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||||
|
"files.associations": {
|
||||||
|
"cc_charger.h": "c",
|
||||||
|
"stdlib.h": "c"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Flash",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "openocd",
|
||||||
|
"args": [
|
||||||
|
"-f",
|
||||||
|
"interface/cmsis-dap.cfg",
|
||||||
|
"-f",
|
||||||
|
"target/rp2040.cfg",
|
||||||
|
"-c",
|
||||||
|
"adapter speed 1000; program {${command:cmake.launchTargetPath}} verify reset exit"
|
||||||
|
],
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build",
|
||||||
|
"type": "cmake",
|
||||||
|
"command": "build",
|
||||||
|
"problemMatcher": "$gcc",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,219 @@
|
||||||
|
#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_CC_timing() {
|
||||||
|
|
||||||
|
gpio_put(DIODE_ON_PIN, false); //Turn off ideal diode
|
||||||
|
|
||||||
|
gpio_put(CC_CHARGER_EN_PIN, false); //Disable CC Charger gate driver
|
||||||
|
|
||||||
|
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);
|
||||||
|
gpio_set_function(3, 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_chan_level(v_i_set_pwm_slice, pwm_gpio_to_channel(CC_I_LIMIT_PIN), charger_current);
|
||||||
|
pwm_set_chan_level(v_i_set_pwm_slice, pwm_gpio_to_channel(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_chan_level(bias_pwm_slice_num, pwm_gpio_to_channel(GATE_BIAS_CLK_PIN), 1250);
|
||||||
|
|
||||||
|
pwm_set_enabled(bias_pwm_slice_num, true);
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef CC_CHARGER_H_INCLUDED
|
||||||
|
#define CC_CHARGER_H_INCLUDED
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
extern bool caps_charged;
|
||||||
|
|
||||||
|
/*! \brief Disable Constant Current Charger timing outputs, effectively turns off CC charger
|
||||||
|
\ingroup CC_Charger
|
||||||
|
*/
|
||||||
|
void disable_CC_timing();
|
||||||
|
|
||||||
|
/*! \brief Enable Constant Current Charger timing outputs, effectively turns on CC charger
|
||||||
|
\ingroup CC_Charger
|
||||||
|
*/
|
||||||
|
void enable_CC_timing();
|
||||||
|
|
||||||
|
/*! \brief Sets the CC charger clock period, indirectly sets the switching frequency of the CC charger
|
||||||
|
\ingroup CC_Charger
|
||||||
|
|
||||||
|
\param period Clock period = 3 * (1 + period) / Sys_clock (default 125MHz)
|
||||||
|
*/
|
||||||
|
void CLK_set_period(uint32_t period);
|
||||||
|
|
||||||
|
/*! \brief Sets the timing for the PWM limiting output
|
||||||
|
\ingroup CC_Charger
|
||||||
|
|
||||||
|
\param wait_time output low time = 2 * (1 + wait_time) / Sys_clock (default 125MHz)
|
||||||
|
\param on_time output high time = (1 + 2 * (1 * on_time)) / Sys_clock (default 125MHz)
|
||||||
|
*/
|
||||||
|
void LIMIT_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled);
|
||||||
|
|
||||||
|
/*! \brief Sets the timing for the PWM limiting output
|
||||||
|
\ingroup CC_Charger
|
||||||
|
|
||||||
|
\param wait_time output low time = 2 * (1 + wait_time) / Sys_clock (default 125MHz)
|
||||||
|
\param on_time output high time = (1 + 2 * (1 * on_time)) / Sys_clock (default 125MHz)
|
||||||
|
*/
|
||||||
|
void BLANKING_set_timing(uint32_t wait_time, uint32_t on_time, bool enabled);
|
||||||
|
|
||||||
|
/*! \brief Setup the CC charger
|
||||||
|
\ingroup CC_Charger
|
||||||
|
*/
|
||||||
|
void CC_Charger_init(int charger_current, int cap_voltage);
|
||||||
|
|
||||||
|
/*! \brief Whether or not the output caps are at the set voltage
|
||||||
|
\ingroup CC_charger
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,36 @@
|
||||||
|
.program CLK
|
||||||
|
.side_set 1 opt
|
||||||
|
|
||||||
|
irq clear 0 side 1 ; Set IRQ for other signals to reference off of
|
||||||
|
mov y, isr ; ISR contains PWM period. Y used as counter.
|
||||||
|
irq 0
|
||||||
|
countloop:
|
||||||
|
jmp x!=y noset ; Set pin high if X == Y, keep the two paths length matched
|
||||||
|
jmp skip side 0
|
||||||
|
noset:
|
||||||
|
nop ; Single dummy cycle to keep the two paths the same length
|
||||||
|
skip:
|
||||||
|
jmp y-- countloop ; Loop until Y hits 0, then pull a restart the counter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% c-sdk {
|
||||||
|
static inline void CLK_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||||
|
pio_sm_config c = CLK_program_get_default_config(offset);
|
||||||
|
|
||||||
|
// Map the state machine's OUT pin group to one pin, namely the `pin`
|
||||||
|
// parameter to this function.
|
||||||
|
sm_config_set_out_pins(&c, pin, 1);
|
||||||
|
// Set this pin's GPIO function (connect PIO to the pad)
|
||||||
|
pio_gpio_init(pio, pin);
|
||||||
|
// Set the pin direction to output at the PIO
|
||||||
|
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||||
|
|
||||||
|
sm_config_set_sideset_pins(&c, pin);
|
||||||
|
|
||||||
|
// Load our configuration, and jump to the start of the program
|
||||||
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
|
// Set the state machine running
|
||||||
|
//pio_sm_set_enabled(pio, sm, true);
|
||||||
|
}
|
||||||
|
%}
|
|
@ -0,0 +1,31 @@
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
include(pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
project(main)
|
||||||
|
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
add_executable(main)
|
||||||
|
|
||||||
|
pico_generate_pio_header(main ${CMAKE_CURRENT_LIST_DIR}/CLK.pio)
|
||||||
|
pico_generate_pio_header(main ${CMAKE_CURRENT_LIST_DIR}/TIMING.pio)
|
||||||
|
|
||||||
|
target_sources( main
|
||||||
|
PRIVATE main.c
|
||||||
|
CC_Charger.c
|
||||||
|
pulse_generator.c)
|
||||||
|
|
||||||
|
# pull in common dependencies
|
||||||
|
target_link_libraries( main
|
||||||
|
pico_stdlib
|
||||||
|
hardware_pio
|
||||||
|
hardware_adc
|
||||||
|
hardware_pwm
|
||||||
|
pico_time)
|
||||||
|
|
||||||
|
pico_enable_stdio_uart(main 1)
|
||||||
|
pico_enable_stdio_usb(main 0)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(main)
|
|
@ -0,0 +1,40 @@
|
||||||
|
.program TIMING
|
||||||
|
.side_set 1 opt
|
||||||
|
|
||||||
|
offStart:
|
||||||
|
wait 0 irq 0 side 0 ; Wait for clock rising edge
|
||||||
|
|
||||||
|
mov y, isr ; Wait time stored in ISR, Y register used as counter
|
||||||
|
|
||||||
|
waitloop:
|
||||||
|
jmp !y onStart ; When the timer runs out turn on the output pin and begin on time loop
|
||||||
|
jmp y-- waitloop ; If the off time hasn't elapsed, keep looping
|
||||||
|
|
||||||
|
onStart:
|
||||||
|
mov y, osr side 1 ; On time stored in OSR, Y register used as a counter
|
||||||
|
|
||||||
|
onloop:
|
||||||
|
jmp !y offStart ; When the timer runs out turn off the output pin and wait for clock edge
|
||||||
|
jmp y-- onloop ; If the on time hasn't yet elapsed, keep looping
|
||||||
|
|
||||||
|
|
||||||
|
% c-sdk {
|
||||||
|
static inline void TIMING_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||||
|
pio_sm_config c = TIMING_program_get_default_config(offset);
|
||||||
|
|
||||||
|
// Map the state machine's OUT pin group to one pin, namely the `pin`
|
||||||
|
// parameter to this function.
|
||||||
|
sm_config_set_out_pins(&c, pin, 1);
|
||||||
|
// Set this pin's GPIO function (connect PIO to the pad)
|
||||||
|
pio_gpio_init(pio, pin);
|
||||||
|
// Set the pin direction to output at the PIO
|
||||||
|
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||||
|
|
||||||
|
sm_config_set_sideset_pins(&c, pin);
|
||||||
|
|
||||||
|
// Load our configuration, and jump to the start of the program
|
||||||
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
|
// Set the state machine running
|
||||||
|
//pio_sm_set_enabled(pio, sm, true);
|
||||||
|
}
|
||||||
|
%}
|
|
@ -0,0 +1,87 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/time.h"
|
||||||
|
#include "hardware/pwm.h"
|
||||||
|
|
||||||
|
#include "CC_Charger.h"
|
||||||
|
#include "pulse_generator.h"
|
||||||
|
|
||||||
|
//Pinout definitions
|
||||||
|
#define CUT_nEN_PIN 0
|
||||||
|
|
||||||
|
//OUTPUT PULSE PARAMETERS (times in usecs)
|
||||||
|
#define OUTPUT_ON_TIME 20
|
||||||
|
#define OUTPUT_OFF_TIME 80
|
||||||
|
#define ISO_PULSE false
|
||||||
|
#define CAP_VOLTAGE_SETPOINT 65 //Don't set higher than 65
|
||||||
|
|
||||||
|
//CC Charger Parameters (don't change unless you know what you're doing)
|
||||||
|
#define CHARGER_CURRENT 850
|
||||||
|
|
||||||
|
//Math stuff DO NOT EDIT
|
||||||
|
#define CAP_VOLTAGE_PWM_LEVEL CAP_VOLTAGE_SETPOINT * 303 / 48
|
||||||
|
|
||||||
|
bool tripped = false;
|
||||||
|
|
||||||
|
void cut_on_off_irq(void) {
|
||||||
|
|
||||||
|
if(gpio_get_irq_event_mask(CUT_nEN_PIN) & GPIO_IRQ_EDGE_FALL) {
|
||||||
|
|
||||||
|
gpio_acknowledge_irq(CUT_nEN_PIN, GPIO_IRQ_EDGE_FALL);
|
||||||
|
|
||||||
|
cutting_enabled = true;
|
||||||
|
begin_output_pulses(OUTPUT_ON_TIME, OUTPUT_OFF_TIME, ISO_PULSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gpio_get_irq_event_mask(CUT_nEN_PIN) & GPIO_IRQ_EDGE_RISE) {
|
||||||
|
|
||||||
|
gpio_acknowledge_irq(CUT_nEN_PIN, GPIO_IRQ_EDGE_RISE);
|
||||||
|
|
||||||
|
cutting_enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_gpio_callback(uint gpio, uint32_t event_mask) {
|
||||||
|
gpio_acknowledge_irq(gpio, event_mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
// stdio_init_all(); //Start the Serial console
|
||||||
|
|
||||||
|
// gpio_init(CUT_nEN_PIN);
|
||||||
|
// gpio_set_dir(CUT_nEN_PIN, GPIO_IN);
|
||||||
|
// gpio_set_pulls(cut_NEN, true, false);
|
||||||
|
|
||||||
|
sleep_ms(1000);
|
||||||
|
|
||||||
|
// while(gpio_get(23)) {}
|
||||||
|
|
||||||
|
CC_Charger_init(CHARGER_CURRENT, CAP_VOLTAGE_PWM_LEVEL); //Setup the CC Charger Outputs
|
||||||
|
|
||||||
|
pulse_generator_init(10);
|
||||||
|
|
||||||
|
gpio_init(CUT_nEN_PIN);
|
||||||
|
gpio_set_dir(CUT_nEN_PIN, GPIO_IN);
|
||||||
|
gpio_set_pulls(CUT_nEN_PIN, true, false);
|
||||||
|
|
||||||
|
gpio_init(1);
|
||||||
|
gpio_set_dir(1, GPIO_OUT);
|
||||||
|
gpio_put(1, false);
|
||||||
|
|
||||||
|
irq_set_enabled(IO_IRQ_BANK0, true);
|
||||||
|
|
||||||
|
sleep_ms(1000);
|
||||||
|
|
||||||
|
gpio_set_irq_enabled(CUT_nEN_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
|
||||||
|
gpio_add_raw_irq_handler(CUT_nEN_PIN, &cut_on_off_irq);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
// sleep_us(10);
|
||||||
|
// gpio_put(3, true);
|
||||||
|
// sleep_us(10);
|
||||||
|
// gpio_put(3, false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate this SDK
|
||||||
|
# It should be include()ed prior to project()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||||
|
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||||
|
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||||
|
|
||||||
|
if (NOT PICO_SDK_PATH)
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT)
|
||||||
|
include(FetchContent)
|
||||||
|
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||||
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
|
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||||
|
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG master
|
||||||
|
GIT_SUBMODULES_RECURSE FALSE
|
||||||
|
)
|
||||||
|
else ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT pico_sdk)
|
||||||
|
message("Downloading Raspberry Pi Pico SDK")
|
||||||
|
FetchContent_Populate(pico_sdk)
|
||||||
|
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||||
|
endif ()
|
||||||
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||||
|
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||||
|
|
||||||
|
include(${PICO_SDK_INIT_CMAKE_FILE})
|
|
@ -0,0 +1,149 @@
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pulse_generator.h"
|
||||||
|
#include "CC_Charger.h"
|
||||||
|
#include "hardware/pwm.h"
|
||||||
|
|
||||||
|
#define OUTPUT_EN_PIN 2
|
||||||
|
#define OUTPUT_CURRENT_TRIP_PIN 10
|
||||||
|
#define SPARK_THRESHOLD_PWM_PIN 14
|
||||||
|
|
||||||
|
bool cutting_enabled = true;
|
||||||
|
bool off_time_insufficient = 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
|
||||||
|
|
||||||
|
//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 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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if(iso_pulse_mode) { //Check pulse mode is iso-pulse
|
||||||
|
|
||||||
|
output_state = WAITING_FOR_IGNITION; //Update pulse generator state
|
||||||
|
|
||||||
|
gpio_put(OUTPUT_EN_PIN, true); //Turn on output FET
|
||||||
|
|
||||||
|
add_alarm_in_us(pulse_timeout_time, begin_off_time, NULL, true); //Set the alarm in case of pulse timeout
|
||||||
|
|
||||||
|
gpio_set_irq_enabled(OUTPUT_CURRENT_TRIP_PIN, GPIO_IRQ_EDGE_RISE, true);//Configure detection of the spark
|
||||||
|
gpio_add_raw_irq_handler(OUTPUT_CURRENT_TRIP_PIN, &output_current_trip_irq);
|
||||||
|
|
||||||
|
} else { //If pulse mode is iso-tonic
|
||||||
|
|
||||||
|
output_state = SPARK_ON; //Update pulse generator state
|
||||||
|
|
||||||
|
gpio_put(OUTPUT_EN_PIN, true); //Turn on output FET
|
||||||
|
add_alarm_in_us(pulse_on_time-3, begin_off_time, NULL, true); //Set alarm for the off transition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64_t begin_off_time(alarm_id_t id, void *user_data){
|
||||||
|
|
||||||
|
if(output_state == WAITING_FOR_IGNITION || iso_pulse_mode == false) { //Spark has timed out or if iso pulse is off, restart pulse cycle
|
||||||
|
|
||||||
|
gpio_put(OUTPUT_EN_PIN, false); //Turn off output MOSFET
|
||||||
|
|
||||||
|
output_state = SPARK_OFF; //Update pulse generator state
|
||||||
|
|
||||||
|
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(); //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
|
||||||
|
|
||||||
|
} else if(output_state == SPARK_ON && iso_pulse_mode == true) { //Spark is already ignited, ignore this timer callback
|
||||||
|
|
||||||
|
//Do nothing
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void first_begin_off_time() {
|
||||||
|
|
||||||
|
LIMIT_set_timing(97, 7, false); //Set the CC Charger PWM max duty cycle lower to prevent inrush
|
||||||
|
|
||||||
|
enable_CC_timing(); //Start the CC Charger
|
||||||
|
|
||||||
|
add_alarm_in_us(15-4, change_CC_timing, NULL, true); //Setup the alarm to correct CC charger timing
|
||||||
|
add_alarm_in_us(pulse_off_time-8, 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) {
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
//Update pulse state based on pulse mode
|
||||||
|
if(iso_pulse_mode) {
|
||||||
|
output_state = WAITING_FOR_IGNITION;
|
||||||
|
} else {
|
||||||
|
output_state = SPARK_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_begin_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);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef PULSE_GENERATOR_H_INCLUDED
|
||||||
|
#define PULSE_GENERATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
extern bool cutting_enabled;
|
||||||
|
extern bool off_time_insufficient;
|
||||||
|
|
||||||
|
/*! \brief Start the EDM machine, ie, begin cutting
|
||||||
|
\ingroup pulse_generator
|
||||||
|
*/
|
||||||
|
void begin_output_pulses(uint32_t on_time, uint32_t off_time, bool iso_pulse);
|
||||||
|
|
||||||
|
/*! \brief Setup pins/dirs for the pulse generator
|
||||||
|
\ingroup pulse_generator
|
||||||
|
*/
|
||||||
|
void pulse_generator_init(uint32_t trip_current);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1 @@
|
||||||
|
POWERCORE-V2.0_MOTHERBOARD-backups/
|
Binary file not shown.
|
@ -63,7 +63,7 @@
|
||||||
36,
|
36,
|
||||||
40
|
40
|
||||||
],
|
],
|
||||||
"visible_layers": "8081100_ffffffff",
|
"visible_layers": "8081100_ffffffe0",
|
||||||
"zone_display_mode": 0
|
"zone_display_mode": 0
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
|
|
Loading…
Reference in New Issue