Landfall

Change of pkg/devices/lib/spi/src/gpio.cc

232:7a9f0b8c1418
pkg/devices/lib/spi/src/gpio.cc cpm-library-improvements
     1.1 --- a/pkg/devices/lib/spi/src/gpio.cc	Sun Nov 12 17:14:10 2023 +0100
     1.2 +++ b/pkg/devices/lib/spi/src/gpio.cc	Mon Nov 13 01:17:15 2023 +0100
     1.3 @@ -40,6 +40,7 @@
     1.4    _clock_device->setup(_clock_pin, Hw::Gpio_chip::Output, 1);
     1.5    _data_device->setup(_data_pin, Hw::Gpio_chip::Output, 0);
     1.6    _enable_device->setup(_enable_pin, Hw::Gpio_chip::Output, 1);
     1.7 +  _control_device->setup(_control_pin, Hw::Gpio_chip::Output, 0);
     1.8  }
     1.9  
    1.10  Spi_gpio::Spi_gpio(uint64_t frequency,
    1.11 @@ -101,7 +102,7 @@
    1.12        _clock_device->set(_clock_pin, 0);
    1.13        _data_device->set(_data_pin, data[byte] & mask ? 1 : 0);
    1.14  
    1.15 -      if ((_control_device != NULL) && (dc != NULL))
    1.16 +      if ((_control_device != NULL) && (_control_pin >= 0) && (dc != NULL))
    1.17          _control_device->set(_control_pin, dc[byte] ? 1 : 0);
    1.18  
    1.19        if (_frequency)
    1.20 @@ -128,34 +129,53 @@
    1.21  uint32_t Spi_gpio::send_units(uint32_t bytes, const uint8_t data[],
    1.22                                uint8_t unit_size, uint8_t char_size)
    1.23  {
    1.24 -  uint32_t count = bytes / unit_size;
    1.25 -  int dc[count];
    1.26 +  /* Obtain the data/command values for each unit. */
    1.27 +
    1.28 +  uint32_t chars = bytes / unit_size;
    1.29 +  int dc[chars];
    1.30 +
    1.31 +  /* Obtain the actual character bytes to be sent. */
    1.32 +
    1.33 +  int char_unit_size = ((char_size ? char_size - 1 : 0) / 8) + 1;
    1.34 +  uint8_t char_data[char_unit_size * chars];
    1.35  
    1.36    /* Traverse the byte sequence, extracting data/command bits for each unit. */
    1.37  
    1.38 -  for (uint32_t offset = 0, unit = 0; offset < bytes; offset += unit_size, unit++)
    1.39 +  for (uint32_t offset = 0, unit = 0, char_offset = 0; unit < chars;
    1.40 +       offset += unit_size, unit++, char_offset += char_unit_size)
    1.41    {
    1.42 +    /* Obtain the unit value. */
    1.43 +
    1.44 +    uint32_t value = 0;
    1.45 +
    1.46 +    for (uint8_t byte = 0; byte < unit_size; byte++)
    1.47 +      value = (value << 8) | data[offset + byte];
    1.48 +
    1.49      /* The unit size must be greater than the character size for data/command
    1.50         bits to be present. */
    1.51  
    1.52      if (unit_size * 8 <= char_size)
    1.53        dc[unit] = 0;
    1.54 +
    1.55 +    /* Extract the data/command level. */
    1.56 +
    1.57      else
    1.58 -    {
    1.59 -      /* Obtain the unit value. */
    1.60 -
    1.61 -      uint32_t value = 0;
    1.62 +      dc[unit] = value & (1 << char_size) ? 1 : 0;
    1.63  
    1.64 -      for (uint8_t byte = 0; byte < unit_size; byte++)
    1.65 -        value = (value << 8) | data[offset + byte];
    1.66 +    /* Obtain the actual character data from the input data, discarding the most
    1.67 +       significant bytes beyond the character and masking out any remaining
    1.68 +       superfluous bits, thus obtaining a whole number of bytes. */
    1.69  
    1.70 -      /* Extract the data/command level. */
    1.71 +    value = value & ((1 << char_size) - 1);
    1.72  
    1.73 -      dc[unit] = value & (1 << char_size) ? 1 : 0;
    1.74 +    for (uint8_t byte = char_unit_size; byte != 0; byte--)
    1.75 +    {
    1.76 +      char_data[char_offset + byte - 1] = value & 0xff;
    1.77 +      value >>= 8;
    1.78      }
    1.79    }
    1.80  
    1.81 -  return send_dc(bytes, data, dc);
    1.82 +  return send_dc(chars, char_data, dc);
    1.83  }
    1.84  
    1.85