A metronome using the FRDM K64F board

Committer:
ram54288
Date:
Sun May 14 18:40:18 2017 +0000
Revision:
0:a7a43371b306
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ram54288 0:a7a43371b306 1 #include "mbed.h"
ram54288 0:a7a43371b306 2 #include "utils.hpp"
ram54288 0:a7a43371b306 3 #include "stdio.h"
ram54288 0:a7a43371b306 4
ram54288 0:a7a43371b306 5 #include "EthernetInterface.h"
ram54288 0:a7a43371b306 6 #include "frdm_client.hpp"
ram54288 0:a7a43371b306 7
ram54288 0:a7a43371b306 8 #include "metronome.hpp"
ram54288 0:a7a43371b306 9
ram54288 0:a7a43371b306 10
ram54288 0:a7a43371b306 11
ram54288 0:a7a43371b306 12 #define IOT_ENABLED
ram54288 0:a7a43371b306 13
ram54288 0:a7a43371b306 14 namespace active_low
ram54288 0:a7a43371b306 15 {
ram54288 0:a7a43371b306 16 const bool on = false;
ram54288 0:a7a43371b306 17 const bool off = true;
ram54288 0:a7a43371b306 18 }
ram54288 0:a7a43371b306 19
ram54288 0:a7a43371b306 20 RawSerial pc(USBTX, USBRX);
ram54288 0:a7a43371b306 21
ram54288 0:a7a43371b306 22 DigitalOut g_led_red(LED1);
ram54288 0:a7a43371b306 23 DigitalOut g_led_green(LED2);
ram54288 0:a7a43371b306 24 DigitalOut g_led_blue(LED3);
ram54288 0:a7a43371b306 25
ram54288 0:a7a43371b306 26 InterruptIn g_button_mode(SW3);
ram54288 0:a7a43371b306 27 InterruptIn g_button_tap(SW2);
ram54288 0:a7a43371b306 28
ram54288 0:a7a43371b306 29 size_t prev_bpm =0,max_bpm=0, min_bpm=INT_MAX;
ram54288 0:a7a43371b306 30 bool min_changed = 0, max_changed =0, bpm_changed =0;
ram54288 0:a7a43371b306 31 uint8_t* buffIn = NULL;
ram54288 0:a7a43371b306 32 uint32_t sizeIn;
ram54288 0:a7a43371b306 33
ram54288 0:a7a43371b306 34 Semaphore updates(0);
ram54288 0:a7a43371b306 35
ram54288 0:a7a43371b306 36 Ticker status_ticker;
ram54288 0:a7a43371b306 37 void blinky(){
ram54288 0:a7a43371b306 38
ram54288 0:a7a43371b306 39 g_led_green = !g_led_green;
ram54288 0:a7a43371b306 40
ram54288 0:a7a43371b306 41 }
ram54288 0:a7a43371b306 42 metronome metronome_object;
ram54288 0:a7a43371b306 43
ram54288 0:a7a43371b306 44
ram54288 0:a7a43371b306 45 void metronome::start_timing(){
ram54288 0:a7a43371b306 46 m_timing = true;
ram54288 0:a7a43371b306 47 m_beat_count = 0;
ram54288 0:a7a43371b306 48 m_timer.start();
ram54288 0:a7a43371b306 49
ram54288 0:a7a43371b306 50 }
ram54288 0:a7a43371b306 51
ram54288 0:a7a43371b306 52 void metronome::stop_timing(){
ram54288 0:a7a43371b306 53
ram54288 0:a7a43371b306 54 m_timing = false;
ram54288 0:a7a43371b306 55 m_timer.stop();
ram54288 0:a7a43371b306 56 size_t curr_bpm=0;
ram54288 0:a7a43371b306 57 curr_bpm = metronome_object.get_bpm();
ram54288 0:a7a43371b306 58 pc.printf("BPM:- %d",curr_bpm);
ram54288 0:a7a43371b306 59 bpm_changed = 1;
ram54288 0:a7a43371b306 60 if(curr_bpm < min_bpm){
ram54288 0:a7a43371b306 61 min_bpm = curr_bpm;
ram54288 0:a7a43371b306 62 min_changed =1;
ram54288 0:a7a43371b306 63 }
ram54288 0:a7a43371b306 64 if(curr_bpm > max_bpm){
ram54288 0:a7a43371b306 65 max_bpm = curr_bpm;
ram54288 0:a7a43371b306 66 max_changed = 1;
ram54288 0:a7a43371b306 67 }
ram54288 0:a7a43371b306 68 if (curr_bpm == 0){
ram54288 0:a7a43371b306 69 g_led_green = active_low::off;
ram54288 0:a7a43371b306 70 }else{
ram54288 0:a7a43371b306 71 //pc.printf("Blinky Call");
ram54288 0:a7a43371b306 72 size_t tempo = 60/curr_bpm;
ram54288 0:a7a43371b306 73 status_ticker.attach(blinky,tempo);
ram54288 0:a7a43371b306 74 }
ram54288 0:a7a43371b306 75 }
ram54288 0:a7a43371b306 76 void metronome::tap(){
ram54288 0:a7a43371b306 77
ram54288 0:a7a43371b306 78 m_beats[m_beat_count++] = m_timer.read_us();
ram54288 0:a7a43371b306 79 pc.printf("%d\n",m_timer.read_us());
ram54288 0:a7a43371b306 80
ram54288 0:a7a43371b306 81
ram54288 0:a7a43371b306 82 }
ram54288 0:a7a43371b306 83 size_t metronome::get_bpm() const {
ram54288 0:a7a43371b306 84 int i=0;
ram54288 0:a7a43371b306 85 size_t bpm=0;
ram54288 0:a7a43371b306 86 if(m_beat_count < 4){
ram54288 0:a7a43371b306 87 return prev_bpm;
ram54288 0:a7a43371b306 88 }else{
ram54288 0:a7a43371b306 89 for(i=0;i<m_beat_count-1;i++){
ram54288 0:a7a43371b306 90 bpm = bpm + m_beats[i+1]-m_beats[i];
ram54288 0:a7a43371b306 91 }
ram54288 0:a7a43371b306 92 bpm = (size_t) bpm/(m_beat_count-1);
ram54288 0:a7a43371b306 93 prev_bpm = (bpm * 0.00006);
ram54288 0:a7a43371b306 94 pc.printf("BPM Calc:- %d",prev_bpm);
ram54288 0:a7a43371b306 95 return prev_bpm;
ram54288 0:a7a43371b306 96 }
ram54288 0:a7a43371b306 97 }
ram54288 0:a7a43371b306 98
ram54288 0:a7a43371b306 99 void on_mode()
ram54288 0:a7a43371b306 100 {
ram54288 0:a7a43371b306 101
ram54288 0:a7a43371b306 102 if(metronome_object.is_timing()){
ram54288 0:a7a43371b306 103 //Go to play mode
ram54288 0:a7a43371b306 104 //printf("playmode");
ram54288 0:a7a43371b306 105 g_led_red = active_low::off;
ram54288 0:a7a43371b306 106 g_led_green = active_low::on;
ram54288 0:a7a43371b306 107 metronome_object.stop_timing();
ram54288 0:a7a43371b306 108
ram54288 0:a7a43371b306 109 }else{
ram54288 0:a7a43371b306 110 //Go to learn mode
ram54288 0:a7a43371b306 111 // printf("learnmode");
ram54288 0:a7a43371b306 112 g_led_green = active_low::off;
ram54288 0:a7a43371b306 113 g_led_red = active_low::on;
ram54288 0:a7a43371b306 114 status_ticker.detach();
ram54288 0:a7a43371b306 115 metronome_object.start_timing();
ram54288 0:a7a43371b306 116
ram54288 0:a7a43371b306 117 }
ram54288 0:a7a43371b306 118 }
ram54288 0:a7a43371b306 119
ram54288 0:a7a43371b306 120 void on_tap()
ram54288 0:a7a43371b306 121 {
ram54288 0:a7a43371b306 122 // Receive a tempo tap
ram54288 0:a7a43371b306 123 if(metronome_object.is_timing()){
ram54288 0:a7a43371b306 124 metronome_object.tap();
ram54288 0:a7a43371b306 125 }
ram54288 0:a7a43371b306 126 }
ram54288 0:a7a43371b306 127
ram54288 0:a7a43371b306 128
ram54288 0:a7a43371b306 129 /*Frequency Class and related resources*/
ram54288 0:a7a43371b306 130 class FreqResource {
ram54288 0:a7a43371b306 131 public:
ram54288 0:a7a43371b306 132 FreqResource() {
ram54288 0:a7a43371b306 133
ram54288 0:a7a43371b306 134 // M2MObject* freq_object;
ram54288 0:a7a43371b306 135 freq_object = M2MInterfaceFactory::create_object("3318");
ram54288 0:a7a43371b306 136 M2MObjectInstance* freq_inst = freq_object->create_object_instance();
ram54288 0:a7a43371b306 137
ram54288 0:a7a43371b306 138
ram54288 0:a7a43371b306 139 // Why is it blinking only 4 time? - Ram
ram54288 0:a7a43371b306 140 // there's not really an execute LWM2M ID that matches... hmm...
ram54288 0:a7a43371b306 141 M2MResource* setValue_res = freq_inst->create_dynamic_resource("5900", "Set Value",
ram54288 0:a7a43371b306 142 M2MResourceInstance::FLOAT, true);
ram54288 0:a7a43371b306 143 // we allow executing a function here...
ram54288 0:a7a43371b306 144 setValue_res->set_operation(M2MBase::GET_PUT_ALLOWED);
ram54288 0:a7a43371b306 145 //setValue_res->set_value_updated_function(value_updated_callback2(this, &FreqResource::handle_put_bpm));
ram54288 0:a7a43371b306 146 setValue_res->set_execute_function(execute_callback(this, &FreqResource::handle_put_bpm));
ram54288 0:a7a43371b306 147 // Completion of execute function can take a time, that's why delayed response is used
ram54288 0:a7a43371b306 148 setValue_res->set_delayed_response(true);
ram54288 0:a7a43371b306 149
ram54288 0:a7a43371b306 150 //Max BPM
ram54288 0:a7a43371b306 151 M2MResource* maxBPM_res = freq_inst->create_dynamic_resource("5602", "Max BPM",
ram54288 0:a7a43371b306 152 M2MResourceInstance::FLOAT, true);
ram54288 0:a7a43371b306 153
ram54288 0:a7a43371b306 154 // we allow executing a function here...
ram54288 0:a7a43371b306 155 maxBPM_res->set_operation(M2MBase::GET_ALLOWED);
ram54288 0:a7a43371b306 156
ram54288 0:a7a43371b306 157 // Completion of execute function can take a time, that's why delayed response is used
ram54288 0:a7a43371b306 158 // maxBPM_res->set_delayed_response(true);
ram54288 0:a7a43371b306 159
ram54288 0:a7a43371b306 160 //Min BPM
ram54288 0:a7a43371b306 161 M2MResource* minBPM_res = freq_inst->create_dynamic_resource("5601", "Min BPM",
ram54288 0:a7a43371b306 162 M2MResourceInstance::FLOAT, true);
ram54288 0:a7a43371b306 163 // we allow executing a function here...
ram54288 0:a7a43371b306 164 minBPM_res->set_operation(M2MBase::GET_ALLOWED);
ram54288 0:a7a43371b306 165
ram54288 0:a7a43371b306 166 // Completion of execute function can take a time, that's why delayed response is used
ram54288 0:a7a43371b306 167 //minBPM_res->set_delayed_response(true);
ram54288 0:a7a43371b306 168
ram54288 0:a7a43371b306 169 //Reset Min/Max
ram54288 0:a7a43371b306 170 M2MResource* resetBPM_res = freq_inst->create_dynamic_resource("5605", "Reset Min/Max BPM",
ram54288 0:a7a43371b306 171 M2MResourceInstance::STRING, true);
ram54288 0:a7a43371b306 172 // we allow executing a function here...
ram54288 0:a7a43371b306 173 resetBPM_res->set_operation(M2MBase::POST_ALLOWED);
ram54288 0:a7a43371b306 174 resetBPM_res->set_execute_function(execute_callback(this, &FreqResource::handle_reset_minMax_bpm));
ram54288 0:a7a43371b306 175 // Completion of execute function can take a time, that's why delayed response is used
ram54288 0:a7a43371b306 176 resetBPM_res->set_delayed_response(true);
ram54288 0:a7a43371b306 177
ram54288 0:a7a43371b306 178 //Units
ram54288 0:a7a43371b306 179 M2MResource* unitsBPM_res = freq_inst->create_dynamic_resource("5701", "Units",
ram54288 0:a7a43371b306 180 M2MResourceInstance::STRING, true);
ram54288 0:a7a43371b306 181 // we allow executing a function here...
ram54288 0:a7a43371b306 182 unitsBPM_res->set_operation(M2MBase::GET_ALLOWED);
ram54288 0:a7a43371b306 183 // Completion of execute function can take a time, that's why delayed response is used
ram54288 0:a7a43371b306 184 //unitsBPM_res->set_delayed_response(true);
ram54288 0:a7a43371b306 185 unitsBPM_res->set_value((uint8_t*)"BPM",3);
ram54288 0:a7a43371b306 186 }
ram54288 0:a7a43371b306 187
ram54288 0:a7a43371b306 188
ram54288 0:a7a43371b306 189 ~FreqResource() {
ram54288 0:a7a43371b306 190
ram54288 0:a7a43371b306 191 }
ram54288 0:a7a43371b306 192
ram54288 0:a7a43371b306 193 void handle_put_bpm(void *argument){
ram54288 0:a7a43371b306 194
ram54288 0:a7a43371b306 195 status_ticker.detach();
ram54288 0:a7a43371b306 196 M2MObjectInstance* inst = freq_object->object_instance();
ram54288 0:a7a43371b306 197 M2MResource* setValue_res = inst->resource("5900");
ram54288 0:a7a43371b306 198
ram54288 0:a7a43371b306 199 // values in mbed Client are all buffers, and we need a vector of int's
ram54288 0:a7a43371b306 200 setValue_res->get_value(buffIn, sizeIn);
ram54288 0:a7a43371b306 201
ram54288 0:a7a43371b306 202 int temp=0;
ram54288 0:a7a43371b306 203 for(int i=0;i<sizeIn;i++){
ram54288 0:a7a43371b306 204 temp=temp*10+(int)buffIn[i]-48;
ram54288 0:a7a43371b306 205 }
ram54288 0:a7a43371b306 206 prev_bpm=temp;
ram54288 0:a7a43371b306 207
ram54288 0:a7a43371b306 208 if(prev_bpm < min_bpm)
ram54288 0:a7a43371b306 209 {
ram54288 0:a7a43371b306 210 min_bpm = prev_bpm;
ram54288 0:a7a43371b306 211 min_changed =1;
ram54288 0:a7a43371b306 212 }
ram54288 0:a7a43371b306 213 if(prev_bpm > max_bpm)
ram54288 0:a7a43371b306 214 {
ram54288 0:a7a43371b306 215 max_bpm = prev_bpm;
ram54288 0:a7a43371b306 216 max_changed = 1;
ram54288 0:a7a43371b306 217 }
ram54288 0:a7a43371b306 218 size_t tempo = 60/prev_bpm;
ram54288 0:a7a43371b306 219 status_ticker.attach(blinky,tempo);
ram54288 0:a7a43371b306 220
ram54288 0:a7a43371b306 221 bpm_changed = 1;
ram54288 0:a7a43371b306 222 }
ram54288 0:a7a43371b306 223
ram54288 0:a7a43371b306 224 void handle_set_bpm(){
ram54288 0:a7a43371b306 225
ram54288 0:a7a43371b306 226 M2MObjectInstance* inst = freq_object->object_instance();
ram54288 0:a7a43371b306 227 M2MResource* setValue_res = inst->resource("5900");
ram54288 0:a7a43371b306 228
ram54288 0:a7a43371b306 229 char buffer[20];
ram54288 0:a7a43371b306 230 int size = sprintf(buffer,"%d",prev_bpm);
ram54288 0:a7a43371b306 231 setValue_res->set_value((uint8_t*)buffer, size);
ram54288 0:a7a43371b306 232
ram54288 0:a7a43371b306 233 }
ram54288 0:a7a43371b306 234
ram54288 0:a7a43371b306 235 void handle_set_min_bpm(){
ram54288 0:a7a43371b306 236 //Send a notification
ram54288 0:a7a43371b306 237 M2MObjectInstance* inst = freq_object->object_instance();
ram54288 0:a7a43371b306 238 M2MResource* minBPM_res = inst->resource("5601");
ram54288 0:a7a43371b306 239 pc.printf("%d",min_bpm);
ram54288 0:a7a43371b306 240 char buffer[20];
ram54288 0:a7a43371b306 241 int size = sprintf(buffer,"%d",min_bpm);
ram54288 0:a7a43371b306 242 minBPM_res->set_value((uint8_t*)buffer, size);
ram54288 0:a7a43371b306 243
ram54288 0:a7a43371b306 244
ram54288 0:a7a43371b306 245 }
ram54288 0:a7a43371b306 246 void handle_set_max_bpm(){
ram54288 0:a7a43371b306 247 //Send a notification
ram54288 0:a7a43371b306 248 M2MObjectInstance* inst = freq_object->object_instance();
ram54288 0:a7a43371b306 249 M2MResource* maxBPM_res = inst->resource("5602");
ram54288 0:a7a43371b306 250
ram54288 0:a7a43371b306 251 char buffer[20];
ram54288 0:a7a43371b306 252 int size = sprintf(buffer,"%d",max_bpm);
ram54288 0:a7a43371b306 253 maxBPM_res->set_value((uint8_t*)buffer, size);
ram54288 0:a7a43371b306 254
ram54288 0:a7a43371b306 255
ram54288 0:a7a43371b306 256 }
ram54288 0:a7a43371b306 257
ram54288 0:a7a43371b306 258 void handle_reset_minMax_bpm(void *argument){
ram54288 0:a7a43371b306 259 //Handle request to reset the min_max values to zero and 1000000 each
ram54288 0:a7a43371b306 260
ram54288 0:a7a43371b306 261 M2MObjectInstance* inst = freq_object->object_instance();
ram54288 0:a7a43371b306 262 M2MResource* minBPM_res = inst->resource("5601");
ram54288 0:a7a43371b306 263 M2MResource* maxBPM_res = inst->resource("5602");
ram54288 0:a7a43371b306 264
ram54288 0:a7a43371b306 265 minBPM_res->set_value(0);
ram54288 0:a7a43371b306 266 maxBPM_res->set_value(0);
ram54288 0:a7a43371b306 267 }
ram54288 0:a7a43371b306 268
ram54288 0:a7a43371b306 269 M2MObject* get_object() {
ram54288 0:a7a43371b306 270 return freq_object;
ram54288 0:a7a43371b306 271 }
ram54288 0:a7a43371b306 272
ram54288 0:a7a43371b306 273 private:
ram54288 0:a7a43371b306 274 M2MObject* freq_object;
ram54288 0:a7a43371b306 275 };
ram54288 0:a7a43371b306 276
ram54288 0:a7a43371b306 277 int main()
ram54288 0:a7a43371b306 278 {
ram54288 0:a7a43371b306 279 // Seed the RNG for networking purposes
ram54288 0:a7a43371b306 280 unsigned seed = utils::entropy_seed();
ram54288 0:a7a43371b306 281 srand(seed);
ram54288 0:a7a43371b306 282
ram54288 0:a7a43371b306 283 // LEDs are active LOW - true/1 means off, false/0 means on
ram54288 0:a7a43371b306 284 // Use the constants for easier reading
ram54288 0:a7a43371b306 285 g_led_red = active_low::off;
ram54288 0:a7a43371b306 286 g_led_green = active_low::off;
ram54288 0:a7a43371b306 287 g_led_blue = active_low::off;
ram54288 0:a7a43371b306 288
ram54288 0:a7a43371b306 289
ram54288 0:a7a43371b306 290 // Button falling edge is on push (rising is on release)
ram54288 0:a7a43371b306 291 g_button_mode.fall(&on_mode);
ram54288 0:a7a43371b306 292 g_button_tap.fall(&on_tap);
ram54288 0:a7a43371b306 293
ram54288 0:a7a43371b306 294 #ifdef IOT_ENABLED
ram54288 0:a7a43371b306 295 // Turn on the blue LED until connected to the network
ram54288 0:a7a43371b306 296 // g_led_blue = active_low::off;
ram54288 0:a7a43371b306 297
ram54288 0:a7a43371b306 298
ram54288 0:a7a43371b306 299 // Need to be connected with Ethernet cable for success
ram54288 0:a7a43371b306 300 EthernetInterface ethernet;
ram54288 0:a7a43371b306 301 if (ethernet.connect() != 0)
ram54288 0:a7a43371b306 302 return 1;
ram54288 0:a7a43371b306 303
ram54288 0:a7a43371b306 304 // Pair with the device connector
ram54288 0:a7a43371b306 305 frdm_client client("coap://api.connector.mbed.com:5684", &ethernet);
ram54288 0:a7a43371b306 306 if (client.get_state() == frdm_client::state::error)
ram54288 0:a7a43371b306 307 return 1;
ram54288 0:a7a43371b306 308
ram54288 0:a7a43371b306 309 // The REST endpoints for this device
ram54288 0:a7a43371b306 310 // Add your own M2MObjects to this list with push_back before client.connect()
ram54288 0:a7a43371b306 311 M2MObjectList objects;
ram54288 0:a7a43371b306 312
ram54288 0:a7a43371b306 313 //Frequency device definition and instance definition
ram54288 0:a7a43371b306 314 FreqResource freq_resource;
ram54288 0:a7a43371b306 315
ram54288 0:a7a43371b306 316 M2MDevice* device = frdm_client::make_device();
ram54288 0:a7a43371b306 317 objects.push_back(device);
ram54288 0:a7a43371b306 318 objects.push_back(freq_resource.get_object());
ram54288 0:a7a43371b306 319
ram54288 0:a7a43371b306 320 // Publish the RESTful endpoints
ram54288 0:a7a43371b306 321 client.connect(objects);
ram54288 0:a7a43371b306 322
ram54288 0:a7a43371b306 323 // Connect complete; turn off blue LED forever
ram54288 0:a7a43371b306 324 //g_led_blue = active_low::on;
ram54288 0:a7a43371b306 325
ram54288 0:a7a43371b306 326 #endif
ram54288 0:a7a43371b306 327
ram54288 0:a7a43371b306 328 while (true)
ram54288 0:a7a43371b306 329 {
ram54288 0:a7a43371b306 330 //updates.wait(25000);
ram54288 0:a7a43371b306 331 #ifdef IOT_ENABLED
ram54288 0:a7a43371b306 332 if (client.get_state() == frdm_client::state::error)
ram54288 0:a7a43371b306 333 break;
ram54288 0:a7a43371b306 334 #endif
ram54288 0:a7a43371b306 335
ram54288 0:a7a43371b306 336 // Insert any code that must be run continuously here
ram54288 0:a7a43371b306 337 if(bpm_changed){
ram54288 0:a7a43371b306 338 bpm_changed = 0;
ram54288 0:a7a43371b306 339 freq_resource.handle_set_bpm();
ram54288 0:a7a43371b306 340 }
ram54288 0:a7a43371b306 341
ram54288 0:a7a43371b306 342 if(min_changed) {
ram54288 0:a7a43371b306 343 min_changed = 0;
ram54288 0:a7a43371b306 344 freq_resource.handle_set_min_bpm();
ram54288 0:a7a43371b306 345 }
ram54288 0:a7a43371b306 346 if(max_changed) {
ram54288 0:a7a43371b306 347 max_changed = 0;
ram54288 0:a7a43371b306 348 freq_resource.handle_set_max_bpm();
ram54288 0:a7a43371b306 349 }
ram54288 0:a7a43371b306 350
ram54288 0:a7a43371b306 351 }
ram54288 0:a7a43371b306 352
ram54288 0:a7a43371b306 353 #ifdef IOT_ENABLED
ram54288 0:a7a43371b306 354 client.disconnect();
ram54288 0:a7a43371b306 355 #endif
ram54288 0:a7a43371b306 356 return 1;
ram54288 0:a7a43371b306 357 }