# HG changeset patch # User Paul Boddie # Date 1699834635 -3600 # Node ID 7a9f0b8c1418c7c3b6c61d1fc0f43b7f0fde2c6c # Parent bd3493979bfdc75b39d580b8fdf90e4c88235b98 Fixed control pin initialisation and unit sending. diff -r bd3493979bfd -r 7a9f0b8c1418 pkg/devices/lib/spi/src/gpio.cc --- a/pkg/devices/lib/spi/src/gpio.cc Sun Nov 12 17:14:10 2023 +0100 +++ b/pkg/devices/lib/spi/src/gpio.cc Mon Nov 13 01:17:15 2023 +0100 @@ -40,6 +40,7 @@ _clock_device->setup(_clock_pin, Hw::Gpio_chip::Output, 1); _data_device->setup(_data_pin, Hw::Gpio_chip::Output, 0); _enable_device->setup(_enable_pin, Hw::Gpio_chip::Output, 1); + _control_device->setup(_control_pin, Hw::Gpio_chip::Output, 0); } Spi_gpio::Spi_gpio(uint64_t frequency, @@ -101,7 +102,7 @@ _clock_device->set(_clock_pin, 0); _data_device->set(_data_pin, data[byte] & mask ? 1 : 0); - if ((_control_device != NULL) && (dc != NULL)) + if ((_control_device != NULL) && (_control_pin >= 0) && (dc != NULL)) _control_device->set(_control_pin, dc[byte] ? 1 : 0); if (_frequency) @@ -128,34 +129,53 @@ uint32_t Spi_gpio::send_units(uint32_t bytes, const uint8_t data[], uint8_t unit_size, uint8_t char_size) { - uint32_t count = bytes / unit_size; - int dc[count]; + /* Obtain the data/command values for each unit. */ + + uint32_t chars = bytes / unit_size; + int dc[chars]; + + /* Obtain the actual character bytes to be sent. */ + + int char_unit_size = ((char_size ? char_size - 1 : 0) / 8) + 1; + uint8_t char_data[char_unit_size * chars]; /* Traverse the byte sequence, extracting data/command bits for each unit. */ - for (uint32_t offset = 0, unit = 0; offset < bytes; offset += unit_size, unit++) + for (uint32_t offset = 0, unit = 0, char_offset = 0; unit < chars; + offset += unit_size, unit++, char_offset += char_unit_size) { + /* Obtain the unit value. */ + + uint32_t value = 0; + + for (uint8_t byte = 0; byte < unit_size; byte++) + value = (value << 8) | data[offset + byte]; + /* The unit size must be greater than the character size for data/command bits to be present. */ if (unit_size * 8 <= char_size) dc[unit] = 0; + + /* Extract the data/command level. */ + else - { - /* Obtain the unit value. */ - - uint32_t value = 0; + dc[unit] = value & (1 << char_size) ? 1 : 0; - for (uint8_t byte = 0; byte < unit_size; byte++) - value = (value << 8) | data[offset + byte]; + /* Obtain the actual character data from the input data, discarding the most + significant bytes beyond the character and masking out any remaining + superfluous bits, thus obtaining a whole number of bytes. */ - /* Extract the data/command level. */ + value = value & ((1 << char_size) - 1); - dc[unit] = value & (1 << char_size) ? 1 : 0; + for (uint8_t byte = char_unit_size; byte != 0; byte--) + { + char_data[char_offset + byte - 1] = value & 0xff; + value >>= 8; } } - return send_dc(bytes, data, dc); + return send_dc(chars, char_data, dc); }