80 lines
2.0 KiB
C
80 lines
2.0 KiB
C
/**
|
|
* 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;
|
|
}
|