1.1 --- a/pkg/devices/lib/spi/src/gpio.cc Tue Nov 07 19:20:32 2023 +0100
1.2 +++ b/pkg/devices/lib/spi/src/gpio.cc Thu Nov 09 18:40:31 2023 +0100
1.3 @@ -27,27 +27,48 @@
1.4 Spi_gpio::Spi_gpio(Hw::Gpio_chip *clock_device, int clock_pin,
1.5 Hw::Gpio_chip *data_device, int data_pin,
1.6 Hw::Gpio_chip *enable_device, int enable_pin,
1.7 - uint64_t frequency)
1.8 + Hw::Gpio_chip *control_device, int control_pin)
1.9 : _clock_device(clock_device),
1.10 _clock_pin(clock_pin),
1.11 _data_device(data_device),
1.12 _data_pin(data_pin),
1.13 _enable_device(enable_device),
1.14 _enable_pin(enable_pin),
1.15 - _frequency(frequency)
1.16 + _control_device(control_device),
1.17 + _control_pin(control_pin)
1.18 {
1.19 _clock_device->setup(_clock_pin, Hw::Gpio_chip::Output, 1);
1.20 _data_device->setup(_data_pin, Hw::Gpio_chip::Output, 0);
1.21 _enable_device->setup(_enable_pin, Hw::Gpio_chip::Output, 1);
1.22 }
1.23
1.24 +Spi_gpio::Spi_gpio(uint64_t frequency,
1.25 + Hw::Gpio_chip *clock_device, int clock_pin,
1.26 + Hw::Gpio_chip *data_device, int data_pin,
1.27 + Hw::Gpio_chip *enable_device, int enable_pin,
1.28 + Hw::Gpio_chip *control_device, int control_pin)
1.29 +: Spi_gpio(clock_device, clock_pin, data_device, data_pin, enable_device,
1.30 + enable_pin, control_device, control_pin)
1.31 +{
1.32 + _frequency = frequency;
1.33 +}
1.34 +
1.35 /* Send a byte sequence. */
1.36
1.37 -void Spi_gpio::send(int bytes, const uint8_t data[])
1.38 +uint32_t Spi_gpio::send(uint32_t bytes, const uint8_t data[])
1.39 +{
1.40 + return send_dc(bytes, data, NULL);
1.41 +}
1.42 +
1.43 +/* Send a byte sequence with accompanying data/command indicators. */
1.44 +
1.45 +uint32_t Spi_gpio::send_dc(uint32_t bytes, const uint8_t data[],
1.46 + const int dc[])
1.47 {
1.48 struct timespec ts;
1.49 uint8_t mask;
1.50 - int bit, byte;
1.51 + int bit;
1.52 + uint32_t byte;
1.53
1.54 if (_frequency)
1.55 {
1.56 @@ -80,6 +101,9 @@
1.57 _clock_device->set(_clock_pin, 0);
1.58 _data_device->set(_data_pin, data[byte] & mask ? 1 : 0);
1.59
1.60 + if ((_control_device != NULL) && (dc != NULL))
1.61 + _control_device->set(_control_pin, dc[byte] ? 1 : 0);
1.62 +
1.63 if (_frequency)
1.64 nanosleep(&ts, NULL);
1.65
1.66 @@ -93,24 +117,77 @@
1.67 }
1.68
1.69 _enable_device->set(_enable_pin, 1);
1.70 +
1.71 + return bytes;
1.72 +}
1.73 +
1.74 +/* Send a number of units, each holding a value in a big endian arrangement
1.75 + limited to the given character size, with any bit immediately above the
1.76 + character portion of the unit indicating the data/command level. */
1.77 +
1.78 +uint32_t Spi_gpio::send_units(uint32_t bytes, const uint8_t data[],
1.79 + uint8_t unit_size, uint8_t char_size)
1.80 +{
1.81 + uint32_t count = bytes / unit_size;
1.82 + int dc[count];
1.83 +
1.84 + /* Traverse the byte sequence, extracting data/command bits for each unit. */
1.85 +
1.86 + for (uint32_t offset = 0, unit = 0; offset < bytes; offset += unit_size, unit++)
1.87 + {
1.88 + /* The unit size must be greater than the character size for data/command
1.89 + bits to be present. */
1.90 +
1.91 + if (unit_size * 8 <= char_size)
1.92 + dc[unit] = 0;
1.93 + else
1.94 + {
1.95 + /* Obtain the unit value. */
1.96 +
1.97 + uint32_t value = 0;
1.98 +
1.99 + for (uint8_t byte = 0; byte < unit_size; byte++)
1.100 + value = (value << 8) | data[offset + byte];
1.101 +
1.102 + /* Extract the data/command level. */
1.103 +
1.104 + dc[unit] = value & (1 << char_size) ? 1 : 0;
1.105 + }
1.106 + }
1.107 +
1.108 + return send_dc(bytes, data, dc);
1.109 }
1.110
1.111
1.112
1.113 /* C language interface. */
1.114
1.115 -void *spi_gpio_get_channel(void *clock_chip, int clock_pin,
1.116 +void *spi_gpio_get_channel(uint64_t frequency,
1.117 + void *clock_chip, int clock_pin,
1.118 void *data_chip, int data_pin,
1.119 void *enable_chip, int enable_pin,
1.120 - uint64_t frequency)
1.121 + void *control_chip, int control_pin)
1.122 {
1.123 - return (void *) new Spi_gpio(reinterpret_cast<Hw::Gpio_chip *>(clock_chip), clock_pin,
1.124 + return (void *) new Spi_gpio(frequency,
1.125 + reinterpret_cast<Hw::Gpio_chip *>(clock_chip), clock_pin,
1.126 reinterpret_cast<Hw::Gpio_chip *>(data_chip), data_pin,
1.127 reinterpret_cast<Hw::Gpio_chip *>(enable_chip), enable_pin,
1.128 - frequency);
1.129 + reinterpret_cast<Hw::Gpio_chip *>(control_chip), control_pin);
1.130 +}
1.131 +
1.132 +uint32_t spi_gpio_send(void *channel, uint32_t bytes, const uint8_t data[])
1.133 +{
1.134 + return static_cast<Spi_gpio *>(channel)->send(bytes, data);
1.135 }
1.136
1.137 -void spi_gpio_send(void *channel, int bytes, const uint8_t data[])
1.138 +uint32_t spi_gpio_send_dc(void *channel, uint32_t bytes, const uint8_t data[],
1.139 + const int dc[])
1.140 {
1.141 - static_cast<Spi_gpio *>(channel)->send(bytes, data);
1.142 + return static_cast<Spi_gpio *>(channel)->send_dc(bytes, data, dc);
1.143 }
1.144 +
1.145 +uint32_t spi_gpio_send_units(void *channel, uint32_t bytes, const uint8_t data[],
1.146 + uint8_t unit_size, uint8_t char_size)
1.147 +{
1.148 + return static_cast<Spi_gpio *>(channel)->send_units(bytes, data, unit_size, char_size);
1.149 +}