wayne roberts
/
alarm_analog_master
broadcasts repeated notification upon change of analog input
Diff: main.cpp
- Revision:
- 0:a25661fcf9b2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Oct 22 17:55:34 2018 -0700 @@ -0,0 +1,209 @@ +#include "radio.h" + +#define NUM_ANALOG_IN 4 + +#if defined(SX127x_H) || defined(SX126x_H) + #define BW_KHZ 500 + #define SPREADING_FACTOR 11 + #define CF_HZ 910800000 + #if defined(SX126x_H) + #define TX_DBM (Radio::chipType == CHIP_TYPE_SX1262 ? 20 : 14) + #else + #define TX_DBM 17 + #endif +#elif defined(SX128x_H) + #define BW_KHZ 200 + #define SPREADING_FACTOR 11 + #define CF_HZ 2487000000 + + #define TX_DBM 5 +#endif + +#define PWM_HZ 120 + +#if defined(TARGET_FF_MORPHO) && defined(TARGET_FAMILY_STM32) +PinName pin_names[NUM_ANALOG_IN] = { + PC_2, /* CN7-35 */ + PC_3, /* CN7-37 */ + PC_4, /* CN10-34 */ + PC_5 /* CN10-6 */ +}; +#endif + +#define CMD_PWM_A 0x02 +#define CMD_PWM_B 0x03 +#define CMD_PWM_C 0x04 +#define CMD_PWM_D 0x05 + +const uint8_t rfCmds[NUM_ANALOG_IN] = { + CMD_PWM_A, + CMD_PWM_B, + CMD_PWM_C, + CMD_PWM_D +}; + +typedef struct { + AnalogIn* ain; + uint16_t prev; + int8_t movement; + bool sent; +} analog_t; + +analog_t _a_[NUM_ANALOG_IN]; + +Timer t; + +volatile bool tx_done; + +static uint16_t crc_ccitt( uint8_t *buffer, uint16_t length ) +{ + // The CRC calculation follows CCITT + const uint16_t polynom = 0x1021; + // CRC initial value + uint16_t crc = 0x0000; + + if( buffer == NULL ) + { + return 0; + } + + for( uint16_t i = 0; i < length; ++i ) + { + crc ^= ( uint16_t ) buffer[i] << 8; + for( uint16_t j = 0; j < 8; ++j ) + { + crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 ); + } + } + + return crc; +} + +void transmit(unsigned target, uint8_t cmd, uint16_t ain) +{ + unsigned t_diff; + uint16_t crc; + + Radio::radio.tx_buf[0] = cmd; + Radio::radio.tx_buf[1] = PWM_HZ; + Radio::radio.tx_buf[2] = ain >> 8; // pwm duty + t_diff = target - t.read_us(); + Radio::radio.tx_buf[3] = t_diff >> 24; + Radio::radio.tx_buf[4] = t_diff >> 16; + Radio::radio.tx_buf[5] = t_diff >> 8; + Radio::radio.tx_buf[6] = t_diff & 0xff; + crc = crc_ccitt(Radio::radio.tx_buf, 7); + Radio::radio.tx_buf[7] = crc >> 8; + Radio::radio.tx_buf[8] = crc & 0xff; + + Radio::Send(9, 0, 0, 0); + + for (tx_done = false; !tx_done; ) + Radio::service(); + + printf("t_diff:%u crc:%04x\r\n", t_diff, crc); +} + +#define TARGET_LATENCY 2000000 +void send_alarm(uint8_t cmd, uint16_t ain) +{ + int i; + unsigned target = t.read_us() + TARGET_LATENCY; + printf("send_alarm() %u\n", target); + + for (i = 0; i < 5; i++) { + transmit(target, cmd, ain); + wait(0.1); + } +} + +void txDoneCB() +{ + tx_done = true; +} + +void rxDoneCB(uint8_t size, float Rssi, float Snr) +{ +} + +#define AIN_REST_THRESHOLD 96 // 12bit left justified + +void analog_mainloop(analog_t* ana, uint8_t rfCmd) +{ + uint16_t ain = ana->ain->read_u16(); + uint16_t diff = abs(ain-ana->prev); + if (diff > AIN_REST_THRESHOLD) { + ana->sent = false; + if (ana->movement < 1) + ana->movement = 1; + else { + if (++ana->movement > 16) + ana->movement = 16; + } + } else { + /* steady state */ + if (ana->movement > 0) + ana->movement = 0; + else { + if (--ana->movement < -16) { + ana->movement = -16; + if (!ana->sent) { + printf("## %02x ##\r\n", ain >> 8); + send_alarm(rfCmd, ain); + ana->sent = true; + } + } + } + } + //printf("%05u diff:%04u move:%d\r\n", ain, diff, ain_movement); + ana->prev = ain; +} + +void trigger_init() +{ + unsigned n; + for (n = 0; n < NUM_ANALOG_IN; n++) { + _a_[n].ain = new AnalogIn(pin_names[n]); + _a_[n].prev = _a_[n].ain->read_u16(); + _a_[n].movement = 0; + _a_[n].sent = false; + } +} + +const RadioEvents_t rev = { + /* Dio0_top_half */ NULL, + /* TxDone_topHalf */ NULL, + /* TxDone_botHalf */ txDoneCB, + /* TxTimeout */ NULL, + /* RxDone */ rxDoneCB, + /* RxTimeout */ NULL, + /* RxError */ NULL, + /* FhssChangeChannel */NULL, + /* CadDone */ NULL +}; + +int main() +{ + printf("\r\nreset-tx\r\n"); + + trigger_init(); + + t.start(); + + Radio::Init(&rev); + + Radio::Standby(); + Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1); + Radio::LoRaPacketConfig(8, false, true, false); // preambleLen, fixLen, crcOn, invIQ + Radio::SetChannel(CF_HZ); + + Radio::set_tx_dbm(TX_DBM); + + for (;;) { + unsigned n; + for (n = 0; n < NUM_ANALOG_IN; n++) { + analog_mainloop(&_a_[n], rfCmds[n]); + } + wait_us(5000); + } // ..for (;;) +}