Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

src/d7a_modem.cpp

Committer:
Jeej
Date:
2016-09-07
Revision:
55:5ea18a3a01b9
Parent:
50:30440c9aeb7c
Child:
56:da34fc11e760

File content as of revision 55:5ea18a3a01b9:

#include "mbed.h"
#include "rtos.h"
#include "dbg.h"
#include "d7a_com.h"
#include "d7a_fs.h"
#include "d7a_modem.h"
#include "d7a_sys.h"
#include "d7a_common.h"
#include "d7a.h"
#include "d7a_alp.h"

#define MODEM_TO    (5000)

typedef struct {
    Thread* thread;
    Queue<void, 8> ready;
    Queue<void, 2> boot;
    Queue<d7a_com_rx_msg_t, 16> pkt_queue;
    Queue<register_file_param_t, 64> registered_files;
    NotifDoneFunction notif_done;
    uint8_t nb_files;
    int8_t status;
    DigitalInOut* reset;
    bool booted;
} d7a_modem_ctx_t;

d7a_modem_ctx_t g_modem_ctx;

void d7a_modem_thread(const void *p);

d7a_errors_t d7a_modem_open(PinName reset_pin, NotifDoneFunction nd)
{
    FPRINT("\r\n");
    
    d7a_errors_t err;
    
    g_modem_ctx.thread = new Thread(d7a_modem_thread, NULL, osPriorityHigh, DEFAULT_STACK_SIZE);
    g_modem_ctx.booted = false;
    g_modem_ctx.nb_files = 0;
    g_modem_ctx.notif_done = nd;

    if (reset_pin == NC)
    {
        g_modem_ctx.reset = NULL;
    }
    else
    {
        g_modem_ctx.reset = new DigitalInOut(reset_pin, PIN_OUTPUT, OpenDrain, 1);
    }

    err = d7a_modem_reset();
    
    return err;
}

d7a_errors_t d7a_modem_wait_boot( uint32_t millisec )
{
    FPRINT("(%d)\r\n", millisec);
    osEvent evt = g_modem_ctx.boot.get(millisec);
    return (evt.status == osEventMessage)? (d7a_errors_t)(int32_t)evt.value.p : D7A_ERR_CMD_TO;
}

d7a_errors_t d7a_modem_wait_ready( uint32_t millisec )
{
    FPRINT("(%d)\r\n", millisec);
    osEvent evt = g_modem_ctx.ready.get(millisec);
    return (evt.status == osEventMessage)? (d7a_errors_t)(int32_t)evt.value.p : D7A_ERR_CMD_TO;
}

static void d7a_modem_soft_reset(void)
{
    FPRINT("\r\n");
    IPRINT("MODEM Soft Reset.\r\n");
            
    // Clean buffer and queues
    d7a_com_restart();
    
    // Try software reset
    d7a_sys_software_reset();
}

static void d7a_modem_hard_reset(void)
{
    FPRINT("\r\n");
    
    ASSERT(g_modem_ctx.reset != NULL, "No reset PIN specified\r\n");
    
    IPRINT("MODEM Hard Reset.\r\n");
    
    // Use hardware reset
    // Assert reset pin
    *(g_modem_ctx.reset) = 0;
    
    // Clean buffer and queues
    d7a_com_restart();
    Thread::wait(100);
    
    // Release reset pin
    *(g_modem_ctx.reset) = 1;
    
}

d7a_errors_t d7a_modem_reset(void)
{
    FPRINT("\r\n");
    d7a_errors_t err = D7A_ERR_UNKNOWN;
    g_modem_ctx.booted = false;

    //d7a_modem_soft_reset();
    //reset_err = d7a_modem_wait_boot(5000);
    
    if (err)
    {
        d7a_modem_hard_reset();
        err = d7a_modem_wait_boot(MODEM_TO);
    }
    ASSERT(!err, "MODEM BOOT err %d\r\n", err);
    g_modem_ctx.booted = true;
    
    err = d7a_modem_wait_ready(MODEM_TO);
    ASSERT(!err, "MODEM READY err %d\r\n", err);
    
    IPRINT("MODEM Ready.\r\n");
    
    return err;
}

void d7a_modem_new_pkt(d7a_com_rx_msg_t* pkt)
{
    FPRINT("\r\n");
    ASSERT(g_modem_ctx.pkt_queue.put(pkt) == osOK, "MODEM queue full!\r\n");
}

d7a_com_rx_msg_t* d7a_modem_wait_pkt(uint32_t millisec)
{
    FPRINT("(millisec:%d)\r\n", millisec);
    osEvent evt = g_modem_ctx.pkt_queue.get(millisec);
    return (evt.status == osEventMessage)? (d7a_com_rx_msg_t*)evt.value.p : NULL;
}

void d7a_modem_msg(uint8_t value, uint8_t* buf, uint8_t len)
{
    FPRINT("(value:0x%02X, buf:0x%08x, len:%d)\r\n", value, buf, len);
    d7a_com_tx_msg_t msg;
    uint8_t val = value;
    msg.id = KAL_COM_FLOW_CMD;
    msg.pbuf = &val;
    msg.abuf = buf;
    msg.plen = 1;
    msg.alen = len;
    d7a_com_post_msg(&msg);
}

d7a_errors_t d7a_modem_register(register_file_param_t* file_infos)
{
    d7a_errors_t err;
    
    d7a_modem_msg(WM_CMD_REGISTER_FILE, (uint8_t*)file_infos, sizeof(register_file_param_t));
    err = d7a_modem_wait_ready(TO_FS);
            
    return err;
}

d7a_errors_t d7a_modem_notify(notify_file_param_t* notif)
{
    d7a_errors_t err;
    
    d7a_modem_msg(WM_CMD_NOTIFY_FILE, (uint8_t*)notif, sizeof(notify_file_param_t));
    err = d7a_modem_wait_ready(TO_FS);
            
    return err;
}

d7a_errors_t d7a_modem_start(void)
{
    d7a_errors_t err;
    
    DPRINT("Start modem.\r\n");

    d7a_modem_msg(WM_CMD_D7A_STACK_START, NULL, 0);
    err = d7a_modem_wait_ready(TO_FS);
    
    WARNING(!err, "Start modem err %d\r\n", err);
        
    DPRINT("Start done.\r\n");
    
    return err;
}

d7a_errors_t d7a_modem_stop(void)
{
    d7a_errors_t err;
    
    DPRINT("Stop modem.\r\n");

    d7a_modem_msg(WM_CMD_D7A_STACK_STOP, NULL, 0);
    err = d7a_modem_wait_ready(TO_FS);
    
    WARNING(!err, "Stop modem err %d\r\n", err);
        
    DPRINT("Stop done.\r\n");
    
    return err;
}

void d7a_modem_thread(const void *p)
{
    FPRINT("\r\n");
    d7a_com_rx_msg_t* pkt;
    
    while (true)
    {
        pkt = d7a_modem_wait_pkt();
        ASSERT(pkt != NULL, "MODEM NULL pkt\r\n");

        switch(pkt->id)
        {
            case KAL_COM_FLOW_CMD:
                uint8_t cmd = pkt->buffer[0];
                if (cmd == WM_OK)
                {
                    DPRINT("Modem ready\r\n");
                    g_modem_ctx.ready.put((void*)D7A_ERR_NONE);
                }
                else if (cmd == WM_BOOT)
                {
                    boot_status_t* bs = (boot_status_t*)&(pkt->buffer[1]);
                    WARNING(false, "Modem booted CAUSE:%d NB_BOOT:%d\r\n", bs->bf.cause, bs->bf.nb_boot);
                    
                    if (g_modem_ctx.booted == true)
                    {
                        // Do something?
                    }
                    else
                    {
                        g_modem_ctx.boot.put(NULL);
                    }
                }
                else if (cmd == WM_ERROR)
                {
                    int8_t err = pkt->buffer[1];
                    int8_t ret;
                    
                    WARNING(false, "Modem cmd error %d\r\n", err);
                    switch (err)
                    {
                        case WM_ERR_NOT_READY:          ret = D7A_ERR_NOT_READY; break;
                        case WM_ERR_COM_LINK:           ret = D7A_ERR_COM_LINK; break;
                        case WM_ERR_ILLEGAL_FID:        ret = D7A_ERR_ILLEGAL_FID; break;
                        case WM_ERR_ILLEGAL_FILE_DEF:   ret = D7A_ERR_ILLEGAL_FILE_DEF; break;
                        case WM_ERR_UNKNOWN:            ret = D7A_ERR_UNKNOWN; break;
                        default:                        ret = D7A_ERR_NONE; break;
                    }
                    
                    g_modem_ctx.ready.put((void*)ret);
                }
                else if (cmd == WM_NOTIF_DONE)
                {
                    if (g_modem_ctx.notif_done != NULL)
                    {
                        g_modem_ctx.notif_done(pkt->buffer[1], pkt->buffer[2]);
                    }
                }
                else
                {
                    EPRINT("MODEM Unknown cmd %d\r\n", cmd);
                }
                break;
            default:
                EPRINT("MODEM Unknown Flow ID 0x%02X\r\n", pkt->id);
                break;
        }
        
        FREE(pkt);
    }
}