main.cpp 15.2 KB
Newer Older
philip's avatar
philip committed
1
2
#include "config.h"

philip's avatar
philip committed
3
#include "stm32h7xx_ll_utils.h"
philip's avatar
philip committed
4
5
6
7
8
9
10
11
12

#include "AggregatMotor.h"

#if USE_USBMIDI == 1
#include "UsbMidiAggregat.h"
#endif

#if USE_NETMIDI == 1
#include "EthernetInterface.h"
philip's avatar
philip committed
13
14
// #include "LWIPStack.h"
#include "nsapi_types.h"
philip's avatar
philip committed
15
16
#endif

17
18
#include "midimessage/midimessage.h"
#include "midimessage/simpleparser.h"
philip's avatar
philip committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

/************ TYPES ************/

typedef enum {
    SourceUsb,
    SourceMidi,
    SourceNet
} Source;

typedef enum {
    ConfigStateValid = 0x1337BEEF
} ConfigState;

typedef struct {
    ConfigState config_state;
philip's avatar
philip committed
34
    uint32_t device_id;
philip's avatar
philip committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    // volatile uint8_t channel_offset;
    // volatile uint8_t controller_offset;
} __attribute__((packed)) Config;

/************ SIGNATURES ************/

void load_config();
void save_config();

void motors_init();
void motors_suspend();
void motors_resume();

void controller_init();
void controller_handle_msg(uint8_t * buffer, size_t length, Source source);

#if USE_USBMIDI == 1
void usbmidi_init();
philip's avatar
philip committed
53
void usbmidi_run();
philip's avatar
philip committed
54
void usbmidi_tx(uint8_t * buffer, size_t length);
philip's avatar
philip committed
55

philip's avatar
philip committed
56
57
// void usbmidi_event_callback();
void usbmidi_rx(uint8_t * buffer, uint8_t length, void * context); // parser callback handler
philip's avatar
philip committed
58
59
#else //USE_USBMIDI == 0
#define usbmidi_init()
philip's avatar
philip committed
60
#define usbmidi_run()
philip's avatar
philip committed
61
62
63
64
65
66
67
#define usbmidi_tx()
#endif //USE_USBMIDI

#if USE_MIDI == 1
void midi_init();
void midi_run();
void midi_tx(uint8_t * buffer, size_t length);
philip's avatar
philip committed
68

philip's avatar
philip committed
69
70
71
72
73
74
75
76
77
void midi_rx(uint8_t * buffer, uint8_t length, void * context); // parser callback handler
#else //USE_MIDI == 0
#define midi_init()
#define midi_tx(buffer, length)
#define midi_run()
#endif //USE_MIDI

#if USE_NETMIDI == 1
void netmidi_init();
philip's avatar
philip committed
78
void netmidi_run();
philip's avatar
philip committed
79
void netmidi_tx(uint8_t * buffer, size_t length);
philip's avatar
philip committed
80
81
82

void eth_status_changed(nsapi_event_t evt, intptr_t intptr);
void eth_ifup();
philip's avatar
philip committed
83
84
#else //USE_NETMIDI == 0
#define netmidi_init()
philip's avatar
philip committed
85
#define netmidi_run()
philip's avatar
philip committed
86
87
88
89
90
#define netmidi_tx(buffer, length)
#endif //USE_NETMIDI

/************ LOCAL VARIABLES ************/

91
// will be overwritten immediately by load_config()
philip's avatar
philip committed
92
Config config = {
93
    .device_id = 0, 
philip's avatar
philip committed
94
95
96
97
};

volatile bool motors_running = false;
AggregatMotor motors[MOTOR_COUNT] = {
philip's avatar
philip committed
98
  AggregatMotor(MOTOR_1_PIN, MOTOR_REFRESH_RATE_HZ, MOTOR_PULSEWIDTH_MIN_USEC, MOTOR_PULSEWIDTH_MAX_USEC)
philip's avatar
philip committed
99
100
101
102
103
};

volatile int32_t channel_offset = CHANNEL_OFFSET;
volatile int32_t controller_offset = CONTROLLER_OFFSET;

philip's avatar
test    
philip committed
104

philip's avatar
philip committed
105
#if USE_USBMIDI == 1
philip's avatar
philip committed
106
107
DigitalOut usbmidi_led(USB_CONNECTED_LED);
UsbMidiAggregat usbmidi(USB_POWER_PIN, false);
philip's avatar
philip committed
108
109
bool usb_to_midi = USBMIDI_FORWARD_TO_MIDI;
bool usb_to_net = USBMIDI_FORWARD_TO_NET;
philip's avatar
philip committed
110
111

MidiMessage::SimpleParser_t usbmidi_parser;
philip's avatar
philip committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#endif

#if USE_MIDI == 1
BufferedSerial midi(MIDI_TX_PIN, MIDI_RX_PIN);
bool midi_to_usb = MIDI_FORWARD_TO_USB;
bool midi_to_net = MIDI_FORWARD_TO_NET;

MidiMessage::SimpleParser_t midi_parser;
// volatile State midi_state = StateStopped;
// Thread midi_thread;
#endif

#if USE_NETMIDI == 1
EthernetInterface eth;
philip's avatar
philip committed
126
127
Thread net_thread;
SocketAddress ip;
philip's avatar
philip committed
128
UDPSocket udp_sock;
philip's avatar
philip committed
129

philip's avatar
test    
philip committed
130
bool eth_reconnect = false; 
philip's avatar
philip committed
131

philip's avatar
philip committed
132
133
DigitalOut net_led(NET_STATUS_LED);

philip's avatar
philip committed
134
135
bool net_to_midi = NETMIDI_FORWARD_TO_MIDI;
bool net_to_usb = NETMIDI_FORWARD_TO_USB;
philip's avatar
philip committed
136
137
char net_hostname[64] = "";
char net_servicename[64] = "";
philip's avatar
philip committed
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// ns_mdns_t mdns_responder = NULL;
#endif

/************ INLINE FUNCTIONS ************/

inline float u7_to_pos(uint8_t value)
{
    // assert_param((value & 0x7F) == 0);

    return ((float)value) / 128.0;
}

inline float u14_to_pos(uint16_t value)
{
    // assert_param((value & 0x3FFF) == 0);

    return ((float)value) / 16383.0;
}

inline float s14_to_pos(int value)
{
    return u14_to_pos(value + 8192);
}

philip's avatar
philip committed
162
163
164

void do_nothing(){}

philip's avatar
philip committed
165
166
167
168
169
170
/************ FUNCTIONS ************/



void load_config()
{
philip's avatar
philip committed
171
172
173
174
175
176
177
    uint32_t uidxor = LL_GetUID_Word0() ^ LL_GetUID_Word1() ^ LL_GetUID_Word2();

    config.device_id = uidxor;


    srand(uidxor + time(NULL));

philip's avatar
philip committed
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    // config.channel_offset = CHANNEL_OFFSET;
    // config.controller_offset = CONTROLLER_OFFSET;
}

void save_config()
{

}

void motors_init()
{
    for(int i = 0; i < MOTOR_COUNT; i++){

        // init to center position
        motors[i].set(0.5);

        // start suspended
        motors[i].suspend();
    }
}

void motors_suspend()
{
    for(int i = 0; i < MOTOR_COUNT; i++){
        motors[i].suspend();
    }

    motors_running = false;
}

void motors_resume()
{
    for(int i = 0; i < MOTOR_COUNT; i++){
        motors[i].resume();
    }
    motors_running = true;
}

void controller_init()
{

}

void controller_handle_msg(uint8_t * buffer, size_t length, Source source)
{
philip's avatar
test    
philip committed
223
    printf("CMD (len %d) ", length);
philip's avatar
philip committed
224
225
226
227
228
    for(int i = 0; i < length; i++){
        printf("%02x", buffer[i]);
    }
    printf("\n");

229
230

    #if ENABLE_CONTROLLER_LOGIC == 1
philip's avatar
philip committed
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    MIDIMessage msg;

    msg.from_raw(buffer, length);

    if (msg.length == 1){   // system real time messages

        // 0xFA = start, 0xFB = continue
        if (msg.data[0] == 0xFA || msg.data[0] == 0xFB){
            motors_resume();
        }

        // 0xFC = stop
        if (msg.data[0] == 0xFC){
            motors_suspend();
        }

        #if ENABLE_SYSTEM_RESET == 1
        // 0xFF = reset
        if (msg.data[0] == 0xFF){
            system_reset();
philip's avatar
philip committed
251
            printf("system_reset??\n");
philip's avatar
philip committed
252
        }
philip's avatar
philip committed
253
254
        #else
        printf("ENABLE_SYSTEM_RESET == 0\n");
philip's avatar
philip committed
255
256
257
258
259
260
261
262
263
264
265
266
        #endif
    }



    if (msg.type() == MIDIMessage::ControlChangeType){

        if (msg.channel() == channel_offset){
            int32_t motori = msg.controller() - controller_offset;

            if (0 <= motori && motori < MOTOR_COUNT){
                float pos = u7_to_pos(msg.value());
philip's avatar
philip committed
267
                printf("motor[%d] = %d\n", motori, (int)(pos*100));
philip's avatar
philip committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
                motors[motori] = pos;
            }
        }
    }

    // each channel controls a motor starting from channel_offset
    if (msg.type() == MIDIMessage::PitchWheelType){
        int32_t motori = msg.channel() - channel_offset;
        
        if (0 <= motori && motori < MOTOR_COUNT){
            float pos = s14_to_pos(msg.pitch());
            motors[motori] = pos;
        }
        
    }
philip's avatar
philip committed
283

284
285
    #endif //ENABLE_CONTROLLER_LOGIC == 1

philip's avatar
philip committed
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
    if (source == SourceUsb){
        if (usb_to_midi){
            midi_tx(buffer, length);
        }
        if (usb_to_net){
            netmidi_tx(buffer, length);
        }
    }
    if (source == SourceMidi){
        if (midi_to_usb){
            usbmidi_tx(buffer, length);
        }
        if (midi_to_net){
            netmidi_tx(buffer, length);
        }
    }
philip's avatar
philip committed
302
303
304
305
306
307
308
}


#if USE_USBMIDI == 1

void usbmidi_init()
{
philip's avatar
philip committed
309
310
311
312
313
314
315
316
    // usbmidi.attach(do_nothing);
    // [](){
    //     // do nothing (it's really sad, but if there is no callback attached, it doesn't work...)
    // });

    static uint8_t buffer[128];

    MidiMessage::simpleparser_init(&usbmidi_parser, true, (uint8_t*)&buffer, sizeof(buffer), usbmidi_rx, NULL, NULL);
philip's avatar
philip committed
317
318
}

philip's avatar
philip committed
319
void usbmidi_run()
philip's avatar
philip committed
320
{
philip's avatar
philip committed
321
322
323
324
325
    usbmidi_led = usbmidi.connected();

    if (usbmidi.connected() == false){

        if (usbmidi.just_reconnected()){
philip's avatar
test    
philip committed
326
            // midi_tx((uint8_t*)"1\n", 2);
philip's avatar
philip committed
327
328
329
330
331
332
            usbmidi.connect();
        }

        return;
    } 

philip's avatar
test    
philip committed
333
    // printf("usbmidi.ready() = %d\n", usbmidi.ready());
philip's avatar
philip committed
334
    if (!usbmidi.ready()){
philip's avatar
philip committed
335
336
337
        return;
    }

philip's avatar
test    
philip committed
338
    
philip's avatar
philip committed
339
    if (usbmidi.readable()){
philip's avatar
test    
philip committed
340
        printf("ubsmidi.readable() = %d\n", usbmidi.readable());    
philip's avatar
philip committed
341
        // mark activity
philip's avatar
test    
philip committed
342
        // usbmidi_led = 0;
philip's avatar
philip committed
343

philip's avatar
philip committed
344
345
        MIDIMessage msg;

346
        usbmidi.read(msg);
philip's avatar
philip committed
347

348
        if (msg.length == 0){
philip's avatar
philip committed
349
350
351
            return;
        }

352
353
        // MIDIMessage can contain multiple messages, thus we have to parse them like a stream...
        MidiMessage::simpleparser_receivedData(&usbmidi_parser, msg.data, (uint8_t)msg.length);
philip's avatar
philip committed
354
355
356
    }
}

philip's avatar
philip committed
357
358
359
360
361
void usbmidi_rx(uint8_t * buffer, uint8_t length, void * context) // parser callback handler
{
    controller_handle_msg(buffer, length, SourceUsb);
}

philip's avatar
philip committed
362
363
364
365
366
367
void usbmidi_tx(uint8_t * buffer, size_t length)
{
    if (usbmidi.ready() == false){
        return;
    }

368
    usbmidi.write(buffer, length);
philip's avatar
philip committed
369
}
philip's avatar
philip committed
370

philip's avatar
philip committed
371
372
373
374
375
376
377
#endif //USE_USBMIDI == 1


#if USE_MIDI == 1

void midi_init()
{
philip's avatar
philip committed
378
379
    printf("midi_init()\n");

philip's avatar
philip committed
380
    // setup MIDI UART according to specs
philip's avatar
philip committed
381
382
    midi.set_baud(MIDI_BAUD); // 31.25kbaud
    midi.set_format(MIDI_BITS, MIDI_PARITY, MIDI_STOP); // 8 data bits, no parity, 1 stop bit
philip's avatar
philip committed
383
384
385
386
    midi.set_flow_control(BufferedSerial::Disabled);

    midi.set_blocking(false);

philip's avatar
philip committed
387
    static uint8_t buffer[128];
philip's avatar
philip committed
388
389
390
391

    MidiMessage::simpleparser_init(&midi_parser, true, (uint8_t*)&buffer, sizeof(buffer), midi_rx, NULL, NULL);
}

philip's avatar
philip committed
392
393
394
void midi_run()
{
    static uint8_t buffer[128];
philip's avatar
philip committed
395

philip's avatar
philip committed
396
397
398
399
400
401
402
    if (midi.readable()){

        size_t rlen = midi.read(buffer, sizeof(buffer));

        if (rlen > 0){
            // echo
            // midi_tx(buffer,rlen);
403
            // printf("midi rx %d\n", rlen);
philip's avatar
philip committed
404
405
406
407
408
409

            MidiMessage::simpleparser_receivedData(&midi_parser, buffer, (uint8_t)rlen);
        }
    }
}

410
411
412
413
414
void midi_rx(uint8_t * buffer, uint8_t length, void * context)
{
    controller_handle_msg(buffer, length, SourceMidi);
}

philip's avatar
philip committed
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
void midi_tx(uint8_t * buffer, size_t length)
{
    if (midi.writable() == false){
        return;
    }

    midi.write(buffer, length);
}
    
#endif //USE_MIDI == 1

#if USE_NETMIDI == 1

void netmidi_init()
{
philip's avatar
philip committed
430
431
432
433
434
435
436
437
    const char * mac = eth.get_mac_address();
    printf("mac %s\n", mac ? mac : "none");

    sprintf(net_hostname, NET_HOSTNAME_FMT, config.device_id);
    printf("hostname %s\n", net_hostname);

    sprintf(net_servicename, NET_SERVICENAME_FMT, config.device_id);
    printf("servicename %s\n", net_servicename);
philip's avatar
philip committed
438

philip's avatar
philip committed
439
    eth.add_event_listener(eth_status_changed);
philip's avatar
philip committed
440
441


philip's avatar
philip committed
442
443
444
445
446
    if (udp_sock.open(&eth)){
        printf("open error\n");
        return;
    }
    printf("opened\n");
philip's avatar
philip committed
447

philip's avatar
philip committed
448
449
450
451
452
453
454
455
456
    if (udp_sock.bind(7)){
        printf("bind error\n");
        return;
    }
    printf("bound to port\n");

    udp_sock.set_blocking(false);

    // eth_reconnect = true;
philip's avatar
philip committed
457
    
philip's avatar
philip committed
458
459
460

    net_thread.start(eth_ifup);
}
philip's avatar
philip committed
461

philip's avatar
philip committed
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
void eth_status_changed(nsapi_event_t evt, intptr_t intptr)
{
    if (evt != NSAPI_EVENT_CONNECTION_STATUS_CHANGE){
        return;
    }

    static bool eth_was_up = false;

    switch(eth.get_connection_status()){
        case NSAPI_STATUS_LOCAL_UP: 
            printf("eth local up\n");
            return;

        case NSAPI_STATUS_GLOBAL_UP:
            eth_was_up = true;
philip's avatar
philip committed
477
            printf("eth global up\n");
philip's avatar
philip committed
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
            return;

        case NSAPI_STATUS_DISCONNECTED: 
            printf("eth disconnected!\n");
            return;

        case NSAPI_STATUS_CONNECTING:
            printf("eth connecting\n");
            if (eth_was_up){
                eth_was_up = false;
                eth_reconnect = true;
                printf("should reconnect\n");
                // eth.disconnect();
            }
            return;

        case NSAPI_STATUS_ERROR_UNSUPPORTED:
            printf("eth unsupported\n");
            return;
    }
}

bool eth_connect()
{
    // printf("eth.status = %d\n", eth.get_connection_status());
    if (eth.get_connection_status() != NSAPI_STATUS_DISCONNECTED){
        eth.disconnect();
    }

    eth.set_default_parameters();

    // to force dhcp
    eth.set_network("0.0.0.0", "0.0.0.0", "0.0.0.0");

    int res;
philip's avatar
philip committed
513
    
philip's avatar
philip committed
514
515
    do {
        res = eth.connect();
philip's avatar
philip committed
516
    } while( res != NSAPI_ERROR_OK && res != NSAPI_ERROR_DHCP_FAILURE );
philip's avatar
philip committed
517

philip's avatar
test    
philip committed
518
519
520
521
    // if (res == NSAPI_ERROR_NO_CONNECTION){
    //     return false;
    // }

philip's avatar
philip committed
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
    if (res == NSAPI_ERROR_OK) {
    
        // Show the network address
        eth.get_ip_address(&ip);
        printf("%s: %s\n", ip.get_ip_version() == NSAPI_IPv4 ? "ipv4" : "ipv6", ip.get_ip_address());

        return true;
    }

    if (res != NSAPI_ERROR_DHCP_FAILURE){
        printf("connect failed: %d\n", res);
        return false;
    }

    printf("dhcp timeout\n");

philip's avatar
philip committed
538

philip's avatar
philip committed
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
    res = eth.get_ipv6_link_local_address(&ip);

    if (res == NSAPI_ERROR_OK){
        printf("ipv6 link-local: %s\n", ip.get_ip_address());
        return true;
    }

    if (res == NSAPI_ERROR_UNSUPPORTED){
        printf("ipv6 link-local not supported\n");
    } else {
        printf("ipv6 link-local fail: %d\n", res);
    }

    // has to disconnect to set manual address
    eth.disconnect();

    // setup ipv4 link-local address
    uint8_t s3 = (((config.device_id >> 24) ^ (config.device_id >> 16)) % 254) + 1;
    uint8_t s4 = (config.device_id >> 8) ^ config.device_id;
    char ll[20] = "";
    sprintf(ll, "169.254.%hhu.%hhu", s3, s4);
    ip.set_ip_address(ll);
philip's avatar
philip committed
561
562


philip's avatar
philip committed
563
564
565
566
567
568
569
570
571
    printf("Using ipv4 link-local: %s/16\n", ll);
    eth.set_network(ip, "255.255.0.0", "0.0.0.0");

    if (eth.connect()){
        printf("link-local connect fail!\n");
        return false;
    } 

    return true;
philip's avatar
philip committed
572
573
}

philip's avatar
philip committed
574
void eth_ifup()
philip's avatar
philip committed
575
{
philip's avatar
philip committed
576
577
578
579
    printf("eth_ifup()\n");

    eth_reconnect = true;

580

philip's avatar
philip committed
581
582
    while (1){

philip's avatar
test    
philip committed
583
584
585
586
587
588
589
590
591
        // if (exclusive_source == ExclusiveSourceNone){
        //     ThisThread::sleep_for(1000);
        //     continue;
        // }

        // if (exclusive_source_mutex.trylock() == false){
        //     continue;
        // }

philip's avatar
philip committed
592
593
594
595
596
        if (eth_reconnect == false){
            ThisThread::sleep_for(1000);
            continue;
        }

philip's avatar
test    
philip committed
597

philip's avatar
philip committed
598
        if (eth_connect() == false){
philip's avatar
test    
philip committed
599
            // exclusive_source_mutex.unlock();
philip's avatar
philip committed
600
601
602
            return;
        }
        
philip's avatar
test    
philip committed
603
604
605
        // exclusive_source = ExclusiveSourceNet;
        // exclusive_source_mutex.unlock();

philip's avatar
philip committed
606
607
        eth_reconnect = false;

philip's avatar
test    
philip committed
608
        // SocketAddress addr;
philip's avatar
philip committed
609

philip's avatar
test    
philip committed
610
        // uint8_t hello[] = "hello!";
philip's avatar
philip committed
611

philip's avatar
test    
philip committed
612
613
        // addr.set_ip_address("169.254.108.82");
        // addr.set_port(6666);
philip's avatar
philip committed
614

philip's avatar
test    
philip committed
615
616
617
618
619
620
621
        // int r = udp_sock.sendto(addr, hello, sizeof(hello));
        // if (r < 0){
        //     printf("tx err %d\n", r);
        //     continue;
        // } else {
        //     printf("sent hello\n");
        // }
philip's avatar
philip committed
622
623
    }

philip's avatar
philip committed
624
625
}

philip's avatar
philip committed
626
627
void netmidi_run()
{
philip's avatar
philip committed
628
629
    net_led = eth.get_connection_status() == NSAPI_STATUS_GLOBAL_UP;

philip's avatar
philip committed
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
    if (eth.get_connection_status() != NSAPI_STATUS_GLOBAL_UP){
        return;
    }

    SocketAddress addr;

    addr.set_ip_address("169.254.108.82");
    addr.set_port(6666);

    uint8_t data[256];

    nsapi_size_or_error_t res = udp_sock.recv(data, sizeof(data));

    if (res > 0){
        data[res] = '\0';
        printf("udp rx (%d) %s", res, data);
        
        // echo back
        udp_sock.sendto(addr, data, res);
    }
}

philip's avatar
philip committed
652
653
void netmidi_tx(uint8_t * buffer, size_t length)
{
654
    //TODO 
philip's avatar
philip committed
655
656
657
658
659
660
661
}

#endif //USE_NETMIDI == 1

// main() runs in its own thread in the OS
int main()
{
philip's avatar
philip committed
662
663
    printf("\nRESTART\n");
    // midi_tx((uint8_t*)"RESTART\n",8);
philip's avatar
philip committed
664

philip's avatar
philip committed
665
666
667
    load_config();
    
    // initialize motors
philip's avatar
philip committed
668
    motors_init();
philip's avatar
philip committed
669
670

    // initialize controller
philip's avatar
philip committed
671
    controller_init();
philip's avatar
philip committed
672
673
674
675

    // any com interface initialization
    usbmidi_init();
    midi_init();
philip's avatar
philip committed
676
    netmidi_init();
philip's avatar
philip committed
677
678
679
680

    // start up handlers
    // midi_start();

philip's avatar
philip committed
681
    motors_resume();
philip's avatar
philip committed
682

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
    // Thread thr;

    // thr.start([](){

    //     while(1){
    //         printf("midi_tx\n");

    //         static uint8_t controller = 1;
    //         static uint8_t value = 127;

    //         value = (value + 1) % 128;

    //         uint8_t cc[3] = {0xB1, controller, value};

    //         usbmidi_tx(cc, 3);

    //         wait_us(1000000);
    //     }

    // });

philip's avatar
philip committed
704
    while (true) {
philip's avatar
philip committed
705
        usbmidi_run();
philip's avatar
philip committed
706
        midi_run();
philip's avatar
philip committed
707
        netmidi_run();
708
709
710
711
712
713
714
715
716
717
718
719
720
721


// if (usbmidi.ready()){
//             static uint8_t controller = 1;
//             static uint8_t value = 127;

//             value = (value + 1) % 128;

//             uint8_t cc[3] = {0xB1, controller, value};

//             usbmidi_tx(cc, 3);

//             wait_us(1000000);
// }
philip's avatar
philip committed
722
723
724
    }
}