Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

src/d7a_modem.cpp

Committer:
Jeej
Date:
2016-05-25
Revision:
30:d775c1409849
Parent:
29:8e7c5c1e9aab
Child:
31:ab9bfdbc6b44

File content as of revision 30:d775c1409849:

#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"

typedef struct {
    Thread* thread;
    Semaphore* ressource;
    Queue<void, 8> ready;
    Queue<void, 2> boot;
    Queue<d7a_com_rx_msg_t, 16> pkt_queue;
    int8_t status;
    DigitalInOut* reset;
    int16_t waiting_count;
    uint8_t ready_count;
} d7a_modem_ctx_t;

d7a_modem_ctx_t g_modem_ctx;

void d7a_modem_thread(const void *p);

void d7a_modem_open( PinName reset_pin )
{
    FPRINT("\r\n");
    
    g_modem_ctx.ressource = new Semaphore(1);
    g_modem_ctx.thread = new Thread(d7a_modem_thread, NULL, osPriorityBelowNormal, DEFAULT_STACK_SIZE);
    g_modem_ctx.waiting_count = 0;
    g_modem_ctx.ready_count = 0;
    
    if (reset_pin == NC)
    {
        g_modem_ctx.reset = NULL;
    }
    else
    {
        g_modem_ctx.reset = new DigitalInOut(reset_pin, PIN_OUTPUT, OpenDrain, 0);
    }
    
    Thread::wait(10);
    
    d7a_modem_reset();
    
    // Wait for modem ready
    osEvent evt = g_modem_ctx.boot.get(5000);
    ASSERT(evt.status == osEventMessage, "MODEM BOOT Timeout\r\n");
    IPRINT("MODEM Boot OK.\r\n");
    ASSERT(d7a_modem_wait_ready(2000), "MODEM READY Timeout\r\n");
    IPRINT("MODEM Ready.\r\n");
}

void d7a_modem_reset( void )
{
    if (g_modem_ctx.reset == NULL)
    {
        // Try software reset
        d7a_sys_software_reset();
    }
    else
    {
        // Use hardware reset
        // Assert reset pin
        *(g_modem_ctx.reset) = 0;
        Thread::wait(10);
        // Release reset pin
        *(g_modem_ctx.reset) = 1;
        Thread::wait(10);
    }
}

bool d7a_modem_wait_ready( uint32_t millisec )
{
    g_modem_ctx.waiting_count++;
    FPRINT("(%d)\r\n", g_modem_ctx.waiting_count);
    osEvent evt = g_modem_ctx.ready.get(millisec);
    return (evt.status == osEventMessage)? true: false;
}

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_send_msg(&msg);
}

bool d7a_modem_register_file(uint8_t fid, uint8_t retry_policy)
{
    g_modem_ctx.ressource->wait();
    
    bool ret = true;
    
    FPRINT("(fid:%d, retry_policy:0x%02X)\r\n", fid, retry_policy);
    register_file_param_t rparams = {
        .bf.fid = fid ,
        .bf.retry_policy = retry_policy
    };

    // Check If modem already has it
    DPRINT("Register: %d\r\n", rparams.bf.fid);
    d7a_fs_distant_stat(rparams.bf.fid, NULL);
    g_modem_ctx.status = (int32_t)d7a_fs_wait_done(TO_FS);
    if (g_modem_ctx.status < 0)
    {
        d7a_fs_properties_t props;
        // retrieve local properties
        d7a_fs_get_properties(rparams.bf.fid, KAL_FS_PROP_ALL, &props);
        // create a remote Host file matching our local one
        props.type = HOST;
        d7a_fs_distant_create(rparams.bf.fid, &props);
        g_modem_ctx.status = (int32_t)d7a_fs_wait_done(TO_FS);
    }
    
    if (g_modem_ctx.status == 0)
    {
        // Distant file is ready, lets register a D7A Interface for it
        d7a_modem_msg(WM_CMD_REGISTER_FILE,(uint8_t*)&rparams,sizeof(register_file_param_t));
        ret = d7a_modem_wait_ready(TO_FS);
    }
    else
    {
        ret = false;
    }
    
    DPRINT("Register done.\r\n");
    g_modem_ctx.ressource->release();
    
    return ret;
}

void d7a_modem_notify_file(uint8_t fid, uint32_t offset, uint32_t length)
{
    g_modem_ctx.ressource->wait();
    
    FPRINT("(fid:%d, offset:%d, length:%d)\r\n", fid, offset, length);
    DPRINT("Notify %d.\r\n", fid);
    
    notify_file_param_t nfp = {
        .bf.fid = fid,
        .bf.offset = offset,
        .bf.size = length
    };

    d7a_modem_msg(WM_CMD_NOTIFY_FILE,(uint8_t*)&nfp,sizeof(notify_file_param_t));
    WARNING(d7a_modem_wait_ready(TO_FS), "Notification Timeout on FID:%d\r\n", fid);
    
    Thread::wait(100); // XXX: To avoid lost packets
    
    DPRINT("Notify %d done.\r\n", fid);
    g_modem_ctx.ressource->release();
}

void d7a_modem_print_infos( void )
{
    uint8_t uid[8];
    revision_t rev;
    
    g_modem_ctx.ressource->wait();
    
    d7a_fs_read(0, uid, 0, 8);
    d7a_fs_wait_done(TO_FS);
    
    d7a_fs_read(2, &rev, 0, sizeof(revision_t));
    d7a_fs_wait_done(TO_FS);
    
    IPRINT("--- D7A Modem infos ---\r\n");
    IPRINT("UID: %02X%02X%02X%02X%02X%02X%02X%02X\r\n", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
    IPRINT("Manufacturer ID:  %08X\r\n", rev.manufacturer_id);
    IPRINT("Device ID:        %08X\r\n", rev.device_id);
    IPRINT("Hardware version: %08X\r\n", rev.hw_version);
    IPRINT("Firmware version: %d-%d.%d.%d-%08x\r\n", rev.fw_version.id, rev.fw_version.major, rev.fw_version.minor, rev.fw_version.patch, rev.fw_version.hash);
    IPRINT("File system CRC:  0x%08x\r\n", rev.fs_crc);
    IPRINT("-----------------------\r\n");  
    
    g_modem_ctx.ressource->release();
}


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_CMD_READY)
                {
                    g_modem_ctx.waiting_count--;
                    DPRINT("Modem ready (%d)\r\n", g_modem_ctx.waiting_count);
                    g_modem_ctx.ready.put(NULL);
                }
                else if (cmd == WM_CMD_BOOT)
                {
                    DPRINT("Modem booted\r\n");
                    g_modem_ctx.boot.put(NULL);
                }
                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);
    }
}