Fork for Get Started Demo
Dependencies: DebouncedInterrupt dash7-alp mbed-rtos mbed wizzi-utils
Fork of D7A_Demo_full by
main.cpp
- Committer:
- Jeej
- Date:
- 2015-11-20
- Revision:
- 6:897d29f7c89a
- Parent:
- 5:e18c38942326
- Child:
- 7:4226c77951a4
File content as of revision 6:897d29f7c89a:
#include "mbed.h" #include "rtos.h" #include "dbg.h" #include "shield.h" #include "alp_serial.h" #include "alp_device.h" #include "alp_file.h" #include "alp_report.h" #include "DebouncedInterrupt.h" #include "system.h" /* These data are user defined and will be used by the dash7board to identify the device */ #define __MANUFACTURER_ID__ 0x01BC50C7 // Identify the manufacturer #define __DEVICE_ID__ 0x89ABCDEF // Identify the device type #define __FW_ID__ 0x01 // Firmware ID #define __HW_ID__ 0x01520C02 // Hardware ID // Firmware version #define __FW_MAJOR__ 0x02 #define __FW_MINOR__ 0x03 #define __FW_PATCH__ 0x0045 #define __FW_HASH__ 0x86605dba const revision_t revision = { // The two first bytes must be present in all reported files // They are parsed by the dash7board .nw_stat = 0, .nw_seq = 255, // These data are parsed to identify the device .manufacturer_id = __MANUFACTURER_ID__, .device_id = __DEVICE_ID__, .fw_version.fw_id = __FW_ID__, .fw_version.major = __FW_MAJOR__, .fw_version.minor = __FW_MINOR__, .fw_version.patch = __FW_PATCH__, .fw_version.hash = __FW_HASH__, .hw_version = __HW_ID__, .fs_crc = 0 }; // Alarm data structure TYPEDEF_STRUCT_PACKED { uint8_t nw_stat; uint8_t nw_seq; uint8_t status; // Alarm state true/false } alarm_data_t; #define ALARM_DATA_FILE_ID (224) #define ALARM_DATA_FILE_SIZE ((uint16_t) sizeof(alarm_data_t)) alarm_data_t alarm_data = { .nw_stat = 0, .nw_seq = 255, .status = 0 }; // Alarm data structure TYPEDEF_STRUCT_PACKED { uint8_t cmd; // Alarm state true/false } alarm_cmd_t; #define ALARM_CMD_FILE_ID (211) #define ALARM_CMD_FILE_SIZE ((uint16_t) sizeof(alarm_cmd_t)) alarm_cmd_t alarm_cmd = { .cmd = 0 }; // Alarm data structure TYPEDEF_STRUCT_PACKED { uint8_t nw_stat; uint8_t nw_seq; int8_t value; // Temperature value in °C } temp_data_t; #define TEMP_DATA_FILE_ID (226) #define TEMP_DATA_FILE_SIZE ((uint16_t) sizeof(temp_data_t)) temp_data_t temp_data = { .nw_stat = 0, .nw_seq = 255, .value = 0 }; // Checks the status of the report send. void check_status( AlpReport* report, void* param ) { char* message = (char*)param; uint8_t status = report->get_status(); switch (status) { case ALP_CMD_OK: // message is send and acknowleged DPRINT("%s OK\r\n", message); break; case ALP_CMD_TIMEOUT: // message has not been acknowleged by modem DPRINT("%s CMD TIMEOUT\r\n", message); break; case ALP_CMD_ERROR: // message has been acknowleged by modem but returned an error DPRINT("%s CMD ERROR\r\n", message); break; case ALP_D7_TIMEOUT: // message has not been acknowleged by gateway DPRINT("%s D7 TIMEOUT\r\n", message); break; case ALP_D7_ERROR: // message has been acknowleged by gateway but returned an error DPRINT("%s D7 ERROR\r\n", message); break; default: DPRINT("%s UNKNOWN ERROR %d\r\n", message, status); break; } } // Semaphore for notifiying button presses Semaphore button_user(1); // Prints the alarm status. void print_alarm( AlpReport* report, void* param ) { alarm_data_t* alarm = (alarm_data_t*)report->get_content(); DPRINT("SENDING REPORT ALARM %d\r\n", alarm->status); } // Updates the temperature value. void update_temp( AlpReport* report, void* param ) { temp_data_t* temp = (temp_data_t*)report->get_content(); temp->value = system_get_temperature(); DPRINT("SENDING REPORT TEMP %d C\r\n", temp->value); } // Interrupt Service Routine on button press. // Inverts alarm status and releases button Semaphore. void button_push_isr( void ) { // Retrieve file content alarm_data_t* alarm = (alarm_data_t*)alp_file_get_content(ALARM_DATA_FILE_ID); // Invert alarm status alarm->status = !alarm->status; // Release button Semaphore button_user.release(); } // This Thread monitors the user button // and reports the alarm status void alarm_thread( const void* args ) { // Get shield device AlpDevice* shield = (AlpDevice*)args; uint8_t retries; // Create new report AlpReport report_alarm(shield, ALARM_DATA_FILE_ID); report_alarm.attach_before(print_alarm, NULL); report_alarm.attach_after(check_status, (void*)"REPORT ALARM"); // Enable interrupt on User button DebouncedInterrupt button(USER_BUTTON); button.attach(&button_push_isr, IRQ_FALL, 200); while(true) { // Wait for button press button_user.wait(); // Reset retries retries = 0; // Notify alarm status if (report_alarm.send() != ALP_CMD_OK) { // Retry policy while (retries < 3) { // retry 1 second later Thread::wait(1000); retries++; DPRINT("RETRY %d: ", retries); if (report_alarm.retry() == ALP_CMD_OK) { break; } } } } } // This Thread reads the chip temperature // and reports it every 5 minutes void temp_thread( const void* args ) { // Get shield device AlpDevice* shield = (AlpDevice*)args; uint8_t retries; // Create new report AlpReport report_temp(shield, TEMP_DATA_FILE_ID); report_temp.attach_before(update_temp, NULL); report_temp.attach_after(check_status, (void*)"REPORT TEMP"); while(true) { // Reset retries retries = 0; // Notify temp value if (report_temp.send() == ALP_CMD_OK) { // Wait 5 minutes // The function Thread::wait(...) takes a uin32_t as parameter // but the maximum value is uin16_t (65535) for (uint8_t i=0 ; i<5 ; i++) { Thread::wait(60000); } } else { // Retry policy while (retries < 3) { // retry 1 second later Thread::wait(1000); retries++; DPRINT("RETRY %d: ", retries); if (report_temp.retry() == ALP_CMD_OK) { break; } } } } } void write_file_callback(uint8_t op, void* p) { ASSERT(op == ALP_OP_WRITE_DATA, "Callback called with wrong OP %d.", op); alp_write_tpl_t* write_cmd = (alp_write_tpl_t*)p; if (write_cmd->access_tpl.file_id == ALARM_CMD_FILE_ID) { alarm_data_t* alarm = (alarm_data_t*)alp_file_get_content(ALARM_DATA_FILE_ID); alarm_cmd_t* status = (alarm_cmd_t*)write_cmd->data; // Update the report file alarm->status = status->cmd; // Simulate a button press // this will report the new written value button_user.release(); } } int main() { // ----- Debug session over USB Serial ----- // DBG_OPEN(); // Clear some lines on the terminal DPRINT("\r\n\nBOOT\r\n"); // Declare Shield NRST pin DigitalOut shield_nrst(PB_0); // Initialize system functions system_open(); // Reset shield shield_nrst = 0; // Open ALP port over serial // This is the physical ALP serial port AlpSerial serial_shield; // Initialize ALP device // This creates an AlpDevice object abstracting the shield1001 // The parameters describe how to access it AlpDevice shield(&serial_shield, 0, ACCESS_CLASS_EP, ALP_FILE_BLOCK_ISFB, true); // Release reset shield_nrst = 1; // Check the shield boot packets shield_check_boot(&shield); // Wait for Shield to notify its files if there is any Thread::wait(1000); // Add the files to the file system alp_file_add(ALARM_CMD_FILE_ID, ALARM_CMD_FILE_SIZE, (uint8_t*)&alarm_cmd); alp_file_add(TEMP_DATA_FILE_ID, TEMP_DATA_FILE_SIZE, (uint8_t*)&temp_data); alp_file_add(ALARM_DATA_FILE_ID, ALARM_DATA_FILE_SIZE, (uint8_t*)&alarm_data); alp_file_add(REVISION_DEVICE_FILE_ID, REVISION_DEVICE_FILE_SIZE, (uint8_t*)&revision); // Create the Revision report AlpReport report_revision(&shield, REVISION_DEVICE_FILE_ID); // Attach callback after report is send report_revision.attach_after(check_status, (void*)"REPORT REVISION"); // Attach callback after a file is written // This allows us to be notified when a file is remotely modified serial_shield.attach_after(ALP_OP_WRITE_DATA, write_file_callback); // Send the Revision report DPRINT("SENDING REPORT REVISION\r\n"); ASSERT(report_revision.send() == ALP_CMD_OK, "Failed to send revision!\r\n"); // Init Threads Thread t_alarm_thread(alarm_thread, &shield); Thread t_temp_thread(temp_thread, &shield); // Set main task to lowest priority osThreadSetPriority(osThreadGetId(), osPriorityIdle); while(true) { // Wait to avoid beeing stuck in loop Thread::wait(osWaitForever); } }