0
mirror of https://gitlab.com/hyperglitch/jellyfish.git synced 2025-12-28 15:26:31 +00:00
2025-06-12 10:31:43 +02:00

130 lines
3.4 KiB
C

/*
* SPDX-FileCopyrightText: 2025 Igor Brkic <igor@hyperglitch.com>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <stdint.h>
#include <stdbool.h>
#include "aux_power.h"
#include "jf_adc.h"
#include "jf_i2c.h"
#include "main.h"
extern I2C_HandleTypeDef hi2c3;
static int32_t current_vset = 0;
static int32_t current_vout = 0;
static int32_t current_iout = 0;
static int32_t current_ilimit = 0;
static uint8_t current_digipot_code = 0;
static uint8_t current_digipot_code_limit = 0;
uint8_t wiper_data[2] = {0}; // needs to be global as it's sent via _IT function
bool vaux_set_digipot(uint8_t val, bool from_isr){
wiper_data[0] = (val>>8)&0x01;
wiper_data[1] = val&0xff;
if (from_isr) {
return jf_i2c_add_to_queue_from_isr(
JF_I2C_DEST_DIGIPOT,
JF_I2C_CMD_WRITE,
wiper_data,
NULL,
2
);
}
else {
return jf_i2c_add_to_queue(
JF_I2C_DEST_DIGIPOT,
JF_I2C_CMD_WRITE,
wiper_data,
NULL,
2,
false
);
}
}
int32_t vout_convert(int32_t adc_value_mv) {
// there's a 1/2 voltage divider on Vsense
current_vout = adc_value_mv * 2;
return current_vout;
}
int32_t iout_convert_handle(int32_t adc_value_mv) {
// 0-1A => 0-2000mV
current_iout = adc_value_mv / 2;
if (current_ilimit>0) {
if (current_iout>current_ilimit) {
// limit current
current_digipot_code_limit = current_digipot_code_limit + (255-current_digipot_code_limit)/2;
vaux_set_digipot(current_digipot_code_limit, true);
}
else {
if (current_digipot_code_limit!=current_digipot_code) {
current_digipot_code_limit--;
vaux_set_digipot(current_digipot_code_limit, true);
}
}
}
return current_iout;
}
void jf_vaux_init() {
jf_adc_register_callback(JF_ADC_AUX_VSENSE, vout_convert);
jf_adc_register_callback(JF_ADC_AUX_ISENSE, iout_convert_handle);
}
void jf_vaux_enable(bool en) {
HAL_GPIO_WritePin(ENABLE_AUX_GPIO_Port, ENABLE_AUX_Pin, en ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
bool jf_vaux_is_enabled() {
return HAL_GPIO_ReadPin(ENABLE_AUX_GPIO_Port, ENABLE_AUX_Pin) == GPIO_PIN_SET;
}
int32_t jf_vaux_measure_voltage() {
return current_vout;
}
int32_t jf_vaux_measure_current() {
return current_iout;
}
int32_t jf_vaux_get_voltage() {
return current_vset;
}
bool jf_vaux_set_voltage(const int32_t voltage_mv, bool from_isr) {
if (voltage_mv<1850) return false;
if (voltage_mv>5200) return false;
// Vout = Vref * (Rtop/Rbot+1)
// Rbot = (Vref*Rtop) / (Vout-Vref)
const int32_t Vref = 596; // mV
const int32_t Rtop = 100000; // Ohm
const int32_t Rbot = (Vref*Rtop) / (voltage_mv - Vref);
// Rbot (digipot): [0-256]=>[0-50k]
const int32_t DP_conv = 195; // 50000/256=195.3
const int32_t digipot_code = Rbot / DP_conv;
current_vout = voltage_mv;
current_digipot_code = digipot_code;
current_digipot_code_limit = digipot_code;
return vaux_set_digipot((uint8_t)digipot_code, from_isr);
}
int32_t jf_vaux_get_current_limit() {
return current_ilimit;
}
bool jf_vaux_set_current_limit(const int32_t current_ma) {
// convert and interpolate based on calibration table
// set digipot
current_ilimit = current_ma;
return true;
}