Trond Enger / d7a_1x

Fork of d7a_1x by WizziLab

Revision:
58:38a366236bda
Parent:
57:fd9c8b67ffdc
Child:
59:b42eae56b51b
--- a/src/d7a_alp.cpp	Thu Sep 08 10:44:05 2016 +0000
+++ b/src/d7a_alp.cpp	Mon Sep 12 16:36:09 2016 +0000
@@ -66,6 +66,11 @@
     return (evt.status == osEventMessage)? (d7a_com_rx_msg_t*)evt.value.p : NULL;
 }
 
+static uint32_t d7a_ctf_to_ti(d7a_ctf_t ctf)
+{
+    return ((1 << (2*ctf.bf.exp)) * ctf.bf.mant);
+}
+
 uint32_t d7a_alp_encode_length(uint8_t* p, uint32_t len)
 {
     if (len <= 0x3F)
@@ -148,6 +153,7 @@
     return len;
 }
 
+
 d7a_alp_rsp_t* d7a_alp_parse_pl(d7a_com_rx_msg_t* pkt)
 {    
     if (pkt == NULL)
@@ -160,10 +166,7 @@
     uint8_t len = pkt->blen;
 
     d7a_alp_rsp_t* rsp = (d7a_alp_rsp_t*)MALLOC(sizeof(d7a_alp_rsp_t));
-    
-    rsp->nb_status = 0;
-    rsp->length = 0;
-    rsp->data = NULL;
+    memset(rsp, 0, sizeof(d7a_alp_rsp_t));
     
     while ((p - t) < len)
     {
@@ -174,34 +177,45 @@
             case ALP_OPCODE_RSP_STATUS:
                 if (ctrl & ALP_OPCODE_INDIRECT)
                 {
-                    uint8_t type = *p++; // ITF Type
+                    // ITF Type
+                    uint8_t type = *p++;
+                    // Length
                     uint32_t length;
-                    p += alp_decode_length(p, &length); // Length
-                    p += length; // Data
-                    DPRINT("ALP RSP ISTATUS %02X\r\n", type);
+                    p += alp_decode_length(p, &length);
+                    // Data
+                    d7a_sp_res_t* res = (d7a_sp_res_t*)p;
+                    p += length;
+                    
+                    // Fill corresponding fields
+                    rsp->s_istatus = 0x01; // IStatus present
+                    rsp->lb = res->lb; // Get Link Budget
+                    memcpy(rsp->id, res->addressee.id, D7A_UID_LEN); // Get UID
+                    
+                    DPRINT("ALP RSP ISTATUS type:%02X lb: %3d ", type, rsp->lb);
+                    PRINT_DATA("UID:", "%02X", rsp->id, D7A_UID_LEN, "\r\n");
                 }
                 else
                 {
-                    rsp->status[rsp->nb_status].aid = *p++; // Action ID
-                    rsp->status[rsp->nb_status].status = *p++; // Status
-                    DPRINT("ALP RSP STATUS[%d] aid:%d Status:%d\r\n", rsp->nb_status, rsp->status[rsp->nb_status].aid, rsp->status[rsp->nb_status].status);
-                    rsp->nb_status++;
+                    rsp->s_status = 0x01; // Status present
+                    rsp->status.aid = *p++; // Action ID
+                    rsp->status.status = *p++; // Status
+                    DPRINT("ALP RSP STATUS aid:%d Status:%d\r\n", rsp->status.aid, rsp->status.status);
                 }
                 break;
             case ALP_OPCODE_RSP_TAG:
-                rsp->tag_status = (ctrl & ~0x3F) | 0x01;
+                rsp->s_tag = (ctrl & ~0x3F) | 0x01;
                 rsp->tag = *p++; // TAG
-                DPRINT("ALP RSP TAG %d %02x\r\n", rsp->tag, rsp->tag_status);
+                DPRINT("ALP RSP TAG %d %02x\r\n", rsp->tag, rsp->s_tag);
                 break;
             case ALP_OPCODE_RSP_F_DATA:
                 uint8_t fid = *p++; // File ID
                 uint32_t offset;
                 p += alp_decode_length(p, &offset); // offset
-                p += alp_decode_length(p, &(rsp->length)); // length
-                rsp->data = (uint8_t*)MALLOC(rsp->length);
-                p += d7a_alp_add(rsp->data, p, rsp->length);
-                DPRINT("ALP RSP F_DATA f:%d o:%d s:%d\r\n", fid, offset, rsp->length);
-                //dbg_print_data("DATA: ", "%02X ", (uint8_t*)rsp->data, rsp->length, "\r\n");
+                p += alp_decode_length(p, &(rsp->data_len)); // length
+                rsp->data = (uint8_t*)MALLOC(rsp->data_len);
+                p += d7a_alp_add(rsp->data, p, rsp->data_len);
+                DPRINT("ALP RSP F_DATA f:%d o:%d s:%d\r\n", fid, offset, rsp->data_len);
+                //dbg_print_data("DATA: ", "%02X ", (uint8_t*)rsp->data, rsp->data_len, "\r\n");
                 break;
             default:
                 WARNING(false, "ALP Untreated OP %d\r\n", ctrl);
@@ -225,14 +239,30 @@
     return (uint32_t)(p - t);
 }
 
-
-
 uint32_t d7a_alp_forward_action(uint8_t* p, alp_d7a_itf_t* itf, bool resp)
 {
     uint8_t* t = p;
     
+    uint32_t itf_size = sizeof(alp_d7a_itf_t);
+    switch (itf->cfg.addressee.ctrl.bf.idf)
+    {
+        case D7A_ID_NBID:
+            itf_size -= 7;
+            break;
+        case D7A_ID_NOID:
+            itf_size -= 8;
+            break;
+        case D7A_ID_UID:
+            break;
+        case D7A_ID_VID:
+            itf_size -= 4;
+            break;
+        default:
+            break;
+    }
+    
     *p++ = ALP_OPCODE_FORWARD + ((resp)? ALP_CTRL_RESP : 0);
-    p += d7a_alp_add(p, (uint8_t*)itf, sizeof(alp_d7a_itf_t));
+    p += d7a_alp_add(p, (uint8_t*)itf, itf_size);
     
     return (uint32_t)(p - t);
 }
@@ -250,7 +280,7 @@
     return (uint32_t)(p - t);
 }
 
-uint32_t d7a_alp_read_action(uint8_t* p, const uint8_t file_id, const uint32_t offset, const uint32_t size, const uint8_t* const buf, bool resp)
+uint32_t d7a_alp_read_action(uint8_t* p, const uint8_t file_id, const uint32_t offset, const uint32_t size, bool resp)
 {
     uint8_t* t = p;
     
@@ -264,68 +294,117 @@
 
 void free_pl(d7a_alp_rsp_t* pl)
 {
-    if (pl->data != NULL)
+    if (pl->data_len)
     {
         FREE(pl->data);
     }
     FREE(pl);
 }
 
+d7a_msg_t* new_msg(void)
+{
+    d7a_msg_t* msg = (d7a_msg_t*)MALLOC(sizeof(d7a_msg_t));
+    memset(msg, 0, sizeof(d7a_msg_t));
+    msg->err = D7A_ERR_UNKNOWN;
+    
+    return msg;
+}
 
-d7a_errors_t d7a_alp_write_file(const uint8_t file_id, const uint32_t offset, const uint32_t size, const uint8_t* const buf, d7a_addressee_t* addressee, uint8_t retry, bool resp)
+d7a_msg_t** d7a_alp_write_file(const uint8_t file_id, const uint32_t offset, const uint32_t size, const uint8_t* const buf, d7a_addressee_t* addressee, uint8_t retry, bool resp)
 {
+    // Get command buffer
     uint8_t* p = &g_alp_ctx.buffer[0];
+    // Save initial position of the command buffer
     uint8_t* t = p;
     
+    bool broadcast = false;
+    d7a_alp_rsp_t* pl = NULL;
+    d7a_com_rx_msg_t* pkt = NULL;
+    uint8_t current_tag;
+    d7a_msg_t** ret = NULL;
+    uint32_t max_responses = 1;
+    uint8_t i;
+    
+    if (addressee)
+    {
+        if (addressee->ctrl.bf.idf == D7A_ID_NBID)
+        {
+            broadcast = true;
+            d7a_ctf_t ctf;
+            ctf.byte = addressee->id[0];
+            max_responses = ((1 << (2*ctf.bf.exp)) * ctf.bf.mant);
+        }
+        else if (addressee->ctrl.bf.idf == D7A_ID_NOID)
+        {
+            broadcast = true;
+            max_responses = 32;
+        }
+    }
+    
+    // malloc and init pointer array
+    ret = (d7a_msg_t**)MALLOC(sizeof(d7a_msg_t*) * (max_responses + 1));
+    for (i = 0; i < (max_responses + 1); i++)
+    {
+        ret[i] = NULL;
+    }
+    
+    // malloc and init first response
+    ret[0] = new_msg();
+    
+    // Construct command
+    
     // Tag action
     p += d7a_alp_tag(p, true);
-        
+    
+    // get tag
+    current_tag = g_alp_ctx.tag;
+    
     if (addressee)
     {
         // Construct interface
         alp_d7a_itf_t itf = {
-            .type = 0xD7, // Dash7 interface
-            .cfg.qos.bf.resp = D7A_RESP_ANY,
+            // Dash7 interface
+            .type = 0xD7,
+            // Switch response type if broadcast
+            .cfg.qos.bf.resp = (broadcast)? D7A_RESP_ALL : D7A_RESP_ANY,
             .cfg.qos.bf.retry = retry,
             .cfg.qos.bf.record = 0,
             .cfg.qos.bf.stop_on_err = 0,
             .cfg.dorm_to.byte = 0,
         };
         memcpy(&itf.cfg.addressee, addressee, sizeof(d7a_addressee_t));
-        itf.cfg.addressee.ctrl.bf.idf = D7A_ID_UID;
-            
-        // Forward
+        
+        // Forward action
         p += d7a_alp_forward_action(p, &itf, true);
     }
     
     // Write action
     p += d7a_alp_write_action(p, file_id, offset, size, buf, resp);
     
+    // Send command
     d7a_com_dump(&g_alp_ctx.buffer[0], (uint8_t)(p - t), KAL_COM_FLOW_AT_CMD);
-    
-    d7a_alp_rsp_t* pl = NULL;
-    d7a_com_rx_msg_t* pkt = NULL;
-    d7a_errors_t status = D7A_ERR_UNKNOWN;
-    uint8_t current_tag = g_alp_ctx.tag;
-    
+
+    i = 0; // start with msg 0
+    // Parse responses
     do
     {
         pkt = d7a_alp_wait_pl(60000);
         
         if (pkt == NULL)
         {
-            status = D7A_ERR_CMD_TO;
+            ret[i]->err = D7A_ERR_CMD_TO;
             break;
         }
         
         pl = d7a_alp_parse_pl(pkt);
         
-        if (!(pl->tag_status & 0x01))
+        // Check TAG
+        if (!(pl->s_tag & 0x01))
         {
             WARNING(false, "No tag in payload expected %d\r\n", current_tag);
             FREE(pkt);
             free_pl(pl);
-            status = D7A_ERR_UNKNOWN;
+            ret[i]->err = D7A_ERR_UNKNOWN;
             break;
         }
         
@@ -339,94 +418,169 @@
         
         FREE(pkt);
         
-        if (pl->nb_status)
+        // Get STATUS
+        if (pl->s_status)
         {
-            status = (d7a_errors_t)pl->status[0].status;
+            ret[i]->err = (d7a_errors_t)pl->status.status;
         }
         else
         {
-            if (pl->tag_status & ALP_CTRL_ERR)
+            if (pl->s_tag & ALP_CTRL_ERR)
             {
-                status = D7A_ERR_TX_FAILED;
+                ret[i]->err = D7A_ERR_TX_FAILED;
             }
             else
             {
-                status = D7A_ERR_NONE;
+                ret[i]->err = D7A_ERR_NONE;
             }
         }
+        
+        // Get DATA
+        if (pl->data_len)
+        {
+            ret[i]->data_len = pl->data_len;
+            ret[i]->data = (uint8_t*)MALLOC(ret[i]->data_len);
+            memcpy((void*)ret[i]->data, (void*)pl->data, ret[i]->data_len);
+        }
+        
+        // Get ISTATUS
+        if (pl->s_istatus)
+        {
+            ret[i]->lb = pl->lb;
+            memcpy(ret[i]->id, pl->id, D7A_UID_LEN); // Get UID
+        }
     
-        if (pl->tag_status & ALP_CTRL_EOP)
+        // Check for END OF PAYLOAD
+        if (pl->s_tag & ALP_CTRL_EOP)
         {
+            // If tag only
+            if (!pl->s_status && !pl->s_istatus && !pl->data_len)
+            {
+                // Ignore response
+                FREE(ret[i]);
+                ret[i] = NULL;
+            }
+            
             free_pl(pl);
             break;
         }
         
+        // Wait for new msg
+        if (pl->s_istatus)
+        {
+            i++;
+            ASSERT(i <= max_responses, "Too much responses! max: %d\r\n", max_responses);
+            ret[i] = new_msg();
+        }
+        
         free_pl(pl);
     } while (1);
     
-    return status;
+    return ret;
 }
 
-d7a_errors_t d7a_alp_read_file(const uint8_t file_id, const uint32_t offset, const uint32_t size, const uint8_t* const buf, d7a_addressee_t* addressee, uint8_t retry)
+d7a_msg_t** d7a_alp_read_file(const uint8_t file_id, const uint32_t offset, const uint32_t size, d7a_addressee_t* addressee, uint8_t retry)
 {
+    // Get command buffer
     uint8_t* p = &g_alp_ctx.buffer[0];
+    // Save initial position of the command buffer
     uint8_t* t = p;
     
+    bool broadcast = false;
+    d7a_alp_rsp_t* pl = NULL;
+    d7a_com_rx_msg_t* pkt = NULL;
+    uint8_t current_tag;
+    d7a_msg_t** ret = NULL;
+    uint32_t max_responses = 1;
+    uint8_t i;
+    
+    if (addressee)
+    {
+        if (addressee->ctrl.bf.idf == D7A_ID_NBID)
+        {
+            broadcast = true;
+            d7a_ctf_t ctf;
+            ctf.byte = addressee->id[0];
+            max_responses = ((1 << (2*ctf.bf.exp)) * ctf.bf.mant);
+        }
+        else if (addressee->ctrl.bf.idf == D7A_ID_NOID)
+        {
+            broadcast = true;
+            max_responses = 32;
+        }
+    }
+    
+    // malloc and init pointer array
+    ret = (d7a_msg_t**)MALLOC(sizeof(d7a_msg_t*) * (max_responses + 1));
+    for (i = 0; i < (max_responses + 1); i++)
+    {
+        ret[i] = NULL;
+    }
+    
+    // malloc and init first response
+    ret[0] = new_msg();
+    
+    // Construct command
+    
     // Tag action
     p += d7a_alp_tag(p, true);
     
+    // get tag
+    current_tag = g_alp_ctx.tag;
+    
     if (addressee)
     {
         // Construct interface
         alp_d7a_itf_t itf = {
-            .type = 0xD7, // Dash7 interface
-            .cfg.qos.bf.resp = D7A_RESP_ANY,
+            // Dash7 interface
+            .type = 0xD7,
+            // Switch response type if broadcast
+            //.cfg.qos.bf.resp = (broadcast)? D7A_RESP_ALL : D7A_RESP_ANY,
+            .cfg.qos.bf.resp = D7A_RESP_ALL,
             .cfg.qos.bf.retry = retry,
             .cfg.qos.bf.record = 0,
             .cfg.qos.bf.stop_on_err = 0,
             .cfg.dorm_to.byte = 0,
         };
         memcpy(&itf.cfg.addressee, addressee, sizeof(d7a_addressee_t));
-        itf.cfg.addressee.ctrl.bf.idf = D7A_ID_UID;
-            
-        // Forward
+        
+        // Forward action
         p += d7a_alp_forward_action(p, &itf, true);
     }
     
     // Read action
-    p += d7a_alp_read_action(p, file_id, offset, size, buf, true);
-    
-    d7a_com_dump(&g_alp_ctx.buffer[0], (uint8_t)(p - t), KAL_COM_FLOW_AT_CMD);
+    p += d7a_alp_read_action(p, file_id, offset, size, true);
     
-    d7a_alp_rsp_t* pl = NULL;
-    d7a_com_rx_msg_t* pkt = NULL;
-    d7a_errors_t status = D7A_ERR_UNKNOWN;
-    uint8_t current_tag = g_alp_ctx.tag;
-    
+    // Send command
+    d7a_com_dump(&g_alp_ctx.buffer[0], (uint8_t)(p - t), KAL_COM_FLOW_AT_CMD);
+
+    i = 0; // start with msg 0
+    // Parse responses
     do
     {
         pkt = d7a_alp_wait_pl(60000);
         
         if (pkt == NULL)
         {
-            status = D7A_ERR_CMD_TO;
+            ret[i]->err = D7A_ERR_CMD_TO;
             break;
         }
         
         pl = d7a_alp_parse_pl(pkt);
         
-        if (!(pl->tag_status & 0x01))
+        // Check TAG
+        if (!(pl->s_tag & 0x01))
         {
             WARNING(false, "No tag in payload expected %d\r\n", current_tag);
             FREE(pkt);
             free_pl(pl);
-            status = D7A_ERR_UNKNOWN;
+            ret[i]->err = D7A_ERR_UNKNOWN;
             break;
         }
         
         if (pl->tag != current_tag)
         {
-            //WARNING(false, "Ingnoring tag %d expecting %d\r\n", pl->tag, current_tag);
+            WARNING(false, "Ingnoring tag %d expecting %d\r\n", pl->tag, current_tag);
             free_pl(pl);
             d7a_alp_new_pl(pkt);
             continue;
@@ -434,43 +588,77 @@
         
         FREE(pkt);
         
-        if (pl->nb_status)
+        // Get STATUS
+        if (pl->s_status)
         {
-            status = (d7a_errors_t)pl->status[0].status;
+            DPRINT("err status\r\n");
+            ret[i]->err = (d7a_errors_t)pl->status.status;
         }
         else
         {
-            if (pl->tag_status & ALP_CTRL_ERR)
+            DPRINT("err not status\r\n");
+            if (pl->s_tag & ALP_CTRL_ERR)
             {
-                status = D7A_ERR_TX_FAILED;
+                ret[i]->err = D7A_ERR_TX_FAILED;
             }
             else
             {
-                status = D7A_ERR_NONE;
+                ret[i]->err = D7A_ERR_NONE;
             }
         }
         
-        if (pl->data != NULL)
+        // Get DATA
+        if (pl->data_len)
         {
-            memcpy((void*)buf, (void*)pl->data, pl->length);
-            status = D7A_ERR_NONE;
+            DPRINT("get data\r\n");
+            ret[i]->data_len = pl->data_len;
+            ret[i]->data = (uint8_t*)MALLOC(ret[i]->data_len);
+            memcpy((void*)ret[i]->data, (void*)pl->data, ret[i]->data_len);
+        }
+        
+        // Get ISTATUS
+        if (pl->s_istatus)
+        {
+            DPRINT("get istatus\r\n");
+            ret[i]->lb = pl->lb;
+            memcpy(ret[i]->id, pl->id, D7A_UID_LEN); // Get UID
         }
     
-        if (pl->tag_status & ALP_CTRL_EOP)
+        // Check for END OF PAYLOAD
+        if (pl->s_tag & ALP_CTRL_EOP)
         {
+            DPRINT("EOP\r\n");
+            
+            // If tag only
+            if (!pl->s_status && !pl->s_istatus && !pl->data_len)
+            {
+                // Ignore response
+                FREE(ret[i]);
+                ret[i] = NULL;
+            }
+            
             free_pl(pl);
             break;
         }
         
+        // Wait for new msg
+        if (pl->s_istatus)
+        {
+            DPRINT("next response\r\n");
+            i++;
+            ASSERT(i <= max_responses, "Too much responses! max: %d\r\n", max_responses);
+            ret[i] = new_msg();
+        }
+        
         free_pl(pl);
     } while (1);
     
-    return status;
+    return ret;
 }
 
 void d7a_alp_thread(const void *p)
 {
-    FPRINT("\r\n");
+    FPRINT("(id:0x%08x)\r\n", osThreadGetId());
     d7a_com_rx_msg_t* pkt;
     
     while (true)