Files
TX/source/driver.c

559 lines
8.5 KiB
C
Raw Normal View History

#include "driver.h"
#include "io.h"
#include "System/system.h"
#include "spi.h"
#include "pwm.h"
#include "utils.h"
static SYSTEM_DATA_t *_sys = NULL;
static TxDriver_t _driver;
2025-06-25 14:49:12 -05:00
static bool powerChangeAllowed(void)
{
return ((_sys->systemTime - _driver.lastPowerChangeTime) > POWER_CHANGE_TIME);
}
2025-08-26 16:10:47 -05:00
static void setTapLF(TransformerTap_t tap, bool update)
{
TransformerTap_t prevTap = _driver.tap;
EXPANDER_CLEAR(TAPS_OFF, NO_UPDATE);
switch (tap)
{
case TAP_2:
{
EXPANDER_SET(_TAP2_LF_ON, update);
break;
}
case TAP_3:
{
EXPANDER_SET(_TAP3_LF_ON, update);
break;
}
case TAP_4:
{
EXPANDER_SET(_TAP4_LF_ON, update);
break;
}
default:
{
EXPANDER_SET(_TAP1_LF_ON, update);
break;
}
}
if (update) io_update();
_driver.tap = tap;
}
static void setAmplifier(Amplifier_t amp)
{
Amplifier_t prevAmp = _driver.amplifier;
switch (amp)
{
case AMPLIFIER_D:
{
io_ampABOn(false, UPDATE);
delayms(5);
io_connectAmpAB(false, UPDATE);
delayms(5);
io_selectAmpD(UPDATE);
io_ampDOn(true, UPDATE);
delayms(10);
io_ampDEnable(true, UPDATE);
break;
}
case AMPLIFIER_AB:
{
// turn off AB
io_ampABOn(false, NO_UPDATE);
io_connectAmpAB(false, NO_UPDATE);
io_update();
// set the voltage appropriate for the accessory
driver_setPSUVoltage(_sys->activeAccessory->driveVoltage[HIGH_FREQ]);
_driver.state = DRIVER_STATE_SWITCH_AMP;
break;
}
default:
{
// turn off all amplifiers
io_ampABOn(false, NO_UPDATE);
io_ampDOn(false, NO_UPDATE);
io_ampDEnable(false, NO_UPDATE);
io_connectAmpAB(false, NO_UPDATE);
io_broadcastOn(false, NO_UPDATE);
// update values at the same time
io_update();
amp = AMPLIFIER_NONE;
}
}
_driver.amplifier = amp;
}
static void allAmpsOff(void)
{
setAmplifier(AMPLIFIER_NONE);
}
float driver_maxLoadCurrent(void)
{
// get max current based on load and frquency and battery
float targetPower = _sys->maxPowerLimit;
if (!driver_isLowFreq())
{
targetPower = 1.0f;
}
return (sqrtf(targetPower / _sys->adc.Ohms_slowfilt));
}
bool driver_isLowFreq(void)
{
return (_driver.frequency->frequency <= MAX_D_FREQ);
}
TxDriver_t * driver_getDriver(void)
{
return &_driver;
}
2025-08-26 16:10:47 -05:00
void driver_optimizeTransformer(void)
{
// update the tap settings based on the load
// must be requested by the accessory
}
void driver_setPSUVoltage(uint8_t value)
{
uint8_t data[2];
data[0] = 0x0;
data[1] = value;
SPI0_SendBytes(data, 2, PSU_VCTRL); // Update the Pot
}
void driver_setAmplitude(uint8_t value)
{
2025-08-26 16:10:47 -05:00
fgen_setAmplitude(value);
}
void driver_isolateOutput(bool isolate)
{
if (_sys != NULL)
{
_sys->status[ESTOP] = isolate;
}
if (isolate)
{
GPIO_WRITE(PIN_ESTOP, LOW); // Isolated
}
else
{
GPIO_WRITE(PIN_ESTOP, HIGH); // Not Isolated
}
}
void driver_enablePower(bool enable)
{
if (enable)
{
GPIO_WRITE(PIN_POWER_CTL, HIGH); // Switch or keep power on
}
else
{
GPIO_WRITE(PIN_POWER_CTL, LOW); // Switch power off
}
}
void driver_init(void)
{
_sys = system_getSys();
// isolate output
driver_isolateOutput(true);
_driver.state = DRIVER_STATE_INIT;
_driver.initState = true;
2025-08-26 16:10:47 -05:00
_driver.signalPath = SIGNAL_PATH_NONE;
// initialize amplitude pot
driver_setAmplitude(0);
// initialize PSU
_driver.psuValueMax = MAX_AB_PSU;
driver_setPSUVoltage(_driver.psuValueMax);
driver_enablePower(true);
2025-06-25 14:49:12 -05:00
2025-08-26 16:10:47 -05:00
_driver.prevAccy = NULL;
2025-06-25 14:49:12 -05:00
2025-08-26 16:10:47 -05:00
_driver.fgen = fgen_init();
2025-06-25 14:49:12 -05:00
// HACK: pick the first frequency for now
_driver.powerLevel = POWER_LEVEL_0;
_driver.frequency = fgen_getByIndex(0);
_driver.lastPowerChangeTime = _sys->systemTime;
2025-08-26 16:10:47 -05:00
setTapLF(TAP_2, UPDATE);
}
2025-08-26 16:10:47 -05:00
void driver_broadcastOn(bool on)
{
// turn off all amplifiers
2025-08-26 16:10:47 -05:00
io_broadcastOn(!on, NO_UPDATE);
io_connectAmpAB(!on, NO_UPDATE);
io_ampDOn(!on, NO_UPDATE);
// update values at the same time
io_update();
delayms(10);
2025-08-26 16:10:47 -05:00
driver_setPSUVoltage((on ? V_27V : V_24V));
// turn on broadcast amp
2025-08-26 16:10:47 -05:00
io_broadcastOn(on, UPDATE);
delayms(5);
// turn on the amplifier power supply
2025-08-26 16:10:47 -05:00
io_ampPsuOn(on, UPDATE);
_driver.amplifier = AMPLIFIER_NONE;
if (!on)
{
// turn off PWM
driver_setDuty(0);
}
}
void driver_setDuty(uint32_t duty)
{
uint32_t frequency;
if (duty == 0)
{
frequency = DEFAULT_PWM_FREQ;
}
else
{
frequency = _driver.frequency->frequency;
}
PWM_Setup(frequency, duty);
}
void driver_setFrequency(FREQUENCY_t *freq)
{
if (_sys->activeAccessory != NULL)
{
freq = _sys->activeAccessory->setFrequency(_sys->activeAccessory, freq);
if (freq != NULL)
{
2025-06-25 14:49:12 -05:00
// accessory may select a different frequency
_driver.frequency = freq;
2025-08-26 16:10:47 -05:00
fgen_setFrequency(freq);
driver_setPower(_driver.powerLevel);
}
}
}
2025-06-25 14:49:12 -05:00
void driver_setPower(PowerLevel_t powerLevel)
{
if (_sys->activeAccessory != NULL)
{
if (powerLevel > POWER_LEVEL_4)
{
powerLevel = POWER_LEVEL_4;
}
if (0 == _sys->activeAccessory->setPower(_sys->activeAccessory, powerLevel))
{
_driver.powerLevel = powerLevel;
}
}
2025-06-25 14:49:12 -05:00
_driver.lastPowerChangeTime = _sys->systemTime;
}
void driver_powerUp(void)
{
// limit power change rate
if (!powerChangeAllowed()) return;
PowerLevel_t level = _driver.powerLevel;
if (level < POWER_LEVEL_4)
{
level++;
}
driver_setPower(level);
}
void driver_powerDown(void)
{
if (!powerChangeAllowed()) return;
PowerLevel_t level = _driver.powerLevel;
if (level > POWER_LEVEL_0)
{
level--;
}
driver_setPower(level);
}
void driver_setSafe(bool safe)
{
_sys->safeMode = safe;
//Select_Estop((safe ? ISOLATED : CONNECTED));
driver_isolateOutput(true);
if (safe)
{
//clear shift registers to known state
io_expanderSetSafe();
delayms(10);
2025-08-26 16:10:47 -05:00
//dds_t *dds = fgen_getDDS(DDS_SIGNAL);
//dds_sleep(dds, true, true);
}
}
2025-08-26 16:10:47 -05:00
static void processSwitchAmp(void)
{
}
bool driver_outputReady(void)
{
return (_driver.state == DRIVER_STATE_RUNNING);
}
void driver_bypass(bool bypass)
{
_sys->status[BYPASS] = bypass;
io_bypassProtection(bypass, UPDATE);
}
void driver_setSignalPath(SignalPath_t path)
{
SignalPath_t prevPath = _driver.signalPath;
if (path == prevPath) return;
// disconnect external outputs
driver_isolateOutput(true);
driver_bypass(false);
// turn off all amplifiers
setAmplifier(AMPLIFIER_NONE);
switch (path)
{
case SIGNAL_PATH_ANT:
{
delayms(10);
driver_setPSUVoltage(V_27V);
// turn on broadcast amp
io_broadcastOn(true, UPDATE);
delayms(5);
// turn on the amplifier power supply
io_ampPsuOn(true, UPDATE);
// turn off PWM
driver_setDuty(0);
break;
}
case SIGNAL_PATH_AMP:
{
// set the frequency generator
driver_setFrequency(_driver.frequency);
// select amplifier
if (driver_isLowFreq())
{
setAmplifier(AMPLIFIER_D);
}
else
{
setAmplifier(AMPLIFIER_AB);
}
break;
}
default:
{
}
}
_driver.signalPath = path;
}
2025-06-25 14:49:12 -05:00
FREQUENCY_t* driver_getFrequency(void)
{
return _driver.frequency;
}
2025-06-25 14:49:12 -05:00
PowerLevel_t driver_getPowerLevel(void)
{
return _driver.powerLevel;
}
2025-08-26 16:10:47 -05:00
uint8_t driver_getAmplitude(void)
{
return _driver.fgen->amplitude;
}
TransformerTap_t driver_getTap(void)
{
return _driver.tap;
}
Amplifier_t driver_getAmplifier(void)
{
return _driver.amplifier;
}
// safety monitor run from interrupt
void driver_monitor(void)
{
}
2025-08-26 16:10:47 -05:00
static void checkAccessory(void)
{
ACCESSORY_t *accy = _sys->activeAccessory;
// do we need to swtich the signal path?
if (accy != NULL)
{
if (accy->state == PORT_STATE_RUNNING)
{
// new accessory attached
if (_driver.prevAccy != accy)
{
if (_driver.signalPath != accy->signalPath)
{
// change the signal path
driver_setSignalPath(accy->signalPath);
}
io_setOutputPort(accy->portId, accy->activeChannel);
_driver.prevAccy = accy;
}
}
}
}
void driver_service(void)
{
2025-08-26 16:10:47 -05:00
DriverState_t prevState = _driver.state;
switch (_driver.state)
{
case DRIVER_STATE_INIT:
{
2025-08-26 16:10:47 -05:00
_driver.state = DRIVER_STATE_RUNNING;
break;
}
2025-08-26 16:10:47 -05:00
case DRIVER_STATE_RUNNING:
{
2025-08-26 16:10:47 -05:00
// has the accessory / signal path changed?
checkAccessory();
break;
}
case DRIVER_STATE_SWITCH_AMP:
{
if (_driver.initState)
{
}
if (_driver.amplifier == AMPLIFIER_AB)
{
if (_sys->adc.V_PSU < MAX_AB_VOLTAGE)
{
// disable D amp
io_ampDEnable(false, UPDATE);
delayms(5);
io_ampDOn(false, UPDATE);
delayms(5);
// select AB amp
// turn on AB amp
io_ampABOn(true, UPDATE);
_driver.state = DRIVER_STATE_RUNNING;
}
}
break;
}
case DRIVER_STATE_SWITCH_FREQUENCY:
{
break;
}
}
2025-08-26 16:10:47 -05:00
if (prevState != _driver.state)
{
_driver.initState = true;
}
}