Files
RadioPhotonic_PCB_software/App/Devices/ds1809_device.c
2026-04-24 16:51:15 +03:00

84 lines
2.5 KiB
C

/**
* @file ds1809_device.c
* @brief DS1809 pulse-based control helper.
*/
#include "ds1809_device.h"
#include "main.h"
#define DS1809_POSITION_COUNT 64u
#define DS1809_CPU_PULSE_WIDTH_MS 2u
#define DS1809_CPU_INTER_PULSE_HIGH_MS 2u
#define DS1809_CONTROL_PORT_READY_DELAY_MS 10u
static void ds1809_drive_idle_high(void)
{
HAL_GPIO_WritePin(DS1809_UC_GPIO_Port, DS1809_UC_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(DS1809_DC_GPIO_Port, DS1809_DC_Pin, GPIO_PIN_SET);
}
static void ds1809_pulse_direction(uint8_t increment,
uint8_t decrement,
uint16_t count,
uint16_t low_time_ms,
uint16_t high_time_ms)
{
uint16_t pulse_index;
if ((count == 0u) || ((increment == 0u) && (decrement == 0u)))
{
ds1809_drive_idle_high();
return;
}
ds1809_drive_idle_high();
for (pulse_index = 0u; pulse_index < count; ++pulse_index)
{
if (increment != 0u)
{
HAL_GPIO_WritePin(DS1809_UC_GPIO_Port, DS1809_UC_Pin, GPIO_PIN_RESET);
}
if (decrement != 0u)
{
HAL_GPIO_WritePin(DS1809_DC_GPIO_Port, DS1809_DC_Pin, GPIO_PIN_RESET);
}
HAL_Delay(low_time_ms);
ds1809_drive_idle_high();
HAL_Delay(high_time_ms);
}
}
void ds1809_pulse(uint8_t increment, uint8_t decrement, uint16_t count, uint16_t pulse_ms)
{
if (pulse_ms < DS1809_CPU_PULSE_WIDTH_MS)
{
pulse_ms = DS1809_CPU_PULSE_WIDTH_MS;
}
ds1809_pulse_direction(increment, decrement, count, pulse_ms, pulse_ms);
}
void ds1809_apply_position_from_min(uint8_t position_from_min)
{
/*
* DS1809 CPU-driven timing requirements from the local datasheet:
* - a pulse must stay low for longer than 1 ms to count as a step;
* - repetitive pulses need at least 1 ms of high time between steps;
* - the control inputs are locked out for at least 10 ms after power-up.
*
* Use 2 ms low/high timing for margin, always drive to the RL end first,
* then walk back up to the requested absolute position.
*/
if (position_from_min >= DS1809_POSITION_COUNT)
{
position_from_min = (uint8_t)(DS1809_POSITION_COUNT - 1u);
}
HAL_Delay(DS1809_CONTROL_PORT_READY_DELAY_MS);
ds1809_pulse_direction(0u, 1u, DS1809_POSITION_COUNT, DS1809_CPU_PULSE_WIDTH_MS, DS1809_CPU_INTER_PULSE_HIGH_MS);
ds1809_pulse_direction(1u, 0u, position_from_min, DS1809_CPU_PULSE_WIDTH_MS, DS1809_CPU_INTER_PULSE_HIGH_MS);
}