Updates along with SDK1.3.0 release (#181)

Bug fixes and new examples

Co-authored-by: Paulo Marques <pm@quant-insight.com>
Co-authored-by: martin <admin@crossleys.biz>
Co-authored-by: matiasilva <matias.silva@raspberrypi.com>
Co-authored-by: Uri Shaked <uri@urishaked.com>
Co-authored-by: Diego Solano <diegosolano@gmail.com>
Co-authored-by: Andrew Scheller <andrew.scheller@raspberrypi.com>
Co-authored-by: Adrian Hesketh <a-h@users.noreply.github.com>
Co-authored-by: Emircan Gündoğdu <58917386+emircangun@users.noreply.github.com>
Co-authored-by: Josef Wegner <80200012+josefwegner@users.noreply.github.com>
Co-authored-by: pmarques-dev <72901351+pmarques-dev@users.noreply.github.com>
Co-authored-by: Paulo Marques <pm@quant-insight.com>
Co-authored-by: mjcross <mjcross@users.noreply.github.com>
Co-authored-by: martin <admin@crossleys.biz>
This commit is contained in:
Graham Sanderson
2021-11-01 14:41:54 -05:00
committed by GitHub
parent 146680d625
commit f800a7e303
150 changed files with 4832 additions and 98 deletions

View File

@@ -0,0 +1,19 @@
# build a normal library
#
add_library(nec_receive_library nec_receive.c)
# invoke pio_asm to assemble the state machine program
#
pico_generate_pio_header(nec_receive_library ${CMAKE_CURRENT_LIST_DIR}/nec_receive.pio)
target_link_libraries(nec_receive_library PRIVATE
pico_stdlib
hardware_pio
)
# add the `binary` directory so that the generated headers are included in the project
#
target_include_directories (nec_receive_library PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)

View File

@@ -0,0 +1,79 @@
/**
* Copyright (c) 2021 mjcross
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// SDK types and declarations
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/clocks.h" // for clock_get_hz()
#include "nec_receive.h"
// import the assembled PIO state machine program
#include "nec_receive.pio.h"
// Claim an unused state machine on the specified PIO and configure it
// to receive NEC IR frames on the given GPIO pin.
//
// Returns: the state machine number on success, otherwise -1
int nec_rx_init(PIO pio, uint pin_num) {
// disable pull-up and pull-down on gpio pin
gpio_disable_pulls(pin_num);
// install the program in the PIO shared instruction space
uint offset;
if (pio_can_add_program(pio, &nec_receive_program)) {
offset = pio_add_program(pio, &nec_receive_program);
} else {
return -1; // the program could not be added
}
// claim an unused state machine on this PIO
int sm = pio_claim_unused_sm(pio, true);
if (sm == -1) {
return -1; // we were unable to claim a state machine
}
// configure and enable the state machine
nec_receive_program_init(pio, sm, offset, pin_num);
return sm;
}
// Validate a 32-bit frame and store the address and data at the locations
// provided.
//
// Returns: `true` if the frame was valid, otherwise `false`
bool nec_decode_frame(uint32_t frame, uint8_t *p_address, uint8_t *p_data) {
// access the frame data as four 8-bit fields
//
union {
uint32_t raw;
struct {
uint8_t address;
uint8_t inverted_address;
uint8_t data;
uint8_t inverted_data;
};
} f;
f.raw = frame;
// a valid (non-extended) 'NEC' frame should contain 8 bit
// address, inverted address, data and inverted data
if (f.address != (f.inverted_address ^ 0xff) ||
f.data != (f.inverted_data ^ 0xff)) {
return false;
}
// store the validated address and data
*p_address = f.address;
*p_data = f.data;
return true;
}

View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) 2021 mjcross
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/stdlib.h"
#include "hardware/pio.h"
// public API
int nec_rx_init(PIO pio, uint pin);
bool nec_decode_frame(uint32_t sm, uint8_t *p_address, uint8_t *p_data);

View File

@@ -0,0 +1,96 @@
;
; Copyright (c) 2021 mjcross
;
; SPDX-License-Identifier: BSD-3-Clause
;
.program nec_receive
; Decode IR frames in NEC format and push 32-bit words to the input FIFO.
;
; The input pin should be connected to an IR detector with an 'active low' output.
;
; This program expects there to be 10 state machine clock ticks per 'normal' 562.5us burst period
; in order to permit timely detection of start of a burst. The initailisation function below sets
; the correct divisor to achive this relative to the system clock.
;
; Within the 'NEC' protocol frames consists of 32 bits sent least-siginificant bit first; so the
; Input Shift Register should be configured to shift right and autopush after 32 bits, as in the
; initialisation function below.
;
.define BURST_LOOP_COUNTER 30 ; the detection threshold for a 'frame sync' burst
.define BIT_SAMPLE_DELAY 15 ; how long to wait after the end of the burst before sampling
.wrap_target
next_burst:
set X, BURST_LOOP_COUNTER
wait 0 pin 0 ; wait for the next burst to start
burst_loop:
jmp pin data_bit ; the burst ended before the counter expired
jmp X-- burst_loop ; wait for the burst to end
; the counter expired - this is a sync burst
mov ISR, NULL ; reset the Input Shift Register
wait 1 pin 0 ; wait for the sync burst to finish
jmp next_burst ; wait for the first data bit
data_bit:
nop [ BIT_SAMPLE_DELAY - 1 ] ; wait for 1.5 burst periods before sampling the bit value
in PINS, 1 ; if the next burst has started then detect a '0' (short gap)
; otherwise detect a '1' (long gap)
; after 32 bits the ISR will autopush to the receive FIFO
.wrap
% c-sdk {
static inline void nec_receive_program_init (PIO pio, uint sm, uint offset, uint pin) {
// Set the GPIO function of the pin (connect the PIO to the pad)
//
pio_gpio_init(pio, pin);
// Set the pin direction to `input` at the PIO
//
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
// Create a new state machine configuration
//
pio_sm_config c = nec_receive_program_get_default_config (offset);
// configure the Input Shift Register
//
sm_config_set_in_shift (&c,
true, // shift right
true, // enable autopush
32); // autopush after 32 bits
// join the FIFOs to make a single large receive FIFO
//
sm_config_set_fifo_join (&c, PIO_FIFO_JOIN_RX);
// Map the IN pin group to one pin, namely the `pin`
// parameter to this function.
//
sm_config_set_in_pins (&c, pin);
// Map the JMP pin to the `pin` parameter of this function.
//
sm_config_set_jmp_pin (&c, pin);
// Set the clock divider to 10 ticks per 562.5us burst period
//
float div = clock_get_hz (clk_sys) / (10.0 / 526.6e-6);
sm_config_set_clkdiv (&c, div);
// Apply the configuration to the state machine
//
pio_sm_init (pio, sm, offset, &c);
// Set the state machine running
//
pio_sm_set_enabled (pio, sm, true);
}
%}