Ping pong app demo.

Dependencies:   modem_ref_helper DebouncedInterrupt

Committer:
Jeej
Date:
Tue Aug 20 14:04:21 2019 +0000
Revision:
11:aa9c3fdf2303
Parent:
10:b69fe2a98432
Child:
12:d621c88d5c49
WizziCom now uses DMA instead of interrupts.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jeej 0:fa3fd69f8148 1 // @autor: jeremie@wizzilab.com
Jeej 0:fa3fd69f8148 2 // @date: 2017-05-02
Jeej 0:fa3fd69f8148 3
Jeej 0:fa3fd69f8148 4 #include "DebouncedInterrupt.h"
Jeej 2:785b422c7d22 5 #include "modem_ref_helper.h"
Jeej 0:fa3fd69f8148 6 #include "modem_callbacks.h"
Jeej 0:fa3fd69f8148 7
Jeej 0:fa3fd69f8148 8 Semaphore button_user(0);
Jeej 0:fa3fd69f8148 9 Semaphore modem_ready[MAX_USER_NB];
Jeej 0:fa3fd69f8148 10
Jeej 0:fa3fd69f8148 11 enum {
Jeej 0:fa3fd69f8148 12 MODEM_RESP_NO,
Jeej 0:fa3fd69f8148 13 MODEM_RESP_TERMINAL,
Jeej 0:fa3fd69f8148 14 MODEM_RESP_DONE,
Jeej 0:fa3fd69f8148 15 };
Jeej 0:fa3fd69f8148 16
Jeej 0:fa3fd69f8148 17 uint8_t g_main_id;
Jeej 0:fa3fd69f8148 18 uint8_t g_void_id;
Jeej 0:fa3fd69f8148 19
Jeej 0:fa3fd69f8148 20 typedef struct {
Jeej 0:fa3fd69f8148 21 Thread* thread;
Jeej 0:fa3fd69f8148 22 uint32_t count;
Jeej 0:fa3fd69f8148 23 d7a_addressee_t addressee;
Jeej 0:fa3fd69f8148 24 } ping_t;
Jeej 0:fa3fd69f8148 25
Jeej 0:fa3fd69f8148 26 #define FID_PING_PONG 128
Jeej 3:0979d8cba5ec 27 #define PING_DELAY 1000
Jeej 0:fa3fd69f8148 28 #define PING_COUNTER_SIZE sizeof(uint32_t)
Jeej 0:fa3fd69f8148 29 #define MAX_PING_NB MAX_USER_NB-2
Jeej 0:fa3fd69f8148 30
Jeej 3:0979d8cba5ec 31 // Special access classes for tests: no duty cycle limit, continuous scan
Jeej 3:0979d8cba5ec 32 // { .bf.s = 12, .bf.m = 1 }; --> High Rate
Jeej 3:0979d8cba5ec 33 // { .bf.s = 13, .bf.m = 1 }; --> Normal Rate
Jeej 3:0979d8cba5ec 34 // { .bf.s = 14, .bf.m = 1 }; --> Slow Rate
Jeej 3:0979d8cba5ec 35
Jeej 8:1b7101152a76 36 // Use Gateway access profile and its 2 subprofiles at the same time
Jeej 8:1b7101152a76 37 // Subprofile 0: 3 channels
Jeej 8:1b7101152a76 38 // Subprofile 1: 4 channels
Jeej 8:1b7101152a76 39 d7a_xcl_t ping_pong_xcl = { .bf.s = 2, .bf.m = 0x1 };
Jeej 6:287a9759d70a 40
Jeej 6:287a9759d70a 41 // This describe the interface used for communication
Jeej 6:287a9759d70a 42 // Do not modify uncommented parameters
Jeej 0:fa3fd69f8148 43 alp_d7a_itf_t my_itf = {
Jeej 0:fa3fd69f8148 44 .type = ALP_ITF_TYPE_D7A,
Jeej 0:fa3fd69f8148 45 .cfg.to = 0,
Jeej 0:fa3fd69f8148 46 .cfg.te = 0,
Jeej 6:287a9759d70a 47 .cfg.qos.bf.resp = D7A_RESP_NO, // Communication protocol
Jeej 8:1b7101152a76 48 .cfg.qos.bf.retry = ALP_RPOL_ONESHOT, // Retry policy
Jeej 6:287a9759d70a 49 .cfg.addressee.ctrl.bf.nls = D7A_NLS_AES_CCM_64, // Security level
Jeej 6:287a9759d70a 50 .cfg.addressee.xcl = ping_pong_xcl, // Used Access Class
Jeej 6:287a9759d70a 51 // One of the followings:
Jeej 8:1b7101152a76 52 .cfg.addressee.ctrl.bf.idf = D7A_ID_NOID, // in Broadcast (same as D7A_ID_NBID with .cfg.addressee.id[0] = D7A_CTF_VAL(2,2) (32))
Jeej 6:287a9759d70a 53
Jeej 6:287a9759d70a 54 //.cfg.addressee.ctrl.bf.idf = D7A_ID_UID, // in Unicast
Jeej 6:287a9759d70a 55 //.cfg.addressee.id = { 0x00, 0x1B, 0xC5, 0x0C, 0x70, 0x00, 0x00, 0x00 }, // Destination UID
Jeej 6:287a9759d70a 56
Jeej 6:287a9759d70a 57 //.cfg.addressee.ctrl.bf.idf = D7A_ID_NBID, // in Broadcast
Jeej 9:63592df2faad 58 //.cfg.addressee.id[0] = D7A_CTF_ENCODE(4), // Estimation of expected responses (1 to 32)
Jeej 0:fa3fd69f8148 59 };
Jeej 0:fa3fd69f8148 60
Jeej 0:fa3fd69f8148 61 // Callback for User
Jeej 0:fa3fd69f8148 62 void my_main_callback(uint8_t terminal, int8_t err, uint8_t id)
Jeej 0:fa3fd69f8148 63 {
Jeej 0:fa3fd69f8148 64 (void)id;
Jeej 0:fa3fd69f8148 65
Jeej 9:63592df2faad 66 if (ALP_ERR_NONE != err)
Jeej 9:63592df2faad 67 {
Jeej 9:63592df2faad 68 modem_print_error(ALP_ITF_TYPE_D7A, err);
Jeej 9:63592df2faad 69 }
Jeej 9:63592df2faad 70
Jeej 0:fa3fd69f8148 71 if (terminal)
Jeej 0:fa3fd69f8148 72 {
Jeej 0:fa3fd69f8148 73 modem_ready[id].release();
Jeej 0:fa3fd69f8148 74 }
Jeej 0:fa3fd69f8148 75 }
Jeej 0:fa3fd69f8148 76
Jeej 0:fa3fd69f8148 77 void my_void_callback(uint8_t terminal, int8_t err, uint8_t id)
Jeej 0:fa3fd69f8148 78 {
Jeej 0:fa3fd69f8148 79 (void)terminal;
Jeej 0:fa3fd69f8148 80 (void)id;
Jeej 9:63592df2faad 81
Jeej 9:63592df2faad 82 if (ALP_ERR_NONE != err)
Jeej 9:63592df2faad 83 {
Jeej 9:63592df2faad 84 modem_print_error(ALP_ITF_TYPE_D7A, err);
Jeej 9:63592df2faad 85 }
Jeej 0:fa3fd69f8148 86 }
Jeej 0:fa3fd69f8148 87
Jeej 0:fa3fd69f8148 88 // Interrupt Service Routine on button press.
Jeej 0:fa3fd69f8148 89 void button_push_isr( void )
Jeej 0:fa3fd69f8148 90 {
Jeej 0:fa3fd69f8148 91 button_user.release();
Jeej 0:fa3fd69f8148 92 }
Jeej 0:fa3fd69f8148 93
Jeej 2:785b422c7d22 94 #ifdef DEBUG_LED
Jeej 0:fa3fd69f8148 95 DigitalOut my_led(DEBUG_LED);
Jeej 0:fa3fd69f8148 96 #endif
Jeej 0:fa3fd69f8148 97
Jeej 8:1b7101152a76 98 void my_udata(void *data, u32 length)
Jeej 8:1b7101152a76 99 {
Jeej 8:1b7101152a76 100 uint8_t* p = (uint8_t*)data;
Jeej 8:1b7101152a76 101 int32_t rem = length;
Jeej 8:1b7101152a76 102 alp_parsed_chunk_t r;
Jeej 8:1b7101152a76 103 d7a_sp_res_t istat;
Jeej 8:1b7101152a76 104
Jeej 8:1b7101152a76 105 do {
Jeej 8:1b7101152a76 106 uint32_t parsed = alp_parse_chunk(&p, &r);
Jeej 8:1b7101152a76 107 if (!parsed)
Jeej 8:1b7101152a76 108 {
Jeej 8:1b7101152a76 109 // Discard the payload in case of parsing error.
Jeej 8:1b7101152a76 110 PRINT("Parsing error!\r\n");
Jeej 8:1b7101152a76 111 break;
Jeej 8:1b7101152a76 112 }
Jeej 8:1b7101152a76 113 rem -= parsed;
Jeej 8:1b7101152a76 114
Jeej 8:1b7101152a76 115 switch (r.type)
Jeej 8:1b7101152a76 116 {
Jeej 8:1b7101152a76 117 // Interface status
Jeej 8:1b7101152a76 118 case ALP_OPCODE_RSP_ISTATUS:
Jeej 8:1b7101152a76 119 // D7A Interface
Jeej 8:1b7101152a76 120 if (ALP_ITF_TYPE_D7A == r.meta.itf.type)
Jeej 8:1b7101152a76 121 {
Jeej 8:1b7101152a76 122 // Save interface status
Jeej 8:1b7101152a76 123 memcpy(&istat, r.data, sizeof(d7a_sp_res_t));
Jeej 8:1b7101152a76 124 }
Jeej 8:1b7101152a76 125 else
Jeej 8:1b7101152a76 126 {
Jeej 8:1b7101152a76 127 PRINT("Got accessed by unknown Interface 0x%02X\n", r.meta.itf.type);
Jeej 8:1b7101152a76 128 }
Jeej 8:1b7101152a76 129 break;
Jeej 8:1b7101152a76 130 // Data return
Jeej 8:1b7101152a76 131 case ALP_OPCODE_RSP_F_DATA:
Jeej 8:1b7101152a76 132 if(FID_PING_PONG == r.meta.f_data.fid && 0 == r.meta.f_data.offset && PING_COUNTER_SIZE == r.meta.f_data.length)
Jeej 8:1b7101152a76 133 {
Jeej 8:1b7101152a76 134 uint32_t count;
Jeej 6:287a9759d70a 135
Jeej 8:1b7101152a76 136 // Get data
Jeej 8:1b7101152a76 137 memcpy(&count, r.data, r.meta.f_data.length);
Jeej 8:1b7101152a76 138
Jeej 8:1b7101152a76 139 PRINT("Got PING %d", count);
Jeej 8:1b7101152a76 140 PRINT_DATA(" from ", "%02X", istat.addressee.id, 8, "");
Jeej 8:1b7101152a76 141 PRINT(" (SNR:%d dB RXLEV:%d dBm LB:%d dB)\n", istat.snr, -istat.rxlev, istat.lb);
Jeej 8:1b7101152a76 142
Jeej 6:287a9759d70a 143 #ifdef DEBUG_LED
Jeej 8:1b7101152a76 144 my_led = 1;
Jeej 6:287a9759d70a 145 #endif
Jeej 8:1b7101152a76 146
Jeej 10:b69fe2a98432 147 ThisThread::sleep_for(PING_DELAY);
Jeej 8:1b7101152a76 148
Jeej 6:287a9759d70a 149 #ifdef DEBUG_LED
Jeej 8:1b7101152a76 150 my_led = 0;
Jeej 6:287a9759d70a 151 #endif
Jeej 8:1b7101152a76 152
Jeej 8:1b7101152a76 153 alp_d7a_itf_t resp_itf = {
Jeej 8:1b7101152a76 154 .type = ALP_ITF_TYPE_D7A,
Jeej 8:1b7101152a76 155 .cfg.to = 0,
Jeej 8:1b7101152a76 156 .cfg.te = 0,
Jeej 8:1b7101152a76 157 .cfg.qos.bf.resp = D7A_RESP_NO,
Jeej 8:1b7101152a76 158 .cfg.qos.bf.retry = ALP_RPOL_ONESHOT,
Jeej 8:1b7101152a76 159 .cfg.addressee = istat.addressee,
Jeej 8:1b7101152a76 160 };
Jeej 8:1b7101152a76 161
Jeej 8:1b7101152a76 162 count++;
Jeej 11:aa9c3fdf2303 163
Jeej 8:1b7101152a76 164 // Send ping
Jeej 8:1b7101152a76 165 PRINT("Send PING %d", count);
Jeej 8:1b7101152a76 166 PRINT_DATA(" to ", "%02X", resp_itf.cfg.addressee.id, 8, "\n");
Jeej 8:1b7101152a76 167
Jeej 8:1b7101152a76 168 modem_send_file_content((uint8_t*)&resp_itf, D7_ITF_SIZE(&resp_itf), NULL, FID_PING_PONG, &count, 0, PING_COUNTER_SIZE, g_void_id);
Jeej 8:1b7101152a76 169 }
Jeej 8:1b7101152a76 170 break;
Jeej 8:1b7101152a76 171 default:
Jeej 8:1b7101152a76 172 PRINT("Untreated OPCODE %d\n", r.type);
Jeej 8:1b7101152a76 173 break;
Jeej 3:0979d8cba5ec 174 }
Jeej 8:1b7101152a76 175 } while (rem > 0);
Jeej 0:fa3fd69f8148 176 }
Jeej 0:fa3fd69f8148 177
Jeej 8:1b7101152a76 178
Jeej 0:fa3fd69f8148 179 void button_user_thread()
Jeej 0:fa3fd69f8148 180 {
Jeej 0:fa3fd69f8148 181 uint32_t ping = 0;
Jeej 0:fa3fd69f8148 182
Jeej 0:fa3fd69f8148 183 FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:fa3fd69f8148 184
Jeej 0:fa3fd69f8148 185 while (true)
Jeej 0:fa3fd69f8148 186 {
Jeej 0:fa3fd69f8148 187 // Wait for button press
Jeej 3:0979d8cba5ec 188 PRINT("PRESS BUTTON TO INITIATE PING...\n");
Jeej 10:b69fe2a98432 189 button_user.acquire();
Jeej 0:fa3fd69f8148 190
Jeej 0:fa3fd69f8148 191 // Initiate ping
Jeej 0:fa3fd69f8148 192 PRINT("Initiate PING\n");
Jeej 7:7524fab147aa 193 modem_send_file_content((uint8_t*)&my_itf, D7_ITF_SIZE(&my_itf), NULL, FID_PING_PONG, &ping, 0, PING_COUNTER_SIZE, g_main_id);
Jeej 10:b69fe2a98432 194 modem_ready[g_main_id].acquire();
Jeej 0:fa3fd69f8148 195 }
Jeej 0:fa3fd69f8148 196 }
Jeej 0:fa3fd69f8148 197
Jeej 0:fa3fd69f8148 198 modem_callbacks_t callbacks = {
Jeej 0:fa3fd69f8148 199 .read = my_read,
Jeej 0:fa3fd69f8148 200 .write = my_write,
Jeej 0:fa3fd69f8148 201 .read_fprop = my_read_fprop,
Jeej 0:fa3fd69f8148 202 .flush = my_flush,
Jeej 0:fa3fd69f8148 203 .remove = my_delete,
Jeej 0:fa3fd69f8148 204 .udata = my_udata,
Jeej 0:fa3fd69f8148 205 .lqual = my_lqual,
Jeej 0:fa3fd69f8148 206 .ldown = my_ldown,
Jeej 0:fa3fd69f8148 207 .reset = my_reset,
Jeej 8:1b7101152a76 208 .boot = my_boot,
Jeej 8:1b7101152a76 209 .busy = my_busy,
Jeej 0:fa3fd69f8148 210 };
Jeej 0:fa3fd69f8148 211
Jeej 0:fa3fd69f8148 212 /*** Main function ------------------------------------------------------------- ***/
Jeej 0:fa3fd69f8148 213 int main()
Jeej 0:fa3fd69f8148 214 {
Jeej 0:fa3fd69f8148 215 // Start & initialize
Jeej 2:785b422c7d22 216 #ifdef DEBUG_LED
Jeej 0:fa3fd69f8148 217 DBG_OPEN(DEBUG_LED);
Jeej 2:785b422c7d22 218 #else
Jeej 2:785b422c7d22 219 DBG_OPEN(NC);
Jeej 2:785b422c7d22 220 #endif
Jeej 3:0979d8cba5ec 221 PRINT("\n"
Jeej 3:0979d8cba5ec 222 "-----------------------------------------\n"
Jeej 3:0979d8cba5ec 223 "------------ Demo Ping Pong -------------\n"
Jeej 3:0979d8cba5ec 224 "-----------------------------------------\n");
Jeej 3:0979d8cba5ec 225
Jeej 0:fa3fd69f8148 226 FPRINT("(id:0x%08x)\r\n", osThreadGetId());
Jeej 0:fa3fd69f8148 227
Jeej 2:785b422c7d22 228 modem_helper_open(&callbacks);
Jeej 0:fa3fd69f8148 229
Jeej 0:fa3fd69f8148 230 g_main_id = modem_get_id(my_main_callback);
Jeej 8:1b7101152a76 231 g_void_id = modem_get_id(my_void_callback);
Jeej 1:4629ccf8315d 232
Jeej 0:fa3fd69f8148 233 // Put modem to listen to this access class
Jeej 0:fa3fd69f8148 234 modem_write_file(D7A_FID_DLL_CFG, &ping_pong_xcl, 0, sizeof(d7a_xcl_t), g_main_id);
Jeej 10:b69fe2a98432 235 modem_ready[g_main_id].acquire();
Jeej 0:fa3fd69f8148 236
Jeej 0:fa3fd69f8148 237 PRINT("Start D7A Stack\n");
Jeej 9:63592df2faad 238 modem_activate_itf(ALP_ITF_TYPE_D7A, 24, 0, ALP_D7A_ISTAT_RESP | ALP_D7A_ISTAT_UNS | ALP_D7A_ISTAT_EOP, true, g_main_id);
Jeej 10:b69fe2a98432 239 modem_ready[g_main_id].acquire();
Jeej 0:fa3fd69f8148 240
Jeej 0:fa3fd69f8148 241 #ifdef DEBUG_BUTTON
Jeej 0:fa3fd69f8148 242 DebouncedInterrupt user_interrupt(DEBUG_BUTTON);
Jeej 0:fa3fd69f8148 243 user_interrupt.attach(button_push_isr, IRQ_FALL, 500, true);
Jeej 0:fa3fd69f8148 244
Jeej 0:fa3fd69f8148 245 Thread but_th(osPriorityNormal, 1024, NULL);
Jeej 0:fa3fd69f8148 246 osStatus status = but_th.start(button_user_thread);
Jeej 0:fa3fd69f8148 247 ASSERT(status == osOK, "Failed to start but thread (err: %d)\r\n", status);
Jeej 0:fa3fd69f8148 248 #endif
Jeej 0:fa3fd69f8148 249
Jeej 0:fa3fd69f8148 250 // Set main task to lowest priority
Jeej 10:b69fe2a98432 251 osThreadSetPriority(osThreadGetId(), osPriorityLow);
Jeej 0:fa3fd69f8148 252 while(true)
Jeej 0:fa3fd69f8148 253 {
Jeej 10:b69fe2a98432 254 ThisThread::sleep_for(500);
Jeej 0:fa3fd69f8148 255 }
Jeej 0:fa3fd69f8148 256 }