mirror of
https://gitlab.com/hyperglitch/jellyfish.git
synced 2025-12-28 15:26:31 +00:00
130 lines
3.4 KiB
C
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;
|
|
} |