broadcasts repeated notification upon change of analog input

Dependencies:   sx12xx_hal

main.cpp

Committer:
wroberts@semtech.com
Date:
2018-10-23
Revision:
1:b5b1352d36d1
Parent:
0:a25661fcf9b2

File content as of revision 1:b5b1352d36d1:

#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 (;;)
}