File syn_dmx512.c¶
File List > proto > syn_dmx512.c
Go to the documentation of this file
#if __has_include("syn_config.h")
#include "syn_config.h"
#endif
#if !defined(SYN_USE_DMX512) || SYN_USE_DMX512
#include "../util/syn_assert.h"
#include "syn_dmx512.h"
#include <string.h>
void syn_dmx512_master_init(SYN_DMX512_Master *master, uint16_t num_channels)
{
SYN_ASSERT(master != NULL);
memset(master, 0, sizeof(*master));
if (num_channels == 0 || num_channels > SYN_DMX512_MAX_CHANNELS) {
num_channels = SYN_DMX512_MAX_CHANNELS;
}
master->num_channels = num_channels;
master->start_code = SYN_DMX512_START_CODE_NULL;
}
SYN_Status syn_dmx512_master_set_channel(SYN_DMX512_Master *master, uint16_t channel, uint8_t value)
{
if (master == NULL) {
return SYN_INVALID_PARAM;
}
if (channel < 1 || channel > master->num_channels) {
return SYN_INVALID_PARAM;
}
master->channels[channel - 1] = value;
return SYN_OK;
}
uint8_t syn_dmx512_master_get_channel(const SYN_DMX512_Master *master, uint16_t channel)
{
if (master == NULL || channel < 1 || channel > master->num_channels) {
return 0;
}
return master->channels[channel - 1];
}
size_t syn_dmx512_master_build_frame(const SYN_DMX512_Master *master, uint8_t *out_buf,
size_t max_len)
{
if (master == NULL || out_buf == NULL || max_len < 1) {
return 0;
}
size_t needed = 1 + master->num_channels;
if (max_len < needed) {
return 0;
}
out_buf[0] = master->start_code;
(void)memcpy(&out_buf[1], master->channels, master->num_channels);
return needed;
}
void syn_dmx512_slave_init(SYN_DMX512_Slave *slave, uint16_t start_address, uint16_t footprint)
{
SYN_ASSERT(slave != NULL);
(void)memset(slave, 0, sizeof(*slave));
uint16_t addr = start_address;
if (addr < 1)
addr = 1;
if (addr > SYN_DMX512_MAX_CHANNELS)
addr = SYN_DMX512_MAX_CHANNELS;
uint16_t fp = footprint;
if (fp < 1)
fp = 1;
if ((uint32_t)addr - 1U + fp > SYN_DMX512_MAX_CHANNELS) {
fp = (uint16_t)(SYN_DMX512_MAX_CHANNELS - (addr - 1U));
}
slave->start_address = addr;
slave->footprint = fp;
slave->rx_state = SYN_DMX512_STATE_WAIT_BREAK;
}
void syn_dmx512_slave_rx_break(SYN_DMX512_Slave *slave)
{
if (slave == NULL)
return;
slave->rx_state = SYN_DMX512_STATE_WAIT_START;
slave->current_slot = 0;
}
void syn_dmx512_slave_rx_byte(SYN_DMX512_Slave *slave, uint8_t byte)
{
if (slave == NULL)
return;
switch (slave->rx_state) {
case SYN_DMX512_STATE_WAIT_START:
slave->start_code = byte;
if (byte == SYN_DMX512_START_CODE_NULL) {
slave->rx_state = SYN_DMX512_STATE_READ_SLOTS;
slave->current_slot = 1; /* Slot 1 is first channel after Start Code */
} else {
slave->rx_state = SYN_DMX512_STATE_WAIT_BREAK;
}
break;
case SYN_DMX512_STATE_READ_SLOTS:
if (slave->current_slot >= slave->start_address &&
slave->current_slot < slave->start_address + slave->footprint) {
uint16_t idx = slave->current_slot - slave->start_address;
slave->rx_channels[idx] = byte;
}
slave->current_slot++;
if (slave->current_slot > SYN_DMX512_MAX_CHANNELS) {
slave->frame_complete = true;
slave->rx_state = SYN_DMX512_STATE_WAIT_BREAK;
}
break;
case SYN_DMX512_STATE_WAIT_BREAK:
default:
break;
}
}
uint8_t syn_dmx512_slave_get_channel(const SYN_DMX512_Slave *slave, uint16_t offset)
{
if (slave == NULL || offset >= slave->footprint) {
return 0;
}
return slave->rx_channels[offset];
}
bool syn_dmx512_slave_is_updated(SYN_DMX512_Slave *slave)
{
if (slave == NULL)
return false;
if (slave->frame_complete) {
slave->frame_complete = false;
return true;
}
return false;
}
#endif /* SYN_USE_DMX512 */