Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of d7a_1x by
Diff: src/d7a_alp.cpp
- 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)