Files
RS485_BSV_fw/Core/Src/board_logic.c

268 lines
6.2 KiB
C

/*
* board_logic.c
*
* Created on: Jul 25, 2024
* Author: User
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "main.h"
#include "modbus_logic.h"
#include "board_logic.h"
#define BOARD_DESC_LEN (14)
static const char board_description[BOARD_DESC_LEN] = "RS485_BSV V1R1";
extern uint16_t tranfer_errors_count;
extern TIM_HandleTypeDef htim6;
extern ADC_HandleTypeDef hadc1;
extern DAC_HandleTypeDef hdac;
#define LED_ACT_ON HAL_GPIO_WritePin(LED_ACT_GPIO_Port, LED_ACT_Pin, GPIO_PIN_SET)
#define LED_ACT_OFF HAL_GPIO_WritePin(LED_ACT_GPIO_Port, LED_ACT_Pin, GPIO_PIN_RESET)
hvs_t hvs = {0};
// Time for LED_ACT to be on
uint16_t led_time_act = 0;
// Raw ADC values buffer (circular DMA)
uint32_t rawADC[4] = {0};
// ADC Buffers
uint16_t volt_buff[ADC_BUFF_LENGTH] = {0};
uint16_t curr_buff[ADC_BUFF_LENGTH] = {0};
uint8_t buff_index = 0;
uint16_t config = 0;
uint16_t config_new = 0;
uint8_t config_update_flag = 0;
uint8_t adc_sum_flag = 0;
void board_init(void) {
// ADC
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_DMA(&hadc1, rawADC, 4);
// DAC
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0);
HAL_DAC_Start(&hdac, DAC_CHANNEL_2);
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, 0);
// 1ms timer start
HAL_TIM_Base_Start_IT(&htim6);
}
void loop_iterate() {
if(hvs.update_voltage_flag) {
uint32_t value = (uint32_t)(hvs.set_voltage*K_DAC_VOLTAGE);
if(value > 4095) value = 4095;
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value);
hvs.update_voltage_flag = 0;
}
if(hvs.update_current_flag)
{
uint32_t value = (uint32_t)(hvs.set_current*K_DAC_CURRENT);
if(value > 4095) value = 4095;
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, value);
hvs.update_current_flag = 0;
}
if(config_update_flag) {
// HVS ON
if((config^config_new) & CONF_BIT_HVS_EN) {
if(config_new & CONF_BIT_HVS_EN) SET_HVS_ON;
else SET_HVS_OFF;
}
config = config_new;
config_update_flag = 0;
}
// Time to calculate ADC results
if (adc_sum_flag) {
uint32_t volt_sum = 0, curr_sum = 0;
for (uint8_t i = 0; i < ADC_BUFF_LENGTH; i++) {
volt_sum += volt_buff[i];
curr_sum += curr_buff[i];
}
volt_sum = volt_sum / ADC_BUFF_LENGTH;
curr_sum = curr_sum / ADC_BUFF_LENGTH;
hvs.voltage = (float)volt_sum / K_ADC_VOLTAGE;
hvs.current = (float)curr_sum / K_ADC_CURRENT;
hvs.v_15 = (float)rawADC[2] / K_ADC_15V;
hvs.v_24 = (float)rawADC[3] / K_ADC_24V;
adc_sum_flag = 0;
}
/* */
modbus_loop_iterate();
HAL_Delay(1);
}
void update_service_indication(void) {
if (led_time_act) {
LED_ACT_ON;
led_time_act--;
} else
LED_ACT_OFF;
}
uint16_t update_status(void) {
uint16_t s = 0;
if(GET_HVS_CONN) {
// 0 - COVER OPEN - Xray board
// 1 - GLASS OPEN - Xray board
// 2 - NO WATER - Xray board
// 3 - JP1 - Xray board
// 4 - JP2 - Xray board
// 5 - was reserved but now it is Connection flag:
s |= (1u<<5);
if(GET_HVS_ENABLE) s |= (1u<<6);
if(GET_HVS_READY) s |= (1u<<7);
if(GET_HVS_XRAYON) s |= (1u<<8);
if(GET_HVS_NOLINK) s |= (1u<<9);
if(GET_HVS_OVERHEAT) s |= (1u<<10);
if(GET_HVS_OVERLOAD) s |= (1u<<11);
//12 - reserved
//13 - THERMSW - Xray board
//14 - SHTR_OPTO - Xray board
}
return s;
}
void adc_bufferize(void) {
if (GET_HVS_CONN) {
volt_buff[buff_index] = rawADC[0];
curr_buff[buff_index] = rawADC[1];
} else {
volt_buff[buff_index] = 0;
curr_buff[buff_index] = 0;
}
if (++buff_index >= ADC_BUFF_LENGTH) {
buff_index = 0;
adc_sum_flag = 1;
}
}
uint8_t read_register(uint16_t address, uint16_t* value)
{
if (address == 0x0001)
*value = MODBUS_PROTOCOL_VERSION;
else if (address == 0x0002)
*value = MODBUS_FIRMWARE_VERSION;
else if (address == 0x0003)
*value = MODBUS_BOARD_TYPE;
else if (address == 0x0004)
*value = tranfer_errors_count;
else if (address == 0x0005)
*value = 0; // supported data rate: unknown
else if (address >= 0x0010 && address <= 0x0099) {
int index = address - 0x0010;
if (index < BOARD_DESC_LEN)
*value = board_description[index];
else
*value = 0;
}
else if (address == 0x2001) { //Read status
*value = update_status();
}
else if (address == 0x2002) { //Read config
*value = config;
}
else if (address == 0x2010) { //Read tube voltage set
*value = ceil(hvs.set_voltage*100);
}
else if (address == 0x2011) { //Read tube current set
*value = ceil(hvs.set_current);
}
else if (address == 0x2012) { //Read tube voltage
if (GET_HVS_CONN)
*value = ceil(hvs.voltage*100);
else
*value = 0;
}
else if (address == 0x2013) { //Read tube current
if (GET_HVS_CONN)
*value = ceil(hvs.current);
else
*value = 0;
}
else if (address == 0x2014) { //Read 24V supply voltage
if (GET_HVS_CONN)
*value = ceil(hvs.v_24*100);
else
*value = 0;
}
else if (address == 0x2015) { //Read 15V supply voltage
if (GET_HVS_CONN)
*value = ceil(hvs.v_15*100);
else
*value = 0;
}
else
return 1;
return 0;
}
uint8_t write_register(uint16_t address, uint16_t value)
{
uint8_t ret = 0;
#ifdef UART_DEBUG
printf("Write A=0x%X D=0x%X\n\r",address,value);
#endif
switch (address) {
case 0x2002: //Write config
config_new = value;
config_update_flag = 1;
break;
case 0x2010: //Voltage set
hvs.set_voltage = (float)value/100;
if (hvs.set_voltage > HVS_U_LIMIT) hvs.set_voltage = HVS_U_LIMIT;
hvs.update_voltage_flag = 1;
break;
case 0x2011: //Current set
hvs.set_current = (float)value;
if (hvs.set_current > HVS_I_LIMIT) hvs.set_current = HVS_I_LIMIT;
hvs.update_current_flag = 1;
break;
default:
ret = 1;
}
return ret;
}
// Timers overflow interrupt
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
// check if the interrupt comes from TIM6 (1ms timer)
if(htim->Instance == TIM6) {
// ACT LED update
update_service_indication();
// bufferize the ADC values
adc_bufferize();
}
}