Helper library to use modem_ref driver.
Dependencies: WizziCom WizziDebug ram_fs modem_ref
Dependents: D7A_Localisation D7A_1x_demo_send_file_data_and_forget D7A_1x_demo_CodeUpgradeProtocol D7A_1x_demo_LoRaWAN ... more
modem_ref_helper.cpp
- Committer:
- Jeej
- Date:
- 2018-11-26
- Revision:
- 49:035512e64fdd
- Parent:
- 48:beb06c0bdb1e
- Child:
- 58:f7105abdceed
File content as of revision 49:035512e64fdd:
#include "modem_ref_helper.h" #if 0 #define HELPER_PRINT(...) PRINT(__VA_ARGS__) #else #define HELPER_PRINT(...); #endif #define MODEM_VERSION_MAJOR 5 #define MODEM_VERSION_MINOR 0 #define MODEM_VERSION_PATCH 36 #define MODEM_DEVICE_ID 0x00001001 static WizziCom* g_modem_com; static Semaphore g_modem_ready; static int8_t g_err; void modem_print_error(uint8_t itf, int8_t error) { if (ALP_ERR_ITF_START >= error && ALP_ERR_ITF_END < error) { error -= ALP_ERR_ITF_START; // Interface specific error if (ALP_ITF_TYPE_HOST == itf) { PRINT("ITF[%02X] Error %d\r\n", itf, error); } else if (ALP_ITF_TYPE_COM == itf) { PRINT("ITF[%02X] Error %d\r\n", itf, error); } else if (ALP_ITF_TYPE_D7A == itf) { PRINT("ITF[%02X] ", itf); switch (error) { /// No error case D7A_ERROR_NO: // = 0, PRINT("D7A_ERROR_NO\r\n"); break; /// Resource busy case D7A_ERROR_BUSY: // = -1, PRINT("D7A_ERROR_BUSY\r\n"); break; /// Bad parameter case D7A_ERROR_BAD_PARAM: // = -2, PRINT("D7A_ERROR_BAD_PARAM\r\n"); break; /// Duty cycle limit overflow case D7A_ERROR_DUTY_CYCLE: // = -3, PRINT("D7A_ERROR_DUTY_CYCLE\r\n"); break; /// CCA timeout case D7A_ERROR_CCA_TO: // = -4, PRINT("D7A_ERROR_CCA_TO\r\n"); break; /// Security frame counter overflow case D7A_ERROR_NLS_KEY: // = -5, PRINT("D7A_ERROR_NLS_KEY\r\n"); break; /// TX stream underflow case D7A_ERROR_TX_UDF: // = -6, PRINT("D7A_ERROR_TX_UDF\r\n"); break; /// RX stream overflow case D7A_ERROR_RX_OVF: // = -7, PRINT("D7A_ERROR_RX_OVF\r\n"); break; /// RX checksum case D7A_ERROR_RX_CRC: // = -8, PRINT("D7A_ERROR_RX_CRC\r\n"); break; /// Abort case D7A_ERROR_ABORT: // = -9, PRINT("D7A_ERROR_ABORT\r\n"); break; /// No ACK received case D7A_ERROR_NO_ACK: // = -10, PRINT("D7A_ERROR_NO_ACK\r\n"); break; /// RX timeout case D7A_ERROR_RX_TO: // = -11, PRINT("D7A_ERROR_RX_TO\r\n"); break; default: PRINT("Unknown Error %d\r\n", error); break; } } else if (ALP_ITF_TYPE_LWAN == itf) { PRINT("ITF[%02X] Error %d\r\n", itf, error); } else { PRINT("ITF[%02X] Error %d\r\n", itf, error); } } else { PRINT("ALP: "); switch (error) { // Not really errors, more like status case ALP_ERR_ITF_FULL: // 0x02: For interfaces supporting buffering, indicates buffer reached maximum capacity (no data loss) PRINT("ALP_ERR_ITF_FULL\r\n"); break; case ALP_ERR_PARTIAL_COMPLETION: // 0x01: Action received and partially completed at response. To be completed after response PRINT("ALP_ERR_PARTIAL_COMPLETION\r\n"); break; // ALP Errors case ALP_ERR_NONE: // 0x00: Action completed (OK) PRINT("ALP_ERR_NONE\r\n"); break; case ALP_ERR_FILE_NOT_FOUND: // 0xFF: Error access file: File ID does not exist PRINT("ALP_ERR_FILE_NOT_FOUND\r\n"); break; case ALP_ERR_FILE_EXIST: // 0xFE: Error create file: File ID already exists PRINT("ALP_ERR_FILE_EXIST\r\n"); break; case ALP_ERR_FILE_NOT_RESTORABLE: // 0xFD: Error restore file: File is not restorable PRINT("ALP_ERR_FILE_NOT_RESTORABLEr\n"); break; case ALP_ERR_PERMISSION_DENIED: // 0xFC: Error access file: Insufficient permissions PRINT("ALP_ERR_PERMISSION_DENIED\r\n"); break; case ALP_ERR_LENGTH_OVERFLOW: // 0xFB: Error create file: Supplied length (in header) is beyond file limits PRINT("ALP_ERR_LENGTH_OVERFLOW\r\n"); break; case ALP_ERR_ALLOC_OVERFLOW: // 0xFA: Error create file: Supplied allocation (in header) is beyond file limits PRINT("ALP_ERR_ALLOC_OVERFLOW\r\n"); break; case ALP_ERR_OFFSET_OVERFLOW: // 0xF9: Error write: Supplied start offset is out of bounds of file allocation PRINT("ALP_ERR_OFFSET_OVERFLOW\r\n"); break; case ALP_ERR_WRITE_OVERFLOW: // 0xF8: Error complete write: Supplied data goes beyond file allocation PRINT("ALP_ERR_WRITE_OVERFLOW\r\n"); break; case ALP_ERR_WRITE_ERROR: // 0xF7: Error write: impossible to write in storage location PRINT("ALP_ERR_WRITE_ERROR\r\n"); break; case ALP_ERR_OPERATION_UNKNOWN: // 0xF6: Error unknown Operation PRINT("ALP_ERR_OPERATION_UNKNOWN\r\n"); break; case ALP_ERR_OPERAND_INCOMPLETE: // 0xF5: Error incomplete Operand PRINT("ALP_ERR_OPERAND_INCOMPLETE\r\n"); break; case ALP_ERR_OPERAND_WRONG_FORMAT: // 0xF4: Error wrong Operand format PRINT("ALP_ERR_OPERAND_WRONG_FORMAT\r\n"); break; case ALP_ERR_ITF_INVALID: // 0xF3: Error invalid interface PRINT("ALP_ERR_ITF_INVALID\r\n"); break; case ALP_ERR_ITF_OVERFLOW: // 0xF2: Error interface overflown (i.e. resources exhausted, buffer full with data discarded) PRINT("ALP_ERR_ITF_OVERFLOW\r\n"); break; case ALP_ERR_QUERY_FAIL: // 0xF1: (Group of) Query result was false (Informative error code). PRINT("ALP_ERR_QUERY_FAIL\r\n"); break; case ALP_ERR_ITF_NOT_SPECIFIED: PRINT("ALP_ERR_ITF_NOT_SPECIFIED\r\n"); break; // Other Errors case ALP_ERR_UNKNOWN: // 0x80: Unknown error PRINT("ALP_ERR_UNKNOWN\r\n"); break; case ALP_ERR_FS_TIMEOUT: // 0x81: Internal FS Error PRINT("ALP_ERR_FS_TIMEOUT\r\n"); break; case ALP_ERR_ITF_UNKNOWN: // 0x82: Unknown Interface PRINT("ALP_ERR_ITF_UNKNOWN\r\n"); break; case ALP_ERR_ITF_TIMEOUT: // 0x83: Internal ITF Error PRINT("ALP_ERR_ITF_TIMEOUT\r\n"); break; default: PRINT("Unknown Error %d\r\n", error); break; } } } int my_alp_itf_d7a_cfg_size(d7a_sp_cfg_t* cfg) { int size = sizeof(d7a_sp_cfg_t) - sizeof(d7a_addressee_t); size += D7A_ADDR_LEN(cfg->addressee.ctrl); return size; } // ============================================================}}} // Serial adapters to WizziLab's own architecture // ============================================================{{{ static void modem_serial_input(WizziCom* com, WizziComPacket_t* pkt) { modem_input(wizzicom_type_to_flow(pkt->type), pkt->data, pkt->length); FREE(pkt); } static int modem_serial_send(uint8_t* data1, uint8_t size1, uint8_t* data2, uint8_t size2) { (void)size1; // Retrieve Flow ID from header and send packet g_modem_com->send((WizziComPacketType)wizzicom_flow_to_type(data1[4]), size2, data2); return (size1 + size2); } // Callback for id User static void my_main_callback(uint8_t terminal, int8_t err, uint8_t id) { (void)id; g_err = err; //modem_print_error(0xC0, g_err); if (terminal) { g_modem_ready.release(); } } // Misc // ============================================================{{{ void modem_notify_host_rev(revision_t* data, alp_file_header_t* header, uint8_t* root_key) { uint8_t id = modem_get_id(my_main_callback); // Write the version to the version file. // This file is notified on write. modem_write_file_root(FID_HOST_REV, (void*)data, 0, HAL_U32_BYTE_SWAP(header->alloc), root_key, id); g_modem_ready.wait(); // Error when writing to the file if (ALP_ERR_NONE != g_err) { // File exists if (ALP_ERR_FILE_NOT_FOUND != g_err) { // Delete old file modem_delete_file_root(FID_HOST_REV, root_key, id); g_modem_ready.wait(); } // Recreate file modem_create_file(FID_HOST_REV, header, id); g_modem_ready.wait(); // Retry writing to the file modem_write_file_root(FID_HOST_REV, (void*)data, 0, HAL_U32_BYTE_SWAP(header->alloc), root_key, id); g_modem_ready.wait(); } modem_free_id(id); } void modem_update_file(uint8_t fid, alp_file_header_t* header, uint8_t* data) { alp_file_header_t remote_header; uint8_t id = modem_get_id(my_main_callback); memset(&remote_header, 0, sizeof(alp_file_header_t)); // Read remote header modem_read_fprop(fid, &remote_header, id); g_modem_ready.wait(); // Add file in local file system ram_fs_new(fid, (uint8_t*)header, data); // Update file if (memcmp(&remote_header, header, sizeof(alp_file_header_t))) { HELPER_PRINT("Updating file %d\n", fid); // Delete modem_delete_file(fid, id); g_modem_ready.wait(); // Restore in local file system ram_fs_new(fid, (uint8_t*)header, data); // Re-create if (data) { modem_declare_file(fid, header, true, id); } else { modem_create_file(fid, header, id); } g_modem_ready.wait(); } else { HELPER_PRINT("File %d up to date\n", fid); } modem_free_id(id); } Semaphore boot(0); void my_startup_boot(u8 cause, u16 number) { HELPER_PRINT("Modem BOOT[%c] #%d\r\n", cause, number); boot.release(); } void modem_helper_open(modem_callbacks_t* callbacks) { static union { uint8_t b[8]; uint32_t w[2]; } uid; revision_t rev; // Override boot callback to catch the first boot message modem_callbacks_t boot_callbacks = { .read = NULL, .write = NULL, .read_fprop = NULL, .flush = NULL, .remove = NULL, .udata = NULL, .lqual = NULL, .ldown = NULL, .reset = NULL, .boot = my_startup_boot, .busy = NULL, .itf_busy = NULL, }; // Open modem Com port g_modem_com = new WizziCom(MODEM_PIN_RX, MODEM_PIN_TX, MODEM_PIN_IRQ_IN, MODEM_PIN_IRQ_OUT); // Hardware reset DigitalOut reset_low(MODEM_PIN_RESET, 0); Thread::wait(100); // Open driver to catch boot packet modem_open(NULL, &boot_callbacks); // Redirect All Port traffic to modem_serial_input g_modem_com->attach(modem_serial_input, WizziComPacketUntreated); // Release reset DigitalIn reset_release(MODEM_PIN_RESET); // Wait for first boot packet HELPER_PRINT("Waiting boot packet...\n"); boot.wait(); // Re-open with user callbacks modem_close(); modem_open(modem_serial_send, callbacks); uint8_t id = modem_get_id(my_main_callback); HELPER_PRINT("Start Modem Process (id=%d)\n", id); Thread::wait(1000); modem_read_file(D7A_FID_UID, uid.b, 0, 8, id); g_modem_ready.wait(); modem_read_file(D7A_FID_FIRMWARE_VERSION, (uint8_t*)&rev, 0, sizeof(revision_t), id); g_modem_ready.wait(); PRINT("------------ D7A Modem infos ------------\r\n"); PRINT_DATA(" - UID: ", "%02X", uid.b, 8, "\r\n"); PRINT(" - Manufacturer ID: %08X\r\n", rev.manufacturer_id); PRINT(" - Device ID: %08X\r\n", rev.device_id); PRINT(" - Hardware version: %08X\r\n", rev.hw_version); PRINT(" - Firmware version: v%d.%d.%d [%02X]\r\n", rev.fw_version.major, rev.fw_version.minor, rev.fw_version.patch, rev.fw_version.id); PRINT(" - CUP max size: %d\r\n", rev.cup_max_size); PRINT("-----------------------------------------\r\n"); if (MODEM_DEVICE_ID == rev.device_id) { // Check version uint32_t rev_sum1 = (rev.fw_version.major << 24) | (rev.fw_version.minor << 16) | rev.fw_version.patch; uint32_t rev_sum2 = (MODEM_VERSION_MAJOR << 24) | (MODEM_VERSION_MINOR << 16) | MODEM_VERSION_PATCH; if (rev_sum1 < rev_sum2) { PRINT("\r\nYou need a modem at version %d.%d.%d or above to use this Driver.\r\n" "You can:\r\n" " - Check modem updates on the Dash7Board:\r\n" " Go to your site's version manager.\r\n" " - Check modem updates by importing:\r\n" " https://developer.mbed.org/teams/WizziLab/code/D7A_WM_Updater\r\n" " - Choose the right 'modem_ref_helper' revision.\r\n" " Right click on modem_ref_helper -> Revision.\r\n" , MODEM_VERSION_MAJOR, MODEM_VERSION_MINOR, MODEM_VERSION_PATCH); Thread::wait(osWaitForever); } } else { // Do not check version PRINT("/!\\ Not a modem firmware /!\\\r\n"); } modem_free_id(id); }