libDaisy
Hardware Library for Daisy
Loading...
Searching...
No Matches
max11300.h
Go to the documentation of this file.
1#pragma once
2#ifndef DSY_MAX11300_H
3#define DSY_MAX11300_H
4
5#include "daisy_core.h"
6#include "per/spiMultislave.h"
7#include "sys/system.h"
8#include <cstring>
9
10
11namespace daisy
12{
21//MAX11300 register definitions
22#define MAX11300_DEVICE_ID 0x00
23#define MAX11300_DEVCTL 0x10
24#define MAX11300_FUNC_BASE 0x20
25#define MAX11300_GPIDAT 0x0b
26#define MAX11300_GPODAT 0x0d
27#define MAX11300_ADCDAT_BASE 0x40
28#define MAX11300_DACDAT_BASE 0x60
29#define MAX11300_TRANSPORT_BUFFER_LENGTH 41
30
31namespace MAX11300Types
32{
59
72 enum class AdcVoltageRange
73 {
74 ZERO_TO_10 = 0x0100,
75 NEGATIVE_5_TO_5 = 0x0200,
76 NEGATIVE_10_TO_0 = 0x0300,
77 ZERO_TO_2P5 = 0x0400
78 };
79
88 enum class DacVoltageRange
89 {
90 ZERO_TO_10 = 0x0100,
91 NEGATIVE_5_TO_5 = 0x0200,
92 NEGATIVE_10_TO_0 = 0x0300,
93 };
94
98 enum class Result
99 {
100 OK,
101 ERR
102 };
103
105 typedef void (*TransportCallbackFunctionPtr)(void* context,
107
114
116 typedef void (*UpdateCompleteCallbackFunctionPtr)(void* context);
117
118} // namespace MAX11300Types
119
121{
122 public:
126 template <size_t numDevices>
142
143 enum class Result
144 {
145 OK,
146 ERR
147 };
148
149 template <size_t num_devices>
151 {
153 spi_config.pin_config.mosi = config.pin_config.mosi;
154 spi_config.pin_config.miso = config.pin_config.miso;
155 spi_config.pin_config.sclk = config.pin_config.sclk;
156 const auto clamped_num_devices
157 = std::min(num_devices, MultiSlaveSpiHandle::max_num_devices_);
158 for(size_t i = 0; i < clamped_num_devices; i++)
159 spi_config.pin_config.nss[i] = config.pin_config.nss[i];
160 spi_config.periph = config.periph;
162 spi_config.datasize = 8;
165 spi_config.baud_prescaler = config.baud_prescaler;
166 // not using clamped value here on purpose to escalate errors from SPI init
167 spi_config.num_devices = num_devices;
168 num_devices_ = num_devices;
169
170 const auto result = spi_.Init(spi_config);
171
172 ready_ = result == SpiHandle::Result::OK;
173 return ready_ ? Result::OK : Result::ERR;
174 }
175
176 bool Ready() { return ready_; }
177
178 Result TransmitBlocking(size_t device_index, uint8_t* buff, size_t size)
179 {
180 if(spi_.BlockingTransmit(device_index, buff, size)
182 {
183 return Result::ERR;
184 }
185 return Result::OK;
186 }
187
188 Result
189 TransmitDma(size_t device_index,
190 uint8_t* buff,
191 size_t size,
193 void* callback_context)
194 {
195 if(spi_.DmaTransmit(device_index,
196 buff,
197 size,
198 nullptr, // start callback
200 callback_context)
202 {
203 return Result::ERR;
204 }
205 return Result::OK;
206 }
207
211 size_t size)
212 {
213 if(spi_.BlockingTransmitAndReceive(device_index, tx_buff, rx_buff, size)
215 {
216 return Result::ERR;
217 }
218
219 return Result::OK;
220 }
221
223 size_t device_index,
226 size_t size,
228 void* callback_context)
229 {
230 if(spi_.DmaTransmitAndReceive(device_index,
231 tx_buff,
232 rx_buff,
233 size,
234 nullptr, // start callback
236 callback_context)
238 {
239 return Result::ERR;
240 }
241 return Result::OK;
242 }
243
244 size_t GetNumDevices() const { return num_devices_; }
245
246 private:
248 size_t num_devices_ = 0;
249 bool ready_ = false;
250};
251
266template <typename Transport, size_t num_devices>
268{
269 public:
270 struct Config
271 {
272 typename Transport::template Config<num_devices> transport_config;
274 };
275
278
292 {
293 dma_buffer_ = dma_buffer;
294 update_complete_callback_ = nullptr;
295 update_complete_callback_context_ = nullptr;
296 run_ = false;
297
298 if(transport_.Init(config.transport_config) != Transport::Result::OK)
300
301 sequencer_.Invalidate();
302
303 for(size_t device_index = 0; device_index < transport_.GetNumDevices();
304 device_index++)
305 {
306 // First, let's verify the SPI comms, and chip presence. The DEVID register
307 // is a fixed, read-only value we can compare against to ensure we're connected.
308 if(ReadRegister(device_index, MAX11300_DEVICE_ID) != 0x0424)
309 {
311 }
312
313 // Init routine (roughly) as per the datasheet pp. 49
314 // These settings were chosen as best applicable for use in a Eurorack context.
315 // Should the need for more configurability arise, this would be the spot to do it.
316
317 // Setup the device...
318 uint16_t devctl = 0x0000;
319 // 1:0 ADCCTL[1:0] - ADC conversion mode selection = 11: Continuous sweep
320 devctl = devctl | 0x0003;
321 // 3:2 DACCTL[1:0] - DAC mode selection = 00: Sequential Update mode for DAC-configured ports.
322 devctl = devctl | 0x0000;
323 // 5:4 ADCCONV[1:0] - ADC conversion rate selection = 11: ADC conversion rate of 400ksps
324 devctl = devctl | 0x0030;
325 // 6 DACREF - DAC voltage reference selection = 1: Internal reference voltage
326 devctl = devctl | 0x0040;
327 // 7 THSHDN - Thermal shutdown enable = 1: Thermal shutdown function enabled.
328 devctl = devctl | 0x0080;
329 // 10:8 TMPCTL[2:0] - Temperature monitor selection = 001: Internal temperature monitor enabled
330 devctl = devctl | 0x0100;
331 // 11 TMPPER - Temperature conversion time control = 0 (Default)
332 // 12 RS_CANCEL - Temperature sensor series resistor cancellation mode = 0 (Default)
333 // 13 LPEN - Power mode selection = 0 (Default)
334 // 14 BRST - Serial interface burst-mode selection = 1: Contextual address incrementing mode
335 devctl = devctl | 0x4000;
336 // 15 RESET - Soft reset control = 0 (Default)
337
338 // Write the device configuration
339 if(WriteRegister(device_index, MAX11300_DEVCTL, devctl)
341 {
343 }
344 // Verify our configuration was written...
345 if(ReadRegister(device_index, MAX11300_DEVCTL) != devctl)
346 {
348 }
349
350 // Add a delay as recommended in the datasheet.
351 DelayUs(200);
352
353 // Set all pins to the default high impedance state...
354 for(uint8_t i = 0; i <= MAX11300Types::Pin::PIN_19; i++)
355 {
356 PinConfig pin_cfg;
357 pin_cfg.Defaults();
358 devices_[device_index].pin_configurations_[i] = pin_cfg;
359 SetPinConfig(device_index, static_cast<MAX11300Types::Pin>(i));
360 }
361 }
362
364 }
365
368 float threshold_voltage)
369 {
370 auto& device = devices_[device_index];
371
372 if(threshold_voltage > 5.0f)
373 threshold_voltage = 5.0f;
374
375 if(threshold_voltage < 0.0f)
376 threshold_voltage = 0.0f;
377
378 device.pin_configurations_[pin].Defaults();
379 device.pin_configurations_[pin].mode = PinMode::GPI;
380 device.pin_configurations_[pin].threshold = threshold_voltage;
381
382 return SetPinConfig(device_index, pin);
383 }
384
387 float output_voltage)
388 {
389 auto& device = devices_[device_index];
390
391 if(output_voltage > 5.0f)
392 output_voltage = 5.0f;
393
394 if(output_voltage < 0.0f)
395 output_voltage = 0.0f;
396
397 device.pin_configurations_[pin].Defaults();
398 device.pin_configurations_[pin].mode = PinMode::GPO;
399 device.pin_configurations_[pin].threshold = output_voltage;
400
401 return SetPinConfig(device_index, pin);
402 }
403
405 ConfigurePinAsAnalogRead(size_t device_index,
408 {
409 auto& device = devices_[device_index];
410
411 device.pin_configurations_[pin].Defaults();
412 device.pin_configurations_[pin].mode = PinMode::ANALOG_IN;
413 device.pin_configurations_[pin].range.adc = range;
414
415 return SetPinConfig(device_index, pin);
416 }
417
419 ConfigurePinAsAnalogWrite(size_t device_index,
422 {
423 auto& device = devices_[device_index];
424
425 device.pin_configurations_[pin].Defaults();
426 device.pin_configurations_[pin].mode = PinMode::ANALOG_OUT;
427 device.pin_configurations_[pin].range.dac = range;
428
429 return SetPinConfig(device_index, pin);
430 }
431
432
433 MAX11300Types::Result DisablePin(size_t device_index, Pin pin)
434 {
435 auto& device = devices_[device_index];
436 device.pin_configurations_[pin].Defaults();
437 return SetPinConfig(device_index, pin);
438 }
439
448 uint16_t ReadAnalogPinRaw(size_t device_index, MAX11300Types::Pin pin) const
449 {
450 auto& device = devices_[device_index];
451
452 if(device.pin_configurations_[pin].value == nullptr)
453 {
454 return 0;
455 }
456 return __builtin_bswap16(*device.pin_configurations_[pin].value);
457 }
458
467 float ReadAnalogPinVolts(size_t device_index, MAX11300Types::Pin pin) const
468 {
469 auto& device = devices_[device_index];
470
472 ReadAnalogPinRaw(device_index, pin),
473 device.pin_configurations_[pin].range.adc);
474 }
475
484 void WriteAnalogPinRaw(size_t device_index,
487 {
488 auto& device = devices_[device_index];
489
490 if(device.pin_configurations_[pin].value != nullptr)
491 {
492 *device.pin_configurations_[pin].value
494 }
495 }
496
506 void WriteAnalogPinVolts(size_t device_index,
508 float voltage)
509 {
510 auto& device = devices_[device_index];
511
512 auto pin_config = device.pin_configurations_[pin];
513 return WriteAnalogPinRaw(
514 device_index,
515 pin,
516 MAX11300Driver::VoltsTo12BitUint(voltage, pin_config.range.dac));
517 }
518
527 bool ReadDigitalPin(size_t device_index, MAX11300Types::Pin pin) const
528 {
529 auto& device = devices_[device_index];
530
532 {
533 return static_cast<bool>((device.gpi_buffer_[4] >> (pin - 16)) & 1);
534 }
535 else if(pin > MAX11300Types::Pin::PIN_7)
536 {
537 return static_cast<bool>((device.gpi_buffer_[1] >> (pin - 8)) & 1);
538 }
539 else
540 {
541 return static_cast<bool>((device.gpi_buffer_[2] >> pin) & 1);
542 }
543 }
544
553 void
554 WriteDigitalPin(size_t device_index, MAX11300Types::Pin pin, bool value)
555 {
556 auto& device = devices_[device_index];
557
558 // (void) pin;
559 // (void) value;
560 if(value)
561 {
563 {
564 device.gpo_buffer_[4] |= (1 << (pin - 16));
565 }
566 else if(pin > MAX11300Types::Pin::PIN_7)
567 {
568 device.gpo_buffer_[1] |= (1 << (pin - 8));
569 }
570 else
571 {
572 device.gpo_buffer_[2] |= (1 << pin);
573 }
574 }
575 else
576 {
578 {
579 device.gpo_buffer_[4] &= ~(1 << (pin - 16));
580 }
581 else if(pin > MAX11300Types::Pin::PIN_7)
582 {
583 device.gpo_buffer_[1] &= ~(1 << (pin - 8));
584 }
585 else
586 {
587 device.gpo_buffer_[2] &= ~(1 << pin);
588 }
589 }
590 }
591
611 = nullptr,
612 void* complete_callback_context = nullptr)
613 {
614 if(sequencer_.IsBusy() && run_)
615 {
616 // When the sequencer is currently busy, we can just return right away, and only
617 // update the callbacks
618 update_complete_callback_ = complete_callback;
619 update_complete_callback_context_ = complete_callback_context;
621 }
622
623 run_ = true;
624 update_complete_callback_ = complete_callback;
625 update_complete_callback_context_ = complete_callback_context;
626
627 sequencer_.current_device_ = 0;
628 sequencer_.current_step_ = UpdateSequencer::first_step_;
629 ContinueUpdate();
630
632 }
633
635 void Stop() { run_ = false; }
636
647 {
648 float vmax = 0;
649 float vmin = 0;
650 float vscaler = 0;
651 switch(range)
652 {
654 vmin = -10;
655 vmax = 0;
656 vscaler = 4095.0f / (vmax - vmin);
657 break;
659 vmin = -5;
660 vmax = 5;
661 vscaler = 4095.0f / (vmax - vmin);
662 break;
664 vmin = 0;
665 vmax = 10;
666 vscaler = 4095.0f / (vmax - vmin);
667 break;
668 }
669 // Clamp...
670 if(volts > vmax)
671 volts = vmax;
672
673 if(volts < vmin)
674 volts = vmin;
675
676 return static_cast<uint16_t>((volts - vmin) * vscaler);
677 }
678
688 static float TwelveBitUintToVolts(uint16_t value,
690 {
691 float vmax = 0;
692 float vmin = 0;
693 float vscaler = 0;
694 switch(range)
695 {
697 vmin = -10;
698 vmax = 0;
699 vscaler = (vmax - vmin) / 4095;
700 break;
702 vmin = -5;
703 vmax = 5;
704 vscaler = (vmax - vmin) / 4095;
705 break;
707 vmin = 0;
708 vmax = 10;
709 vscaler = (vmax - vmin) / 4095;
710 break;
712 vmin = 0;
713 vmax = 2.5;
714 vscaler = (vmax - vmin) / 4095;
715 break;
716 }
717 // Clamp...
718 if(value > 4095)
719 value = 4095;
720
721 return (value * vscaler) + vmin;
722 }
723
724 private:
730 enum class PinMode
731 {
732 NONE = 0x0000, // Mode 0 (High impedance)
733 GPI = 0x1000, // Mode 1
734 GPO = 0x3000, // Mode 3
735 ANALOG_OUT = 0x5000, // Mode 5
736 ANALOG_IN = 0x7000, // Mode 7
737 };
738
743 struct PinConfig
744 {
745 PinMode mode;
746 union
747 {
750 } range;
757 float threshold;
762 uint16_t* value;
766 void Defaults()
767 {
768 mode = PinMode::NONE;
770 threshold = 0.0f;
771 value = nullptr;
772 }
773 };
774
781 MAX11300Types::Result SetPinConfig(size_t device_index,
783 {
784 uint16_t pin_func_cfg = 0x0000;
785 auto& device = devices_[device_index];
786
787 if(device.pin_configurations_[pin].mode != PinMode::NONE)
788 {
789 // Set the pin to high impedance mode before changing (as per the datasheet).
790 WriteRegister(device_index, MAX11300_FUNC_BASE + pin, 0x0000);
791 // According to the datasheet, the amount of time necessary for the pin to
792 // switch to high impedance mode depends on the prior configuration.
793 // The worst case recommended wait time seems to be 1ms.
794 DelayUs(1000);
795 }
796
797 // Apply the pin configuration
798 pin_func_cfg
799 = pin_func_cfg
800 | static_cast<uint16_t>(device.pin_configurations_[pin].mode);
801
802 if(device.pin_configurations_[pin].mode == PinMode::ANALOG_OUT)
803 {
804 pin_func_cfg |= static_cast<uint16_t>(
805 device.pin_configurations_[pin].range.dac);
806 }
807 else if(device.pin_configurations_[pin].mode == PinMode::ANALOG_IN)
808 {
809 // In ADC mode we'll average 128 samples per Update
810 pin_func_cfg = pin_func_cfg | 0x00e0
811 | static_cast<uint16_t>(
812 device.pin_configurations_[pin].range.adc);
813 }
814 else if(device.pin_configurations_[pin].mode == PinMode::GPI)
815 {
816 // The DAC data register for that port needs to be set to the value corresponding to the
817 // intended input threshold voltage. Any input voltage above that programmed threshold is
818 // reported as a logic one. The input voltage must be between 0V and 5V.
819 // It may take up to 1ms for the threshold voltage to be effective
820 WriteRegister(device_index,
821 (MAX11300_DACDAT_BASE + pin),
823 device.pin_configurations_[pin].threshold,
824 device.pin_configurations_[pin].range.dac));
825 }
826 else if(device.pin_configurations_[pin].mode == PinMode::GPO)
827 {
828 // The port’s DAC data register needs to be set first. It may require up to 1ms for the
829 // port to be ready to produce the desired logic one level.
830 WriteRegister(device_index,
831 (MAX11300_DACDAT_BASE + pin),
833 device.pin_configurations_[pin].threshold,
834 device.pin_configurations_[pin].range.dac));
835 }
836
837 // Write the configuration now...
838 if(WriteRegister(device_index, MAX11300_FUNC_BASE + pin, pin_func_cfg)
840 {
842 }
843
844 // Wait for 1ms as per the datasheet
845 DelayUs(1000);
846
847 // Verify our configuration was written
848 if(ReadRegister(device_index, MAX11300_FUNC_BASE + pin) != pin_func_cfg)
849 {
851 }
852
853 // Update and re-index the pin configuration now...
854 UpdatePinConfig(device_index);
855
857 }
858
862 MAX11300Types::Result UpdatePinConfig(size_t device_index)
863 {
864 // TODO
865 auto& device = devices_[device_index];
866
867 // Zero everything out...
868 std::memset(device.dac_buffer_, 0, sizeof(device.dac_buffer_));
869 std::memset(device.adc_buffer_, 0, sizeof(device.adc_buffer_));
870 std::memset(device.gpi_buffer_, 0, sizeof(device.gpi_buffer_));
871 std::memset(device.gpo_buffer_, 0, sizeof(device.gpo_buffer_));
872
873 device.dac_pin_count_ = 0;
874 device.adc_pin_count_ = 0;
875 device.gpi_pin_count_ = 0;
876 device.gpo_pin_count_ = 0;
877
878 for(uint8_t i = 0; i <= MAX11300Types::Pin::PIN_19; i++)
879 {
880 MAX11300Types::Pin pin = static_cast<MAX11300Types::Pin>(i);
881
882 // Always reset the value pointer first...
883 device.pin_configurations_[i].value = nullptr;
884
885 if(device.pin_configurations_[i].mode == PinMode::ANALOG_OUT)
886 {
887 device.dac_pin_count_++;
888 if(device.dac_pin_count_ == 1)
889 {
890 // If this is the first pin of this type, we need to set
891 // the initial address of the dac_buffer_ to point at this pin.
892 // The ordering of subsequent pins is known by the MAX11300.
893 device.dac_buffer_[0] = (MAX11300_DACDAT_BASE + pin) << 1;
894 }
895 // set the pin_config.value to a pointer at the appropriate
896 // index of the dac_buffer...
897 device.pin_configurations_[i].value
898 = reinterpret_cast<uint16_t*>(
899 &device.dac_buffer_[(2 * device.dac_pin_count_) - 1]);
900 }
901 else if(device.pin_configurations_[i].mode == PinMode::ANALOG_IN)
902 {
903 device.adc_pin_count_++;
904 if(device.adc_pin_count_ == 1)
905 {
906 // If this is the first pin of this type, we need to set
907 // the initial address of the adc_buffer_ to point at this pin.
908 // The ordering of subsequent pins is known by the MAX11300.
909 device.adc_first_adress
910 = ((MAX11300_ADCDAT_BASE + pin) << 1) | 1;
911 }
912 // set the pin_config.value to a pointer at the appropriate
913 // index of the adc_buffer...
914 device.pin_configurations_[i].value
915 = reinterpret_cast<uint16_t*>(
916 &device.adc_buffer_[(2 * device.adc_pin_count_) - 1]);
917 }
918 else if(device.pin_configurations_[i].mode == PinMode::GPI)
919 {
920 device.gpi_pin_count_++;
921 }
922 else if(device.pin_configurations_[i].mode == PinMode::GPO)
923 {
924 device.gpo_pin_count_++;
925 }
926 }
927
929 }
930
931 // This is just a wrapper for System::DelayUs to allow it to be
932 // excluded from the unit tests without dirtying up the code so much
933 void DelayUs(uint32_t delay)
934 {
935 (void)delay;
936#ifndef UNIT_TEST
937 System::DelayUs(delay);
938#endif
939 }
940
946 uint16_t ReadRegister(size_t device_index, uint8_t address)
947 {
948 uint16_t val = 0;
949 ReadRegister(device_index, address, &val, 1);
950 return val;
951 }
952
960 MAX11300Types::Result ReadRegister(size_t device_index,
961 uint8_t address,
962 uint16_t* values,
963 size_t size)
964 {
965 size_t rx_length = (size * 2) + 1;
966 uint8_t rx_buff[MAX11300_TRANSPORT_BUFFER_LENGTH] = {};
967 uint8_t tx_buff[MAX11300_TRANSPORT_BUFFER_LENGTH] = {};
968 tx_buff[0] = (address << 1) | 1;
969
970 if(transport_.TransmitAndReceiveBlocking(
971 device_index, tx_buff, rx_buff, rx_length)
972 != Transport::Result::OK)
973 {
975 }
976
977 size_t rx_idx = 1;
978 for(size_t i = 0; i < size; i++)
979 {
980 values[i] = static_cast<uint16_t>((rx_buff[rx_idx] << 8)
981 + rx_buff[rx_idx + 1]);
982 rx_idx = rx_idx + 2;
983 }
985 }
986
994 WriteRegister(size_t device_index, uint8_t address, uint16_t value)
995 {
996 return WriteRegister(device_index, address, &value, 1);
997 }
998
1006 MAX11300Types::Result WriteRegister(size_t device_index,
1007 uint8_t address,
1008 uint16_t* values,
1009 size_t size)
1010 {
1011 size_t tx_size = (size * 2) + 1;
1012 uint8_t tx_buff[MAX11300_TRANSPORT_BUFFER_LENGTH] = {};
1013 tx_buff[0] = (address << 1);
1014
1015 size_t tx_idx = 1;
1016 for(size_t i = 0; i < size; i++)
1017 {
1018 tx_buff[tx_idx++] = static_cast<uint8_t>(values[i] >> 8);
1019 tx_buff[tx_idx++] = static_cast<uint8_t>(values[i]);
1020 }
1021
1022 if(transport_.TransmitBlocking(device_index, tx_buff, tx_size)
1023 == Transport::Result::OK)
1024 {
1026 }
1027
1029 }
1030
1031
1039 MAX11300Types::Result ReadModifyWriteRegister(size_t device_index,
1040 uint8_t address,
1041 uint16_t mask,
1042 uint16_t value)
1043 {
1044 uint16_t reg = ReadRegister(device_index, address);
1045 reg = (reg & ~mask) | (uint16_t)(value);
1046 return WriteRegister(device_index, address, reg);
1047 }
1048
1049 void ContinueUpdate()
1050 {
1051 // read results from the transmission that was just completed
1052 switch(sequencer_.current_step_)
1053 {
1054 case UpdateSequencer::Step::start:
1055 sequencer_.current_device_ = 0;
1056 sequencer_.current_step_ = UpdateSequencer::Step::updateDac;
1057 break;
1058 case UpdateSequencer::Step::updateDac:
1059 // nothing to read back; we only sent data
1060 sequencer_.current_step_ = UpdateSequencer::Step::updateAdc;
1061 break;
1062 case UpdateSequencer::Step::updateAdc:
1063 {
1064 // read back rx data
1065 const size_t size
1066 = (devices_[sequencer_.current_device_].adc_pin_count_ * 2)
1067 + 1;
1068 memcpy(devices_[sequencer_.current_device_].adc_buffer_,
1069 dma_buffer_->rx_buffer,
1070 size);
1071 sequencer_.current_step_ = UpdateSequencer::Step::updateGpo;
1072 }
1073 break;
1074 case UpdateSequencer::Step::updateGpo:
1075 // nothing to read back; we only sent data
1076 sequencer_.current_step_ = UpdateSequencer::Step::updateGpi;
1077 break;
1078 case UpdateSequencer::Step::updateGpi:
1079 {
1080 // read back rx data
1081 const size_t size
1082 = sizeof(devices_[sequencer_.current_device_].gpi_buffer_);
1083 memcpy(devices_[sequencer_.current_device_].gpi_buffer_,
1084 dma_buffer_->rx_buffer,
1085 size);
1086
1087 sequencer_.current_device_++;
1088 sequencer_.current_step_ = UpdateSequencer::Step::updateDac;
1089 }
1090 break;
1091 }
1092
1093 bool done = false;
1094 while(!done)
1095 {
1096 if(sequencer_.current_device_ >= num_devices)
1097 {
1098 sequencer_.Invalidate();
1099 if(update_complete_callback_)
1100 update_complete_callback_(
1101 update_complete_callback_context_);
1102 // retrigger if not stopped
1103 if(run_)
1104 {
1105 sequencer_.current_device_ = 0;
1106 sequencer_.current_step_ = UpdateSequencer::Step::updateDac;
1107 }
1108 else
1109 return; // all devices complete, no retriggering
1110 }
1111
1112 auto& device = devices_[sequencer_.current_device_];
1113
1114 switch(sequencer_.current_step_)
1115 {
1116 case UpdateSequencer::Step::updateDac:
1117 if(device.dac_pin_count_ > 0)
1118 {
1119 // This is a burst transaction utilizing the contextual addressing
1120 // scheme of the MAX11300. See the datasheet @ pp. 30
1121 //
1122 // We've prefixed the dac_buffer_ to point at the first dac pin to be written to.
1123 // Subsequent DAC pins are written in their absolute order (0-19) if configured as such.
1124 // For example:
1125 // [1st_dac_pin_addr],[1st_dac_pin_msb],[1st_dac_pin_lsb],[2nd_dac_pin_msb],[2nd_dac_pin_lsb]...
1126 //
1127 // The size of the transaction is determined by the number of configured dac pins,
1128 // plus one byte for the initial pin address.
1129 size_t tx_size = (device.dac_pin_count_ * 2) + 1;
1130 memcpy(dma_buffer_->tx_buffer,
1131 device.dac_buffer_,
1132 tx_size);
1133 transport_.TransmitDma(sequencer_.current_device_,
1134 dma_buffer_->tx_buffer,
1135 tx_size,
1136 &DmaCompleteCallback,
1137 this);
1138 done = true;
1139 }
1140 else
1141 {
1142 sequencer_.current_step_
1143 = UpdateSequencer::Step::updateAdc;
1144 done = false; // cycle again
1145 }
1146 break;
1147 case UpdateSequencer::Step::updateAdc:
1148 if(device.adc_pin_count_ > 0)
1149 {
1150 // Reading ADC pins is a burst transaction approximately the same as the DAC transaction
1151 // as described above...
1152 size_t size = (device.adc_pin_count_ * 2) + 1;
1153 dma_buffer_->tx_buffer[0] = device.adc_first_adress;
1154 // clear the rest of the buffer (it may contain stuff from a previous transaction)
1155 for(size_t i = 1; i < size; i++)
1156 dma_buffer_->tx_buffer[i] = 0x00;
1157 transport_.TransmitAndReceiveDma(
1158 sequencer_.current_device_,
1159 dma_buffer_->tx_buffer,
1160 dma_buffer_->rx_buffer,
1161 size,
1162 &DmaCompleteCallback,
1163 this);
1164 done = true;
1165 }
1166 else
1167 {
1168 sequencer_.current_step_
1169 = UpdateSequencer::Step::updateGpo;
1170 done = false; // cycle again
1171 }
1172 break;
1173 case UpdateSequencer::Step::updateGpo:
1174 if(device.gpo_pin_count_ > 0)
1175 {
1176 // Writing GPO pins is a single 5 byte transaction, with the first byte being the
1177 // the GPO data register, and the subsequent 4 bytes containing the state of the
1178 // GPO ports to be written.
1179 memcpy(dma_buffer_->tx_buffer,
1180 device.gpo_buffer_,
1181 sizeof(device.gpo_buffer_));
1182 dma_buffer_->tx_buffer[0] = (MAX11300_GPODAT << 1);
1183 transport_.TransmitDma(sequencer_.current_device_,
1184 dma_buffer_->tx_buffer,
1185 sizeof(device.gpo_buffer_),
1186 &DmaCompleteCallback,
1187 this);
1188 done = true;
1189 }
1190 else
1191 {
1192 sequencer_.current_step_
1193 = UpdateSequencer::Step::updateGpi;
1194 done = false; // cycle again
1195 }
1196 break;
1197
1198 case UpdateSequencer::Step::updateGpi:
1199 if(device.gpi_pin_count_ > 0)
1200 {
1201 // Reading GPI pins is a single, 5 byte, full-duplex transaction with the first
1202 // and only TX byte being the GPI register.
1203 dma_buffer_->tx_buffer[0] = (MAX11300_GPIDAT << 1) | 1;
1204 // clear the rest of the buffer (it may contain stuff from a previous transaction)
1205 for(size_t i = 1; i < sizeof(device.gpi_buffer_); i++)
1206 dma_buffer_->tx_buffer[i] = 0x00;
1207 transport_.TransmitAndReceiveDma(
1208 sequencer_.current_device_,
1209 dma_buffer_->tx_buffer,
1210 dma_buffer_->rx_buffer,
1211 sizeof(device.gpi_buffer_),
1212 &DmaCompleteCallback,
1213 this);
1214 done = true;
1215 }
1216 else
1217 {
1218 sequencer_.current_step_
1219 = UpdateSequencer::Step::updateDac;
1220 sequencer_
1221 .current_device_++; // go to next chip in sequence
1222 done = false; // cycle again
1223 }
1224 break;
1225 default: break;
1226 }
1227 }
1228 }
1229
1230 static void DmaCompleteCallback(void* context, SpiHandle::Result result)
1231 {
1232 auto& driver = *reinterpret_cast<MAX11300Driver*>(context);
1233 if(result == SpiHandle::Result::OK)
1234 {
1235 driver.ContinueUpdate();
1236 }
1237 else
1238 {
1239 driver.sequencer_.Invalidate();
1240 }
1241 }
1242
1243 MAX11300Types::DmaBuffer* dma_buffer_;
1244
1245 struct Device
1246 {
1247 PinConfig pin_configurations_[20];
1248 uint8_t dac_pin_count_;
1249 uint8_t adc_pin_count_;
1250 uint8_t gpi_pin_count_;
1251 uint8_t gpo_pin_count_;
1252 uint8_t dac_buffer_[41];
1253 uint8_t adc_first_adress;
1254 uint8_t adc_buffer_[41];
1255 uint8_t gpi_buffer_[5];
1256 uint8_t gpo_buffer_[5];
1257 };
1258 Device devices_[num_devices];
1259
1260 struct UpdateSequencer
1261 {
1262 size_t current_device_ = 0;
1263 enum class Step
1264 {
1265 start = 0,
1266 updateDac,
1267 updateAdc,
1268 updateGpo,
1269 updateGpi,
1270 };
1271 static constexpr auto first_step_ = Step::start;
1272 static constexpr auto last_step_ = Step::updateGpi;
1273 Step current_step_ = first_step_;
1274 bool IsBusy() const { return current_device_ < num_devices; }
1275 void Invalidate()
1276 {
1277 current_device_ = num_devices;
1278 current_step_ = first_step_;
1279 }
1280 } sequencer_;
1281
1282 Transport transport_;
1283
1284 MAX11300Types::UpdateCompleteCallbackFunctionPtr update_complete_callback_;
1285 void* update_complete_callback_context_;
1286 bool run_;
1287};
1288template <size_t num_devices = 1>
1291
1295}; // namespace daisy
1296
1297#endif
Definition leddriver.h:33
void Init(I2CHandle i2c, const uint8_t(&addresses)[numDrivers], DmaBuffer dma_buffer_a, DmaBuffer dma_buffer_b, Pin oe_pin=Pin(PORTX, 0))
Definition leddriver.h:65
Device Driver for the MAX11300 20 port ADC/DAC/GPIO device.
Definition max11300.h:268
MAX11300Driver()
Definition max11300.h:276
MAX11300Types::Result ConfigurePinAsAnalogWrite(size_t device_index, MAX11300Types::Pin pin, MAX11300Types::DacVoltageRange range)
Definition max11300.h:419
MAX11300Types::Result ConfigurePinAsDigitalRead(size_t device_index, MAX11300Types::Pin pin, float threshold_voltage)
Definition max11300.h:366
uint16_t ReadAnalogPinRaw(size_t device_index, MAX11300Types::Pin pin) const
Definition max11300.h:448
void WriteAnalogPinRaw(size_t device_index, MAX11300Types::Pin pin, uint16_t raw_value)
Definition max11300.h:484
static uint16_t VoltsTo12BitUint(float volts, MAX11300Types::DacVoltageRange range)
Definition max11300.h:645
void WriteAnalogPinVolts(size_t device_index, MAX11300Types::Pin pin, float voltage)
Definition max11300.h:506
bool ReadDigitalPin(size_t device_index, MAX11300Types::Pin pin) const
Definition max11300.h:527
MAX11300Types::Result Start(MAX11300Types::UpdateCompleteCallbackFunctionPtr complete_callback=nullptr, void *complete_callback_context=nullptr)
Definition max11300.h:610
MAX11300Types::Result Init(Config config, MAX11300Types::DmaBuffer *dma_buffer)
Definition max11300.h:290
void Stop()
Definition max11300.h:635
MAX11300Types::Result ConfigurePinAsAnalogRead(size_t device_index, MAX11300Types::Pin pin, MAX11300Types::AdcVoltageRange range)
Definition max11300.h:405
float ReadAnalogPinVolts(size_t device_index, MAX11300Types::Pin pin) const
Definition max11300.h:467
MAX11300Types::Result ConfigurePinAsDigitalWrite(size_t device_index, MAX11300Types::Pin pin, float output_voltage)
Definition max11300.h:385
~MAX11300Driver()
Definition max11300.h:277
MAX11300Types::Result DisablePin(size_t device_index, Pin pin)
Definition max11300.h:433
void WriteDigitalPin(size_t device_index, MAX11300Types::Pin pin, bool value)
Definition max11300.h:554
static float TwelveBitUintToVolts(uint16_t value, MAX11300Types::AdcVoltageRange range)
Definition max11300.h:688
Definition max11300.h:121
Result TransmitAndReceiveBlocking(size_t device_index, uint8_t *tx_buff, uint8_t *rx_buff, size_t size)
Definition max11300.h:208
size_t GetNumDevices() const
Definition max11300.h:244
Result Init(Config< num_devices > config)
Definition max11300.h:150
Result TransmitDma(size_t device_index, uint8_t *buff, size_t size, MAX11300Types::TransportCallbackFunctionPtr complete_callback, void *callback_context)
Definition max11300.h:189
Result TransmitBlocking(size_t device_index, uint8_t *buff, size_t size)
Definition max11300.h:178
bool Ready()
Definition max11300.h:176
Result TransmitAndReceiveDma(size_t device_index, uint8_t *tx_buff, uint8_t *rx_buff, size_t size, MAX11300Types::TransportCallbackFunctionPtr complete_callback, void *callback_context)
Definition max11300.h:222
Result
Definition max11300.h:144
Definition spiMultislave.h:21
SpiHandle::Result Init(const Config &config)
static constexpr size_t max_num_devices_
Definition spiMultislave.h:23
SpiHandle::Result BlockingTransmit(size_t device_index, uint8_t *buff, size_t size, uint32_t timeout=100)
SpiHandle::Result BlockingTransmitAndReceive(size_t device_index, uint8_t *tx_buff, uint8_t *rx_buff, size_t size, uint32_t timeout=100)
SpiHandle::Result DmaTransmit(size_t device_index, uint8_t *buff, size_t size, SpiHandle::StartCallbackFunctionPtr start_callback, SpiHandle::EndCallbackFunctionPtr end_callback, void *callback_context)
SpiHandle::Result DmaTransmitAndReceive(size_t device_index, uint8_t *tx_buff, uint8_t *rx_buff, size_t size, SpiHandle::StartCallbackFunctionPtr start_callback, SpiHandle::EndCallbackFunctionPtr end_callback, void *callback_context)
Result
Definition spi.h:116
static void DelayUs(uint32_t delay_us)
#define MAX11300_ADCDAT_BASE
Definition max11300.h:27
#define MAX11300_GPODAT
Definition max11300.h:26
#define MAX11300_FUNC_BASE
Definition max11300.h:24
#define MAX11300_DEVCTL
Definition max11300.h:23
#define MAX11300_DACDAT_BASE
Definition max11300.h:28
#define MAX11300_TRANSPORT_BUFFER_LENGTH
Definition max11300.h:29
#define MAX11300_DEVICE_ID
Definition max11300.h:22
#define MAX11300_GPIDAT
Definition max11300.h:25
Result
Definition max11300.h:99
DacVoltageRange
Definition max11300.h:89
void(* TransportCallbackFunctionPtr)(void *context, SpiHandle::Result result)
Definition max11300.h:105
AdcVoltageRange
Definition max11300.h:73
Pin
Definition max11300.h:37
@ PIN_19
Definition max11300.h:57
@ PIN_8
Definition max11300.h:46
@ PIN_1
Definition max11300.h:39
@ PIN_7
Definition max11300.h:45
@ PIN_2
Definition max11300.h:40
@ PIN_0
Definition max11300.h:38
@ PIN_13
Definition max11300.h:51
@ PIN_5
Definition max11300.h:43
@ PIN_18
Definition max11300.h:56
@ PIN_6
Definition max11300.h:44
@ PIN_12
Definition max11300.h:50
@ PIN_3
Definition max11300.h:41
@ PIN_15
Definition max11300.h:53
@ PIN_9
Definition max11300.h:47
@ PIN_14
Definition max11300.h:52
@ PIN_17
Definition max11300.h:55
@ PIN_11
Definition max11300.h:49
@ PIN_10
Definition max11300.h:48
@ PIN_16
Definition max11300.h:54
@ PIN_4
Definition max11300.h:42
void(* UpdateCompleteCallbackFunctionPtr)(void *context)
Definition max11300.h:116
Hardware defines and helpers for daisy field platform.
Definition index.h:2
@ PORTB
Definition daisy_core.h:178
@ PORTG
Definition daisy_core.h:183
Definition max11300.h:271
Transport::template Config< num_devices > transport_config
Definition max11300.h:272
void Defaults()
Definition max11300.h:273
Pin nss[numDevices]
Definition max11300.h:131
SpiHandle::Config::Peripheral periph
Definition max11300.h:138
SpiHandle::Config::BaudPrescaler baud_prescaler
Definition max11300.h:140
struct daisy::MAX11300MultiSlaveSpiTransport::Config::PinConfig pin_config
Definition max11300.h:110
uint8_t tx_buffer[41]
Definition max11300.h:112
uint8_t rx_buffer[41]
Definition max11300.h:111
Definition spiMultislave.h:25
SpiHandle::Config::Direction direction
Definition spiMultislave.h:35
SpiHandle::Config::ClockPhase clock_phase
Definition spiMultislave.h:38
size_t num_devices
Definition spiMultislave.h:40
struct daisy::MultiSlaveSpiHandle::Config::@19 pin_config
SpiHandle::Config::Peripheral periph
Definition spiMultislave.h:34
SpiHandle::Config::ClockPolarity clock_polarity
Definition spiMultislave.h:37
SpiHandle::Config::BaudPrescaler baud_prescaler
Definition spiMultislave.h:39
unsigned long datasize
Definition spiMultislave.h:36
representation of hardware port/pin combination
Definition daisy_core.h:193
BaudPrescaler
Definition spi.h:72
Peripheral
Definition spi.h:29