Send file data demo.

Dependencies:   modem_ref_helper CRC DebouncedInterrupt

main.cpp

Committer:
marin_wizzi
Date:
2021-10-29
Revision:
20:5856f9bfd8e3
Parent:
19:68f3a84dbc8f

File content as of revision 20:5856f9bfd8e3:

// @autor: jeremie@wizzilab.com
// @date: 2017-05-02

#include "DebouncedInterrupt.h"
#include "modem_d7a.h"
#include "modem_callbacks.h"
#include "files.h"
#include "crc.h"


Semaphore button_user(0);
Semaphore modem_ready(0);
Semaphore user_ready(0);
Queue<touch_t, 8> modem_resp;

uint8_t id, g_report_id;

enum {
    MODEM_RESP_NO,
    MODEM_RESP_TERMINAL,
    MODEM_RESP_ERROR,
    MODEM_RESP_ACK,
    MODEM_RESP_TIMEOUT,
};

alp_d7a_itf_t alarm_itf = {
    .type                           = ALP_ITF_TYPE_D7A,
    .cfg.to.byte                    = D7A_CTF_ENCODE(0),
    .cfg.te.byte                    = D7A_CTF_ENCODE(0),
    .cfg.qos.bf.resp                = D7A_RESP_ALL,
    .cfg.qos.bf.retry               = ALP_RPOL_ONESHOT,
    .cfg.addressee.ctrl.bf.nls      = D7A_NLS_AES_CCM_64,
    .cfg.addressee.ctrl.bf.idf      = D7A_ID_NBID,
    .cfg.addressee.xcl.bf           = {.s = 2, .m = 0x1},// XXX D7A_XCL_GW,
    .cfg.addressee.id[0]            = D7A_CTF_ENCODE(8),
};

// Interrupt Service Routine on button press.
void button_push_isr( void )
{
    button_user.release();
}

// Main Callback
void my_main_callback(uint8_t terminal, int8_t err, uint8_t id)
{
    if (ALP_ERR_NONE > err)
    {
        modem_print_error(ALP_ITF_TYPE_D7A, err);
    }
    
    if (terminal)
    {
        modem_ready.release();
    }
}

// Response Callback
void my_response_callback(uint8_t terminal, int8_t err, uint8_t id)
{
    (void)id;
    
    if (ALP_ERR_NONE > err)
    {
        modem_print_error(ALP_ITF_TYPE_D7A, err);
    }
    
    if (terminal)
    {
        modem_resp.put((touch_t*)MODEM_RESP_TERMINAL);
    }
    else
    {
        if (ALP_ERR_NONE == err)
        {
            modem_resp.put((touch_t*)MODEM_RESP_ACK);
        }
        else if (ALP_ERR_NONE > err)
        {
            modem_resp.put((touch_t*)MODEM_RESP_ERROR);
        }
        else
        {
            return;
        }
    }
    
    // Wait end of user processing before resuming
    user_ready.acquire();
}

void button_user_thread()
{
    touch_t* touch;
    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
    
    osEvent evt;
    uint32_t resp;
    uint8_t alarm;
    uint8_t id = modem_ref_get_id(my_main_callback);
    d7a_sp_res_t istat;
    alp_payload_t* alp;
    alp_payload_t* alp_rsp;
    uint8_t nb = 0;
    int err;
    
    memset(&istat, 0, sizeof(d7a_sp_res_t));
    
    // Load alarm value
    ram_fs_read(FID_ALARM, &alarm, 0, 1);
    
    
    while (true)
    {
        
        // Wait for button press
        PRINT("PRESS BUTTON TO SEND ALARM...\r\n");
        button_user.acquire();
        
        
        
        nb = 0;
        
        // load/save value to keep choerency in case of remote access...
        ram_fs_read(FID_ALARM, &alarm, 0, 1);

        // Toggle alarm state
        alarm = !alarm;
        
        ram_fs_write(FID_ALARM, &alarm, 0, 1);
        
        PRINT("BUTTON ALARM %d\r\n", alarm);
        
        alp = NULL;
        alp = alp_payload_rsp_f_data(alp, FID_ALARM, &alarm, 0, 1);
                
        err = modem_remote_raw_alp((void*)&alarm_itf, alp, &alp_rsp, (uint32_t)15000);
        
        if (err < ALP_ERR_NONE)
        {
            PRINT("Timeout.\n");
        }
        else
        {
            err = alp_payload_get_err(alp_rsp);
            PRINT("err %d\n", err);
            modem_print_error(alarm_itf.type, err);
        }
                
        do {
            nb++;
                    
            alp = alp_payload_extract(&alp_rsp, ALP_OPCODE_RSP_ISTATUS);
    
            if (alp)
            {
                alp_parsed_chunk_t r;
                u8* p = alp->d;
                    
                alp_parse_chunk(&p, &r);
                memcpy(&istat, r.data, r.meta.itf.length);
                        
                // Print metadata
                PRINT("ACK %d: ", nb);
                PRINT_DATA("UID:", "%02X", istat.addressee.id, 8, " ");
                PRINT("snr:%d rxlev:%d lb:%d \n", istat.snr, -istat.rxlev, istat.lb);
                        
                alp_payload_free(alp);
            }
            else
            {
                break;
            }
                    
                FLUSH();
            } while (1);
            PRINT("Done.\n");
        }
}


// Misc
// ============================================================{{{

void my_get_alp_file_props(uint8_t fid, alp_file_header_t* hdr)
{
    memcpy(hdr, ram_fs_get_header(fid), sizeof(alp_file_header_t));
}

modem_ref_callbacks_t callbacks = {
    .read       = my_read,
    .write      = my_write,
    .read_fprop = my_read_fprop,
    .flush      = my_flush,
    .remove     = my_delete,
    .udata      = my_udata,
    .lqual      = my_lqual,
    .ldown      = my_ldown,
    .reset      = my_reset,
    .boot       = my_boot,
    .busy       = my_busy,
};


/*** Main function ------------------------------------------------------------- ***/
int main()
{
    // Start & initialize
#ifdef DEBUG_LED
    DBG_OPEN(DEBUG_LED);
#else
    DBG_OPEN(NC);
#endif
    PRINT("\n"
          "-----------------------------------------\n"
          "---------- Demo Send file data ----------\n"
          "-----------------------------------------\n");
              
    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
    
    modem_open(&callbacks);
    
    uint8_t id = modem_ref_get_id(my_main_callback);
    
    PRINT("Register Files\n");
    // Button/Alarm is a local file. As we want to check the outcome of sending
    // this, don't use D7AActP Notification but rather plain ALP ITF Forwarding.
    // Declaration just allows remote access.
    ram_fs_new(FID_ALARM, (uint8_t*)&h_alarm, (uint8_t*)&f_alarm);
    modem_declare_file(FID_ALARM, (alp_file_header_t*)&h_alarm);
    
    
    PRINT("Enable D7A interface\n");
    modem_d7a_enable_itf();
    
    // Host revision file is in the modem. Update it.
    PRINT("Update host revision\n");
    modem_write_file(FID_HOST_REV, (void*)&f_rev, 0, sizeof(revision_t));
    
    
    // Retrieve modem revision
    PRINT("Send revision\n");
    
    revision_t rev;
    
    modem_read_file(FID_WM_REV, &rev, 0, sizeof(revision_t));

#ifdef DEBUG_BUTTON
    DebouncedInterrupt user_interrupt(DEBUG_BUTTON);
    user_interrupt.attach(button_push_isr, IRQ_FALL, 500, true);
    
    Thread but_th(osPriorityNormal, 4096, NULL);
    osStatus status = but_th.start(button_user_thread);
    ASSERT(status == osOK, "Failed to start but thread (err: %d)\r\n", status);
#endif

#ifdef DEBUG_LED
    DigitalOut my_led(DEBUG_LED);
#endif
    
    // Set main task to lowest priority
    osThreadSetPriority(osThreadGetId(), osPriorityLow);
    while(true)
    {
        ThisThread::sleep_for(500);
#ifdef DEBUG_LED
        my_led = !my_led;
#endif
    }
}