97 lines
3.4 KiB
Plaintext
97 lines
3.4 KiB
Plaintext
;
|
|
; 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 / 562.5e-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);
|
|
}
|
|
%}
|