84 lines
2.5 KiB
C
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);
|
|
}
|