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"
47 assert(config != NULL);
49 assert(util_uint_in_range(
54 assert(config->
pio != NULL);
55 check_pio_param(config->
pio);
116 hxm->
_dma_channel = (uint)dma_claim_unused_channel(
true);
118 dma_channel_config cfg = dma_channel_get_default_config(
133 channel_config_set_transfer_data_size(
141 channel_config_set_read_increment(
149 channel_config_set_write_increment(
156 channel_config_set_dreq(
168 channel_config_set_irq_quiet(
172 dma_channel_configure(
197 dma_irqn_set_channel_enabled(
202 irq_set_exclusive_handler(
215 pio_set_irqn_source_enabled(
222 irq_set_exclusive_handler(
237 return dma_irqn_get_channel_status(
248 return pio_interrupt_get(
305 dma_irqn_set_channel_enabled(
312 dma_channel_set_write_addr(
344 dma_irqn_set_channel_enabled(
349 pio_set_irqn_source_enabled(
355 #ifndef HX711_NO_MUTEX
356 mutex_exit(&hxm->
_mut);
372 pio_set_irqn_source_enabled(
393 dma_irqn_acknowledge_channel(
440 return hxm != NULL &&
445 #ifndef HX711_NO_MUTEX
446 mutex_is_initialized(&hxm->
_mut) &&
463 const uint32_t*
const pinvals,
464 int32_t*
const values,
467 assert(pinvals != NULL);
468 assert(values != NULL);
494 for(
size_t chipNum = 0; chipNum < len; ++chipNum) {
503 const uint32_t bit = (pinvals[bitPos] >> chipNum) & 1;
504 rawVal |= bit << shift;
522 #ifndef HX711_NO_MUTEX
527 mutex_init(&hxm->
_mut);
570 #ifndef HX711_NO_MUTEX
571 mutex_enter_blocking(&hxm->
_mut);
590 pio_set_irqn_source_enabled(
596 dma_irqn_set_channel_enabled(
623 pio_set_sm_mask_enabled(
649 #ifndef HX711_NO_MUTEX
650 mutex_exit(&hxm->
_mut);
665 pio_sm_drain_tx_fifo(
677 tight_loop_contents();
684 int32_t*
const values) {
687 assert(values != NULL);
692 tight_loop_contents();
700 int32_t*
const values,
701 const uint timeout) {
704 assert(values != NULL);
707 const absolute_time_t end = make_timeout_time_us(timeout);
708 bool success =
false;
712 while(!time_reached(end)) {
742 const uint32_t status = save_and_disable_interrupts();
744 #ifndef HX711_NO_MUTEX
745 mutex_enter_blocking(&hxm->
_mut);
756 pio_set_irqn_source_enabled(
763 restore_interrupts(status);
774 int32_t*
const values) {
821 pio_set_sm_mask_enabled(
840 pio_set_sm_mask_enabled(
875 const uint32_t allReady = (uint32_t)pow(2, hxm->
_chips_len);
878 return state == 0 || state == allReady;
#define HX711_MUTEX_BLOCK(mut,...)
bool hx711_is_value_valid(const int32_t v)
Check whether the given value is valid for a HX711 implementation.
int32_t hx711_get_twos_comp(const uint32_t raw)
Convert a raw value from the HX711 to a 32-bit signed int.
void hx711_wait_power_down()
Convenience function for sleeping for the appropriate amount of time to allow the HX711 to power down...
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...
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.
static void hx711_multi__async_finish(hx711_multi_t *const hxm)
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.
void hx711_multi_power_up(hx711_multi_t *const hxm, const hx711_gain_t gain)
void hx711_multi__init_asert(const hx711_multi_config_t *const config)
void hx711_multi_init(hx711_multi_t *const hxm, const hx711_multi_config_t *const config)
void hx711_multi_set_gain(hx711_multi_t *const hxm, const hx711_gain_t gain)
Sets the HX711s' gain.
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.
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.
void hx711_multi__async_start_dma(hx711_multi_t *const hxm)
Triggers DMA reading; moves request state from WAITING to READING.
bool hx711_multi__async_add_reader(hx711_multi_t *const hxm)
Adds hxm to the array for ISR access. Returns false if no space.
void hx711_multi_power_down(hx711_multi_t *const hxm)
static bool hx711_multi__is_state_machines_enabled(hx711_multi_t *const hxm)
void hx711_multi__init_irq(hx711_multi_t *const hxm)
Subroutine for initialising IRQ.
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...
bool hx711_multi_async_done(hx711_multi_t *const hxm)
Check whether an asynchronous read is complete. This function is not mutex protected.
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.
void hx711_multi_async_start(hx711_multi_t *const hxm)
Start an asynchronos read. This function is not mutex protected.
void __isr __not_in_flash_func() hx711_multi__async_dma_irq_handler()
ISR handler for DMA IRQs.
bool hx711_multi__async_is_running(hx711_multi_t *const hxm)
Check whether an async read is currently occurring.
static bool hx711_multi__is_initd(hx711_multi_t *const hxm)
void hx711_multi__init_pio(hx711_multi_t *const hxm)
Subroutine for initialising PIO.
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.
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.
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.
void __isr __not_in_flash_func() hx711_multi__async_pio_irq_handler()
ISR handler for PIO IRQs.
bool hx711_multi_is_syncd(hx711_multi_t *const hxm)
Determines whether all chips are in sync.
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,...
void hx711_multi_close(hx711_multi_t *const hxm)
Stop communication with all HX711s.
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.
void hx711_multi__init_dma(hx711_multi_t *const hxm)
Subroutine for initialising DMA.
hx711_multi_t * hx711_multi__async_read_array[]
Array of hxm for ISR to access. This is a global variable.
void hx711_multi__async_remove_reader(const hx711_multi_t *const hxm)
Removes the given hxm from the request array.
#define HX711_MULTI_MIN_CHIPS
Minimum number of chips to connect to a hx711_multi.
@ HX711_MULTI_ASYNC_STATE_WAITING
@ HX711_MULTI_ASYNC_STATE_NONE
@ HX711_MULTI_ASYNC_STATE_READING
@ HX711_MULTI_ASYNC_STATE_DONE
#define HX711_MULTI_CONVERSION_DONE_IRQ_NUM
PIO interrupt number which is set by the reader PIO State Machine when a conversion period ends....
#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...
#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...
size_t chips_len
Number of HX711 chips connected.
uint data_pin_base
Lowest GPIO pin number connected to a HX711 chip.
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...
const pio_program_t * awaiter_prog
PIO awaiter program.
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....
const pio_program_t * reader_prog
PIO reader program.
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....
uint clock_pin
GPIO pin number connected to all HX711 chips.
PIO pio
Which PIO to use. Either pio0 or pio1.
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...
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...
pio_sm_config _awaiter_default_config
volatile hx711_multi_async_state_t _async_state
const pio_program_t * _reader_prog
pio_sm_config _reader_default_config
const pio_program_t * _awaiter_prog
uint32_t _buffer[HX711_READ_BITS]
void util_gpio_set_output(const uint gpio)
Initialises and sets GPIO pin to output.
bool util_pio_sm_is_enabled(PIO const pio, const uint sm)
Check whether a given state machine is enabled.
bool util_pio_irq_index_is_valid(const uint idx)
Check whether PIO IRQ index is valid.
void util_pio_sm_clear_rx_fifo(PIO const pio, const uint sm)
Clears a given state machine's RX FIFO.
uint util_pio_get_pis_from_pio_interrupt_num(const uint pio_interrupt_num)
void util_dma_channel_set_quiet(const uint channel, const bool quiet)
Sets a DMA channel's IRQ quiet mode.
void util_gpio_set_contiguous_input_pins(const uint base, const uint len)
Sets GPIO pins from base to base + len to input.
uint util_dma_get_irqn(const uint irq_index)
Gets the NVIC IRQ number based on the DMA IRQ index.
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.
#define UTIL_INTERRUPTS_OFF_BLOCK(...)
bool util_dma_irq_index_is_valid(const uint idx)
Check whether a DMA IRQ index is valid.