hx711-pico-c
hx711_multi.c
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2023 Daniel Robertson
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include <assert.h>
24 #include <math.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <strings.h>
28 #include "hardware/dma.h"
29 #include "hardware/gpio.h"
30 #include "hardware/irq.h"
31 #include "hardware/pio.h"
32 #include "pico/mutex.h"
33 #include "pico/platform.h"
34 #include "pico/time.h"
35 #include "pico/types.h"
36 #include "../include/hx711.h"
37 #include "../include/hx711_multi.h"
38 #include "../include/util.h"
39 
41  NULL, //...
42 };
43 
45  const hx711_multi_config_t* const config) {
46 
47  assert(config != NULL);
48 
49  assert(util_uint_in_range(
50  config->chips_len,
53 
54  assert(config->pio != NULL);
55  check_pio_param(config->pio);
56  assert(config->pio_init != NULL);
57 
58  assert(config->awaiter_prog != NULL);
59  assert(config->awaiter_prog_init != NULL);
60 
61  assert(config->reader_prog != NULL);
62  assert(config->reader_prog_init != NULL);
63 
66 
67 #ifndef NDEBUG
68  {
69  //make sure none of the data pins are also the clock pin
70  const uint l = config->data_pin_base + config->chips_len - 1;
71  for(uint i = config->data_pin_base; i <= l; ++i) {
72  assert(i != config->clock_pin);
73  }
74  }
75 #endif
76 
77 }
78 
80 
81  //adding programs and claiming state machines
82  //will panic if unable; this is appropriate.
83  hxm->_awaiter_offset = pio_add_program(
84  hxm->_pio,
85  hxm->_awaiter_prog);
86 
87  hxm->_reader_offset = pio_add_program(
88  hxm->_pio,
89  hxm->_reader_prog);
90 
98  hxm->_awaiter_sm = (uint)pio_claim_unused_sm(
99  hxm->_pio,
100  true);
101 
102  hxm->_reader_sm = (uint)pio_claim_unused_sm(
103  hxm->_pio,
104  true);
105 
106 }
107 
109 
116  hxm->_dma_channel = (uint)dma_claim_unused_channel(true);
117 
118  dma_channel_config cfg = dma_channel_get_default_config(
119  hxm->_dma_channel);
120 
133  channel_config_set_transfer_data_size(
134  &cfg,
135  DMA_SIZE_32);
136 
141  channel_config_set_read_increment(
142  &cfg,
143  false);
144 
149  channel_config_set_write_increment(
150  &cfg,
151  true);
152 
156  channel_config_set_dreq(
157  &cfg,
158  pio_get_dreq(
159  hxm->_pio,
160  hxm->_reader_sm,
161  false));
162 
168  channel_config_set_irq_quiet(
169  &cfg,
170  false);
171 
172  dma_channel_configure(
173  hxm->_dma_channel,
174  &cfg,
175  NULL, //don't set a write address yet
176  &hxm->_pio->rxf[hxm->_reader_sm], //read from reader pio program rx fifo
177  HX711_READ_BITS, //24 transfers; one for each HX711 bit
178  false); //false = don't start now
179 
180 }
181 
183 
197  dma_irqn_set_channel_enabled(
198  hxm->_dma_irq_index,
199  hxm->_dma_channel,
200  true);
201 
202  irq_set_exclusive_handler(
205 
206  irq_set_enabled(
208  true);
209 
215  pio_set_irqn_source_enabled(
216  hxm->_pio,
217  hxm->_pio_irq_index,
220  false);
221 
222  irq_set_exclusive_handler(
225 
226  irq_set_enabled(
228  true);
229 
230 }
231 
233  hx711_multi_t* const hxm) {
234 
235  assert(hx711_multi__is_initd(hxm));
236 
237  return dma_irqn_get_channel_status(
238  hxm->_dma_irq_index,
239  hxm->_dma_channel);
240 
241 }
242 
244  hx711_multi_t* const hxm) {
245 
246  assert(hx711_multi__is_initd(hxm));
247 
248  return pio_interrupt_get(
249  hxm->_pio,
251 
252 }
253 
255 
256  assert(hx711_multi__async_read_array != NULL);
257 
258  for(uint i = 0; i < HX711_MULTI_ASYNC_READ_COUNT; ++i) {
259 
260  if(hx711_multi__async_read_array[i] == NULL) {
261  continue;
262  }
263 
266  }
267 
268  }
269 
270  return NULL;
271 
272 }
273 
275 
276  assert(hx711_multi__async_read_array != NULL);
277 
278  for(uint i = 0; i < HX711_MULTI_ASYNC_READ_COUNT; ++i) {
279 
280  if(hx711_multi__async_read_array[i] == NULL) {
281  continue;
282  }
283 
286  }
287 
288  }
289 
290  return NULL;
291 
292 }
293 
295  hx711_multi_t* const hxm) {
296 
299 
301  hxm->_pio,
302  hxm->_reader_sm);
303 
304  //listen for DMA done
305  dma_irqn_set_channel_enabled(
306  hxm->_dma_irq_index,
307  hxm->_dma_channel,
308  true);
309 
311 
312  dma_channel_set_write_addr(
313  hxm->_dma_channel,
314  hxm->_buffer,
315  true); //trigger
316 
317 }
318 
320  hx711_multi_t* const hxm) {
321 
323 
324  switch(hxm->_async_state) {
327  return true;
328  default:
329  //anything else is not considered running
330  return false;
331  }
332 
333 }
334 
336  hx711_multi_t* const hxm) {
337 
338  assert(hx711_multi__is_initd(hxm));
339 
340  //stop listening for IRQs
341 
342  dma_channel_abort(hxm->_dma_channel);
343 
344  dma_irqn_set_channel_enabled(
345  hxm->_dma_irq_index,
346  hxm->_dma_channel,
347  false);
348 
349  pio_set_irqn_source_enabled(
350  hxm->_pio,
351  hxm->_pio_irq_index,
353  false);
354 
355 #ifndef HX711_NO_MUTEX
356  mutex_exit(&hxm->_mut);
357 #endif
358 
359 }
360 
361 void __isr __not_in_flash_func(hx711_multi__async_pio_irq_handler)() {
362 
363  hx711_multi_t* const hxm =
365 
368 
370 
371  //disable listening until required again
372  pio_set_irqn_source_enabled(
373  hxm->_pio,
374  hxm->_pio_irq_index,
376  false);
377 
378  irq_clear(
380 
381 }
382 
383 void __isr __not_in_flash_func(hx711_multi__async_dma_irq_handler)() {
384 
385  hx711_multi_t* const hxm =
387 
390 
392 
393  dma_irqn_acknowledge_channel(
394  hxm->_dma_irq_index,
395  hxm->_dma_channel);
396 
398 
399  irq_clear(
401  hxm->_dma_irq_index));
402 
403 }
404 
406  hx711_multi_t* const hxm) {
407 
408  assert(hx711_multi__async_read_array != NULL);
409 
410  for(uint i = 0; i < HX711_MULTI_ASYNC_READ_COUNT; ++i) {
411  if(hx711_multi__async_read_array[i] == NULL) {
413  return true;
414  }
415  }
416 
417  return false;
418 
419 }
420 
422  const hx711_multi_t* const hxm) {
423 
424  //we don't care whether it's initd at this point
425  //or whether the SMs are running; just remove it
426  //from the array
427  assert(hxm != NULL);
428  assert(hx711_multi__async_read_array != NULL);
429 
430  for(uint i = 0; i < HX711_MULTI_ASYNC_READ_COUNT; ++i) {
431  if(hx711_multi__async_read_array[i] == hxm) {
433  return;
434  }
435  }
436 
437 }
438 
439 static bool hx711_multi__is_initd(hx711_multi_t* const hxm) {
440  return hxm != NULL &&
441  hxm->_pio != NULL &&
442  pio_sm_is_claimed(hxm->_pio, hxm->_awaiter_sm) &&
443  pio_sm_is_claimed(hxm->_pio, hxm->_reader_sm) &&
444  dma_channel_is_claimed(hxm->_dma_channel) &&
445 #ifndef HX711_NO_MUTEX
446  mutex_is_initialized(&hxm->_mut) &&
447 #endif
448  irq_get_exclusive_handler(util_pio_get_irq_from_index(
449  hxm->_pio,
451  irq_get_exclusive_handler(util_dma_get_irqn(
453 }
454 
456  hx711_multi_t* const hxm) {
457  return hx711_multi__is_initd(hxm) &&
460 }
461 
463  const uint32_t* const pinvals,
464  int32_t* const values,
465  const size_t len) {
466 
467  assert(pinvals != NULL);
468  assert(values != NULL);
469  assert(len > 0);
470 
471  //construct an individual chip value by OR-ing
472  //together the bits from the pinvals array.
473  //
474  //each n-th bit of the pinvals array makes up all
475  //the bits for an individual chip. ie.:
476  //
477  //pinvals[0] contains all the 24th bit HX711 values
478  //for each chip, pinvals[1] contains all the 23rd bit
479  //values, and so on...
480  //
481  //(pinvals[0] >> 0) & 1 is the 24th HX711 bit of the 0th chip
482  //(pinvals[1] >> 0) & 1 is the 23rd HX711 bit of the 0th chip
483  //(pinvals[1] >> 2) & 1 is the 23rd HX711 bit of the 3rd chip
484  //(pinvals[23] >> 0) & 1 is the 0th HX711 bit of the 0th chip
485  //
486  //eg.
487  //rawvals[0] =
488  // ((pinvals[0] >> 0) & 1) << 24 |
489  // ((pinvals[1] >> 0) & 1) << 23 |
490  // ((pinvals[2] >> 0) & 1) << 22 |
491  //...
492  // ((pinvals[23]) >> 0) & 1) << 0;
493 
494  for(size_t chipNum = 0; chipNum < len; ++chipNum) {
495 
496  //reset to 0
497  //this is the raw value for an individual chip
498  uint32_t rawVal = 0;
499 
500  //reconstruct an individual twos comp HX711 value from pinbits
501  for(size_t bitPos = 0; bitPos < HX711_READ_BITS; ++bitPos) {
502  const uint shift = HX711_READ_BITS - bitPos - 1;
503  const uint32_t bit = (pinvals[bitPos] >> chipNum) & 1;
504  rawVal |= bit << shift;
505  }
506 
507  //then convert to a regular ones comp
508  values[chipNum] = hx711_get_twos_comp(rawVal);
509 
510  assert(hx711_is_value_valid(values[chipNum]));
511 
512  }
513 
514 }
515 
517  hx711_multi_t* const hxm,
518  const hx711_multi_config_t* const config) {
519 
520  hx711_multi__init_asert(config);
521 
522 #ifndef HX711_NO_MUTEX
523  //this doesn't need to be an interrupts-off block
524  //because the mutex will protect the hxm from reads
525  //until init returns, and the source IRQs aren't
526  //enabled anyway
527  mutex_init(&hxm->_mut);
528 #endif
529 
530  HX711_MUTEX_BLOCK(hxm->_mut,
531 
532  hxm->_clock_pin = config->clock_pin;
533  hxm->_data_pin_base = config->data_pin_base;
534  hxm->_chips_len = config->chips_len;
535 
536  hxm->_pio = config->pio;
537  hxm->_awaiter_prog = config->awaiter_prog;
538  hxm->_reader_prog = config->reader_prog;
539 
540  hxm->_pio_irq_index = config->pio_irq_index;
541  hxm->_dma_irq_index = config->dma_irq_index;
542 
544 
546 
548 
550  hxm->_data_pin_base,
551  hxm->_chips_len);
552 
554 
555  config->pio_init(hxm);
556  config->awaiter_prog_init(hxm);
557  config->reader_prog_init(hxm);
558 
561 
562  );
563 
564 }
565 
567 
568  assert(hx711_multi__is_initd(hxm));
569 
570 #ifndef HX711_NO_MUTEX
571  mutex_enter_blocking(&hxm->_mut);
572 #endif
573 
574  //make sure the disabling and removal of IRQs and
575  //handlers is atomic
577 
578  //interrupts are off, but cancel any running
579  //async reads
580  dma_channel_abort(hxm->_dma_channel);
581 
582  irq_set_enabled(
584  false);
585 
586  irq_set_enabled(
588  false);
589 
590  pio_set_irqn_source_enabled(
591  hxm->_pio,
592  hxm->_pio_irq_index,
594  false);
595 
596  dma_irqn_set_channel_enabled(
597  hxm->_dma_irq_index,
598  hxm->_dma_channel,
599  false);
600 
602 
604 
605  irq_remove_handler(
608 
609  irq_remove_handler(
612 
613  );
614 
615  //at this point it is impossible for a relevant DMA
616  //or PIO IRQ to occur, so we can turn interrupts
617  //back on
618 
620  hxm->_dma_channel,
621  true);
622 
623  pio_set_sm_mask_enabled(
624  hxm->_pio,
625  (1 << hxm->_awaiter_sm) | (1 << hxm->_reader_sm),
626  false);
627 
628  dma_channel_unclaim(
629  hxm->_dma_channel);
630 
631  pio_sm_unclaim(
632  hxm->_pio,
633  hxm->_awaiter_sm);
634 
635  pio_sm_unclaim(
636  hxm->_pio,
637  hxm->_reader_sm);
638 
639  pio_remove_program(
640  hxm->_pio,
641  hxm->_awaiter_prog,
642  hxm->_awaiter_offset);
643 
644  pio_remove_program(
645  hxm->_pio,
646  hxm->_reader_prog,
647  hxm->_reader_offset);
648 
649 #ifndef HX711_NO_MUTEX
650  mutex_exit(&hxm->_mut);
651 #endif
652 
653 }
654 
656  hx711_multi_t* const hxm,
657  const hx711_gain_t gain) {
658 
660 
661  const uint32_t gainVal = hx711_gain_to_pio_gain(gain);
662 
663  assert(hx711_is_pio_gain_valid(gain));
664 
665  pio_sm_drain_tx_fifo(
666  hxm->_pio,
667  hxm->_reader_sm);
668 
669  pio_sm_put(
670  hxm->_pio,
671  hxm->_reader_sm,
672  gainVal);
673 
675 
676  while(!hx711_multi_async_done(hxm)) {
677  tight_loop_contents();
678  }
679 
680 }
681 
683  hx711_multi_t* const hxm,
684  int32_t* const values) {
685 
687  assert(values != NULL);
688  assert(!hx711_multi__async_is_running(hxm));
689 
691  while(!hx711_multi_async_done(hxm)) {
692  tight_loop_contents();
693  }
694  hx711_multi_async_get_values(hxm, values);
695 
696 }
697 
699  hx711_multi_t* const hxm,
700  int32_t* const values,
701  const uint timeout) {
702 
704  assert(values != NULL);
705  assert(!hx711_multi__async_is_running(hxm));
706 
707  const absolute_time_t end = make_timeout_time_us(timeout);
708  bool success = false;
709 
711 
712  while(!time_reached(end)) {
713  if(hx711_multi_async_done(hxm)) {
714  success = true;
715  break;
716  }
717  }
718 
719  if(success) {
720  hx711_multi_async_get_values(hxm, values);
721  }
722  else {
723  //if timed out, cancel DMA and stop listening
724  //for IRQs and exit mutex. Do this atomically!
727  );
728  }
729 
730  return success;
731 
732 }
733 
735 
737  assert(!hx711_multi__async_is_running(hxm));
738 
739  //if starting the following statements would lead to an
740  //immediate interrupt, DMA may not be properly set up,
741  //so disable until it is
742  const uint32_t status = save_and_disable_interrupts();
743 
744 #ifndef HX711_NO_MUTEX
745  mutex_enter_blocking(&hxm->_mut);
746 #endif
747 
749 
750  //if pio interrupt is already set, we can bypass the
751  //IRQ handler and immediately trigger dma
752  if(pio_interrupt_get(hxm->_pio, HX711_MULTI_CONVERSION_DONE_IRQ_NUM)) {
754  }
755  else {
756  pio_set_irqn_source_enabled(
757  hxm->_pio,
758  hxm->_pio_irq_index,
760  true);
761  }
762 
763  restore_interrupts(status);
764 
765 }
766 
768  assert(hx711_multi__is_initd(hxm));
770 }
771 
773  hx711_multi_t* const hxm,
774  int32_t* const values) {
775  assert(hx711_multi__is_initd(hxm));
776  assert(hx711_multi_async_done(hxm));
778  hxm->_buffer,
779  values,
780  hxm->_chips_len);
781 }
782 
784  hx711_multi_t* const hxm,
785  const hx711_gain_t gain) {
786 
787  assert(hx711_multi__is_initd(hxm));
788 
789  const uint32_t pioGainVal = hx711_gain_to_pio_gain(gain);
790 
791  assert(hx711_is_pio_gain_valid(pioGainVal));
792 
793  HX711_MUTEX_BLOCK(hxm->_mut,
794 
795  gpio_put(
796  hxm->_clock_pin,
797  false);
798 
799  pio_sm_init(
800  hxm->_pio,
801  hxm->_reader_sm,
802  hxm->_reader_offset,
803  &hxm->_reader_default_config);
804 
805  pio_sm_clear_fifos(
806  hxm->_pio,
807  hxm->_reader_sm);
808 
809  //put the gain value into the reader FIFO
810  pio_sm_put(
811  hxm->_pio,
812  hxm->_reader_sm,
813  pioGainVal);
814 
815  pio_sm_init(
816  hxm->_pio,
817  hxm->_awaiter_sm,
818  hxm->_awaiter_offset,
820 
821  pio_set_sm_mask_enabled(
822  hxm->_pio,
823  (1 << hxm->_awaiter_sm) | (1 << hxm->_reader_sm),
824  true);
825 
826  );
827 
828 }
829 
831 
832  assert(hx711_multi__is_initd(hxm));
833 
834  HX711_MUTEX_BLOCK(hxm->_mut,
835 
838  );
839 
840  pio_set_sm_mask_enabled(
841  hxm->_pio,
842  (1 << hxm->_awaiter_sm) | (1 << hxm->_reader_sm),
843  false);
844 
845  gpio_put(
846  hxm->_clock_pin,
847  true);
848 
849  );
850 
851 }
852 
854  hx711_multi_t* const hxm,
855  const hx711_gain_t gain) {
856  assert(hx711_multi__is_initd(hxm));
859  hx711_multi_power_up(hxm, gain);
860 }
861 
863  hx711_multi_t* const hxm) {
865  return pio_sm_get_blocking(hxm->_pio, hxm->_awaiter_sm);
866 }
867 
869  hx711_multi_t* const hxm) {
870 
872 
873  //all chips should either be 0 or 1 which translates
874  //to a bitmask of exactly 0 or 2^chips
875  const uint32_t allReady = (uint32_t)pow(2, hxm->_chips_len);
876  const uint32_t state = hx711_multi_get_sync_state(hxm);
877 
878  return state == 0 || state == allReady;
879 
880 }
#define HX711_MUTEX_BLOCK(mut,...)
Definition: hx711.h:36
bool hx711_is_value_valid(const int32_t v)
Check whether the given value is valid for a HX711 implementation.
Definition: hx711.c:361
int32_t hx711_get_twos_comp(const uint32_t raw)
Convert a raw value from the HX711 to a 32-bit signed int.
Definition: hx711.c:231
void hx711_wait_power_down()
Convenience function for sleeping for the appropriate amount of time to allow the HX711 to power down...
Definition: hx711.c:491
bool hx711_is_pio_gain_valid(const uint32_t g)
Check whether a given value is permitted to be transmitted to a PIO State Machine to set a HX711's ga...
Definition: hx711.c:368
#define HX711_READ_BITS
Definition: hx711.h:49
hx711_gain_t
Definition: hx711.h:67
uint32_t hx711_gain_to_pio_gain(const hx711_gain_t gain)
Convert a hx711_gain_t to a numeric value appropriate for a PIO State Machine.
Definition: hx711.c:495
static void hx711_multi__async_finish(hx711_multi_t *const hxm)
Definition: hx711_multi.c:335
void hx711_multi_async_get_values(hx711_multi_t *const hxm, int32_t *const values)
Get the values from the last asynchronous read. This function is not mutex protected.
Definition: hx711_multi.c:772
void hx711_multi_power_up(hx711_multi_t *const hxm, const hx711_gain_t gain)
Definition: hx711_multi.c:783
void hx711_multi__init_asert(const hx711_multi_config_t *const config)
Definition: hx711_multi.c:44
void hx711_multi_init(hx711_multi_t *const hxm, const hx711_multi_config_t *const config)
Definition: hx711_multi.c:516
void hx711_multi_set_gain(hx711_multi_t *const hxm, const hx711_gain_t gain)
Sets the HX711s' gain.
Definition: hx711_multi.c:655
bool hx711_multi__async_dma_irq_is_set(hx711_multi_t *const hxm)
Whether a given hxm is the cause of the current DMA IRQ.
Definition: hx711_multi.c:232
hx711_multi_t *const hx711_multi__async_get_dma_irq_request()
Get the hxm which caused the current DMA IRQ. Returns NULL if none found.
Definition: hx711_multi.c:254
void hx711_multi__async_start_dma(hx711_multi_t *const hxm)
Triggers DMA reading; moves request state from WAITING to READING.
Definition: hx711_multi.c:294
bool hx711_multi__async_add_reader(hx711_multi_t *const hxm)
Adds hxm to the array for ISR access. Returns false if no space.
Definition: hx711_multi.c:405
void hx711_multi_power_down(hx711_multi_t *const hxm)
Definition: hx711_multi.c:830
static bool hx711_multi__is_state_machines_enabled(hx711_multi_t *const hxm)
Definition: hx711_multi.c:455
void hx711_multi__init_irq(hx711_multi_t *const hxm)
Subroutine for initialising IRQ.
Definition: hx711_multi.c:182
bool hx711_multi_get_values_timeout(hx711_multi_t *const hxm, int32_t *const values, const uint timeout)
Fill an array with one value from each HX711, timing out if failing to obtain values within the timeo...
Definition: hx711_multi.c:698
bool hx711_multi_async_done(hx711_multi_t *const hxm)
Check whether an asynchronous read is complete. This function is not mutex protected.
Definition: hx711_multi.c:767
hx711_multi_t *const hx711_multi__async_get_pio_irq_request()
Get the hxm which caused the current PIO IRQ. Returns NULL if none found.
Definition: hx711_multi.c:274
void hx711_multi_async_start(hx711_multi_t *const hxm)
Start an asynchronos read. This function is not mutex protected.
Definition: hx711_multi.c:734
void __isr __not_in_flash_func() hx711_multi__async_dma_irq_handler()
ISR handler for DMA IRQs.
Definition: hx711_multi.c:383
bool hx711_multi__async_is_running(hx711_multi_t *const hxm)
Check whether an async read is currently occurring.
Definition: hx711_multi.c:319
static bool hx711_multi__is_initd(hx711_multi_t *const hxm)
Definition: hx711_multi.c:439
void hx711_multi__init_pio(hx711_multi_t *const hxm)
Subroutine for initialising PIO.
Definition: hx711_multi.c:79
void hx711_multi_sync(hx711_multi_t *const hxm, const hx711_gain_t gain)
Attempt to synchronise all connected chips. This does not include a settling time.
Definition: hx711_multi.c:853
void hx711_multi_get_values(hx711_multi_t *const hxm, int32_t *const values)
Fill an array with one value from each HX711. Blocks until values are obtained.
Definition: hx711_multi.c:682
void hx711_multi_pinvals_to_values(const uint32_t *const pinvals, int32_t *const values, const size_t len)
Convert an array of pinvals to regular HX711 values.
Definition: hx711_multi.c:462
void __isr __not_in_flash_func() hx711_multi__async_pio_irq_handler()
ISR handler for PIO IRQs.
Definition: hx711_multi.c:361
bool hx711_multi_is_syncd(hx711_multi_t *const hxm)
Determines whether all chips are in sync.
Definition: hx711_multi.c:868
uint32_t hx711_multi_get_sync_state(hx711_multi_t *const hxm)
Returns the state of each chip as a bitmask. The 0th bit is the first chip, 1th bit is the second,...
Definition: hx711_multi.c:862
void hx711_multi_close(hx711_multi_t *const hxm)
Stop communication with all HX711s.
Definition: hx711_multi.c:566
bool hx711_multi__async_pio_irq_is_set(hx711_multi_t *const hxm)
Whether a given hxm is the cause of the current PIO IRQ.
Definition: hx711_multi.c:243
void hx711_multi__init_dma(hx711_multi_t *const hxm)
Subroutine for initialising DMA.
Definition: hx711_multi.c:108
hx711_multi_t * hx711_multi__async_read_array[]
Array of hxm for ISR to access. This is a global variable.
Definition: hx711_multi.c:40
void hx711_multi__async_remove_reader(const hx711_multi_t *const hxm)
Removes the given hxm from the request array.
Definition: hx711_multi.c:421
#define HX711_MULTI_MIN_CHIPS
Minimum number of chips to connect to a hx711_multi.
Definition: hx711_multi.h:71
@ HX711_MULTI_ASYNC_STATE_WAITING
Definition: hx711_multi.h:87
@ HX711_MULTI_ASYNC_STATE_NONE
Definition: hx711_multi.h:86
@ HX711_MULTI_ASYNC_STATE_READING
Definition: hx711_multi.h:88
@ HX711_MULTI_ASYNC_STATE_DONE
Definition: hx711_multi.h:89
#define HX711_MULTI_CONVERSION_DONE_IRQ_NUM
PIO interrupt number which is set by the reader PIO State Machine when a conversion period ends....
Definition: hx711_multi.h:43
#define HX711_MULTI_ASYNC_READ_COUNT
Only one instance of a hx711_multi can operate within a PIO. So the maximum number of concurrent asyn...
Definition: hx711_multi.h:60
#define HX711_MULTI_MAX_CHIPS
The max number of chips could technically be the same as the number of bits output from the PIO State...
Definition: hx711_multi.h:80
size_t chips_len
Number of HX711 chips connected.
Definition: hx711_multi.h:142
uint data_pin_base
Lowest GPIO pin number connected to a HX711 chip.
Definition: hx711_multi.h:137
uint dma_irq_index
Which index to use for a DMA interrupt. Either 0 or 1. Corresponds to DMA_IRQ[IRQ_INDEX] NVIC IRQ num...
Definition: hx711_multi.h:155
const pio_program_t * awaiter_prog
PIO awaiter program.
Definition: hx711_multi.h:174
hx711_multi_program_init_t awaiter_prog_init
PIO awaiter init function. This is called to set up the State Machine for the awaiter program....
Definition: hx711_multi.h:181
const pio_program_t * reader_prog
PIO reader program.
Definition: hx711_multi.h:187
hx711_multi_program_init_t reader_prog_init
PIO reader init function. This is called to set up the State Machine for the reader program....
Definition: hx711_multi.h:194
uint clock_pin
GPIO pin number connected to all HX711 chips.
Definition: hx711_multi.h:132
PIO pio
Which PIO to use. Either pio0 or pio1.
Definition: hx711_multi.h:161
hx711_multi_pio_init_t pio_init
PIO init function. This is called to set up any PIO functions (pio_*) as opposed to any State Machine...
Definition: hx711_multi.h:168
uint pio_irq_index
Which index to use for a PIO interrupt. Either 0 or 1. Corresponds to PIO[PIO_INDEX]_IRQ[IRQ_INDEX] N...
Definition: hx711_multi.h:149
uint _data_pin_base
Definition: hx711_multi.h:95
pio_sm_config _awaiter_default_config
Definition: hx711_multi.h:101
volatile hx711_multi_async_state_t _async_state
Definition: hx711_multi.h:116
uint _dma_irq_index
Definition: hx711_multi.h:115
uint _reader_offset
Definition: hx711_multi.h:108
const pio_program_t * _reader_prog
Definition: hx711_multi.h:105
pio_sm_config _reader_default_config
Definition: hx711_multi.h:106
uint _pio_irq_index
Definition: hx711_multi.h:114
mutex_t _mut
Definition: hx711_multi.h:119
const pio_program_t * _awaiter_prog
Definition: hx711_multi.h:100
size_t _chips_len
Definition: hx711_multi.h:96
uint _awaiter_offset
Definition: hx711_multi.h:103
uint32_t _buffer[HX711_READ_BITS]
Definition: hx711_multi.h:112
void util_gpio_set_output(const uint gpio)
Initialises and sets GPIO pin to output.
Definition: util.c:185
bool util_pio_sm_is_enabled(PIO const pio, const uint sm)
Check whether a given state machine is enabled.
Definition: util.c:366
bool util_pio_irq_index_is_valid(const uint idx)
Check whether PIO IRQ index is valid.
Definition: util.c:226
void util_pio_sm_clear_rx_fifo(PIO const pio, const uint sm)
Clears a given state machine's RX FIFO.
Definition: util.c:334
uint util_pio_get_pis_from_pio_interrupt_num(const uint pio_interrupt_num)
Definition: util.c:301
void util_dma_channel_set_quiet(const uint channel, const bool quiet)
Sets a DMA channel's IRQ quiet mode.
Definition: util.c:161
void util_gpio_set_contiguous_input_pins(const uint base, const uint len)
Sets GPIO pins from base to base + len to input.
Definition: util.c:170
uint util_dma_get_irqn(const uint irq_index)
Gets the NVIC IRQ number based on the DMA IRQ index.
Definition: util.c:144
uint util_pio_get_irq_from_index(PIO const pio, const uint idx)
Gets the NVIC PIO IRQ number using a PIO pointer and PIO IRQ index.
Definition: util.c:250
#define UTIL_INTERRUPTS_OFF_BLOCK(...)
Definition: util.h:75
bool util_dma_irq_index_is_valid(const uint idx)
Check whether a DMA IRQ index is valid.
Definition: util.c:65