The document describes the LinnStrument, an open-source musical instrument created by Geert Bevin. It uses Arduino boards and sensors to allow for touch-based music performance and expression in 3D. The document discusses the hardware components, including LEDs, sensors, and foot pedals. It also covers accessing these components through Arduino code and firmware, including touch tracking, MIDI output, and debugging tools. The goal is to make the instrument fully hackable and customizable through open-source software and tools.
LinnStrument is an expressive electronic musical instrument with five dimensions of touch sensing. It is built with open-source hardware, the Arduino Due and runs open-source firmware. There are hundreds of playing cells and multi-color LEDs, making it ideal to discover embedded Arduino development with concrete musical and visual results.
This session will introduce the Arduino development concepts, tie them back to the actual hardware, provide an overview of the main algorithms in the LinnStrument firmware that are responsible for the musical feel and explain valuable lessons that were learned during the development of the firmware.
Arduino is an open-source project that created microcontroller-based kits for building digital devices and interactive objects that can sense and control physical devices.
A webinar presented to the members of EUROAVIA Patras as an introduction to the Arduino microcontroller. It goes over the basics of the controllers features and capabilities, and guides the participant through their first steps of programming an Arduino using C++.
Unleash Unlimited Potential with One-Time Purchase
BoxLang is more than just a language; it's a community. By choosing a Visionary License, you're not just investing in your success, you're actively contributing to the ongoing development and support of BoxLang.
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...Juraj Vysvader
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I didn't get rich from it but it did have 63K downloads (powered possible tens of thousands of websites).
More Related Content
Similar to LinnStrument : the ultimate open-source hacker instrument
LinnStrument is an expressive electronic musical instrument with five dimensions of touch sensing. It is built with open-source hardware, the Arduino Due and runs open-source firmware. There are hundreds of playing cells and multi-color LEDs, making it ideal to discover embedded Arduino development with concrete musical and visual results.
This session will introduce the Arduino development concepts, tie them back to the actual hardware, provide an overview of the main algorithms in the LinnStrument firmware that are responsible for the musical feel and explain valuable lessons that were learned during the development of the firmware.
Arduino is an open-source project that created microcontroller-based kits for building digital devices and interactive objects that can sense and control physical devices.
A webinar presented to the members of EUROAVIA Patras as an introduction to the Arduino microcontroller. It goes over the basics of the controllers features and capabilities, and guides the participant through their first steps of programming an Arduino using C++.
Unleash Unlimited Potential with One-Time Purchase
BoxLang is more than just a language; it's a community. By choosing a Visionary License, you're not just investing in your success, you're actively contributing to the ongoing development and support of BoxLang.
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...Juraj Vysvader
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I didn't get rich from it but it did have 63K downloads (powered possible tens of thousands of websites).
Software Engineering, Software Consulting, Tech Lead, Spring Boot, Spring Cloud, Spring Core, Spring JDBC, Spring Transaction, Spring MVC, OpenShift Cloud Platform, Kafka, REST, SOAP, LLD & HLD.
Do you want Software for your Business? Visit Deuglo
Deuglo has top Software Developers in India. They are experts in software development and help design and create custom Software solutions.
Deuglo follows seven steps methods for delivering their services to their customers. They called it the Software development life cycle process (SDLC).
Requirement — Collecting the Requirements is the first Phase in the SSLC process.
Feasibility Study — after completing the requirement process they move to the design phase.
Design — in this phase, they start designing the software.
Coding — when designing is completed, the developers start coding for the software.
Testing — in this phase when the coding of the software is done the testing team will start testing.
Installation — after completion of testing, the application opens to the live server and launches!
Maintenance — after completing the software development, customers start using the software.
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteGoogle
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
👉👉 Click Here To Get More Info 👇👇
https://sumonreview.com/ai-pilot-review/
AI Pilot Review: Key Features
✅Deploy AI expert bots in Any Niche With Just A Click
✅With one keyword, generate complete funnels, websites, landing pages, and more.
✅More than 85 AI features are included in the AI pilot.
✅No setup or configuration; use your voice (like Siri) to do whatever you want.
✅You Can Use AI Pilot To Create your version of AI Pilot And Charge People For It…
✅ZERO Manual Work With AI Pilot. Never write, Design, Or Code Again.
✅ZERO Limits On Features Or Usages
✅Use Our AI-powered Traffic To Get Hundreds Of Customers
✅No Complicated Setup: Get Up And Running In 2 Minutes
✅99.99% Up-Time Guaranteed
✅30 Days Money-Back Guarantee
✅ZERO Upfront Cost
See My Other Reviews Article:
(1) TubeTrivia AI Review: https://sumonreview.com/tubetrivia-ai-review
(2) SocioWave Review: https://sumonreview.com/sociowave-review
(3) AI Partner & Profit Review: https://sumonreview.com/ai-partner-profit-review
(4) AI Ebook Suite Review: https://sumonreview.com/ai-ebook-suite-review
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus
As part of the DOE Integrated Research Infrastructure (IRI) program, NERSC at Lawrence Berkeley National Lab and ALCF at Argonne National Lab are working closely with General Atomics on accelerating the computing requirements of the DIII-D experiment. As part of the work the team is investigating ways to speedup the time to solution for many different parts of the DIII-D workflow including how they run jobs on HPC systems. One of these routes is looking at Globus Compute as a way to replace the current method for managing tasks and we describe a brief proof of concept showing how Globus Compute could help to schedule jobs and be a tool to connect compute at different facilities.
AI Genie Review: World’s First Open AI WordPress Website CreatorGoogle
AI Genie Review: World’s First Open AI WordPress Website Creator
👉👉 Click Here To Get More Info 👇👇
https://sumonreview.com/ai-genie-review
AI Genie Review: Key Features
✅Creates Limitless Real-Time Unique Content, auto-publishing Posts, Pages & Images directly from Chat GPT & Open AI on WordPress in any Niche
✅First & Only Google Bard Approved Software That Publishes 100% Original, SEO Friendly Content using Open AI
✅Publish Automated Posts and Pages using AI Genie directly on Your website
✅50 DFY Websites Included Without Adding Any Images, Content Or Doing Anything Yourself
✅Integrated Chat GPT Bot gives Instant Answers on Your Website to Visitors
✅Just Enter the title, and your Content for Pages and Posts will be ready on your website
✅Automatically insert visually appealing images into posts based on keywords and titles.
✅Choose the temperature of the content and control its randomness.
✅Control the length of the content to be generated.
✅Never Worry About Paying Huge Money Monthly To Top Content Creation Platforms
✅100% Easy-to-Use, Newbie-Friendly Technology
✅30-Days Money-Back Guarantee
See My Other Reviews Article:
(1) TubeTrivia AI Review: https://sumonreview.com/tubetrivia-ai-review
(2) SocioWave Review: https://sumonreview.com/sociowave-review
(3) AI Partner & Profit Review: https://sumonreview.com/ai-partner-profit-review
(4) AI Ebook Suite Review: https://sumonreview.com/ai-ebook-suite-review
#AIGenieApp #AIGenieBonus #AIGenieBonuses #AIGenieDemo #AIGenieDownload #AIGenieLegit #AIGenieLiveDemo #AIGenieOTO #AIGeniePreview #AIGenieReview #AIGenieReviewandBonus #AIGenieScamorLegit #AIGenieSoftware #AIGenieUpgrades #AIGenieUpsells #HowDoesAlGenie #HowtoBuyAIGenie #HowtoMakeMoneywithAIGenie #MakeMoneyOnline #MakeMoneywithAIGenie
Atelier - Innover avec l’IA Générative et les graphes de connaissancesNeo4j
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Allez au-delà du battage médiatique autour de l’IA et découvrez des techniques pratiques pour utiliser l’IA de manière responsable à travers les données de votre organisation. Explorez comment utiliser les graphes de connaissances pour augmenter la précision, la transparence et la capacité d’explication dans les systèmes d’IA générative. Vous partirez avec une expérience pratique combinant les relations entre les données et les LLM pour apporter du contexte spécifique à votre domaine et améliorer votre raisonnement.
Amenez votre ordinateur portable et nous vous guiderons sur la mise en place de votre propre pile d’IA générative, en vous fournissant des exemples pratiques et codés pour démarrer en quelques minutes.
Graspan: A Big Data System for Big Code AnalysisAftab Hussain
We built a disk-based parallel graph system, Graspan, that uses a novel edge-pair centric computation model to compute dynamic transitive closures on very large program graphs.
We implement context-sensitive pointer/alias and dataflow analyses on Graspan. An evaluation of these analyses on large codebases such as Linux shows that their Graspan implementations scale to millions of lines of code and are much simpler than their original implementations.
These analyses were used to augment the existing checkers; these augmented checkers found 132 new NULL pointer bugs and 1308 unnecessary NULL tests in Linux 4.4.0-rc5, PostgreSQL 8.3.9, and Apache httpd 2.2.18.
- Accepted in ASPLOS ‘17, Xi’an, China.
- Featured in the tutorial, Systemized Program Analyses: A Big Data Perspective on Static Analysis Scalability, ASPLOS ‘17.
- Invited for presentation at SoCal PLS ‘16.
- Invited for poster presentation at PLDI SRC ‘16.
Check out the webinar slides to learn more about how XfilesPro transforms Salesforce document management by leveraging its world-class applications. For more details, please connect with sales@xfilespro.com
If you want to watch the on-demand webinar, please click here: https://www.xfilespro.com/webinars/salesforce-document-management-2-0-smarter-faster-better/
We describe the deployment and use of Globus Compute for remote computation. This content is aimed at researchers who wish to compute on remote resources using a unified programming interface, as well as system administrators who will deploy and operate Globus Compute services on their research computing infrastructure.
May Marketo Masterclass, London MUG May 22 2024.pdfAdele Miller
Can't make Adobe Summit in Vegas? No sweat because the EMEA Marketo Engage Champions are coming to London to share their Summit sessions, insights and more!
This is a MUG with a twist you don't want to miss.
Enhancing Research Orchestration Capabilities at ORNL.pdfGlobus
Cross-facility research orchestration comes with ever-changing constraints regarding the availability and suitability of various compute and data resources. In short, a flexible data and processing fabric is needed to enable the dynamic redirection of data and compute tasks throughout the lifecycle of an experiment. In this talk, we illustrate how we easily leveraged Globus services to instrument the ACE research testbed at the Oak Ridge Leadership Computing Facility with flexible data and task orchestration capabilities.
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisGlobus
JASMIN is the UK’s high-performance data analysis platform for environmental science, operated by STFC on behalf of the UK Natural Environment Research Council (NERC). In addition to its role in hosting the CEDA Archive (NERC’s long-term repository for climate, atmospheric science & Earth observation data in the UK), JASMIN provides a collaborative platform to a community of around 2,000 scientists in the UK and beyond, providing nearly 400 environmental science projects with working space, compute resources and tools to facilitate their work. High-performance data transfer into and out of JASMIN has always been a key feature, with many scientists bringing model outputs from supercomputers elsewhere in the UK, to analyse against observational or other model data in the CEDA Archive. A growing number of JASMIN users are now realising the benefits of using the Globus service to provide reliable and efficient data movement and other tasks in this and other contexts. Further use cases involve long-distance (intercontinental) transfers to and from JASMIN, and collecting results from a mobile atmospheric radar system, pushing data to JASMIN via a lightweight Globus deployment. We provide details of how Globus fits into our current infrastructure, our experience of the recent migration to GCSv5.4, and of our interest in developing use of the wider ecosystem of Globus services for the benefit of our user community.
Enterprise Resource Planning System includes various modules that reduce any business's workload. Additionally, it organizes the workflows, which drives towards enhancing productivity. Here are a detailed explanation of the ERP modules. Going through the points will help you understand how the software is changing the work dynamics.
To know more details here: https://blogs.nyggs.com/nyggs/enterprise-resource-planning-erp-system-modules/
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Crescat
Crescat is industry-trusted event management software, built by event professionals for event professionals. Founded in 2017, we have three key products tailored for the live event industry.
Crescat Event for concert promoters and event agencies. Crescat Venue for music venues, conference centers, wedding venues, concert halls and more. And Crescat Festival for festivals, conferences and complex events.
With a wide range of popular features such as event scheduling, shift management, volunteer and crew coordination, artist booking and much more, Crescat is designed for customisation and ease-of-use.
Over 125,000 events have been planned in Crescat and with hundreds of customers of all shapes and sizes, from boutique event agencies through to international concert promoters, Crescat is rigged for success. What's more, we highly value feedback from our users and we are constantly improving our software with updates, new features and improvements.
If you plan events, run a venue or produce festivals and you're looking for ways to make your life easier, then we have a solution for you. Try our software for free or schedule a no-obligation demo with one of our product specialists today at crescat.io
17. ARM Cortex-M3
32-bit 84MHz
CPU
SPI signals
shared by
LED/Sensor
Digital 33-37
Footpedals
DIN <-> USB
LED control
MIDI <-> Serial
18. Arduino Due and LinnStrument
• 32-bit core, 4 bytes wide operations within single CPU clock
• CPU Clock at 84Mhz
• 96 KBytes of SRAM
• 512 KBytes of Flash memory for code
• Digital I/O pins
• Serial Peripheral Interface (SPI) pins with Slave Select
19. Very simple Arduino program
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
20. Arduino code
• language based on C/C++
• concise reference with all language structures, values and functions
• Arduino IDE to get started
• the ‘setup’ function runs once, when the board starts up
• the ‘loop’ function runs at 100% CPU, over and over again
21. Only one execution thread
• what happens in the ‘loop’ function is all that’s happening
• if something takes too long, something else isn’t happening
• guerrilla coding tactics: powerful, short strikes and get out of there
• design your algorithms to be sub-dividable
• avoid dynamic memory allocation, it’s very slow
30. Easy LED functions
• Change the color and brightness of a single LED
void setLed(byte col, // Column of LED to be changed
byte row, // Row of LED to be changed
byte color, // Color of LED to be changed
byte brightness) // Brightness of LED (0, 1, 2 or 3)
• Light up a single LED with the default color and brightness
void lightLed(byte col, // Column of LED to be changed
byte row ) // Row of LED to be changed
• Clear a single LED
void clearLed(byte col, // Column of LED to be changed
byte row ) // Row of LED to be changed
31. Details of LED control
• LED control is done through SPI using pin 10, with mode 0, running at 21MHz
SPI.begin(10);
SPI.setDataMode(10, SPI_MODE0);
SPI.setClockDivider(10, 4); // 84MHz divided by 4
• Digital pin 37 is an output and connected to the LED driver chips
pinMode(37, OUTPUT);
• Write 32-bit data structure to SPI to control the LEDs, refreshed every 100μs
digitalWrite(37, HIGH); // enable the outputs of the LED driver chips
SPI.transfer(10, column, SPI_CONTINUE); // send column (left-shifted 2 bits + special bit 7)
SPI.transfer(10, blue, SPI_CONTINUE); // send blue byte
SPI.transfer(10, green, SPI_CONTINUE); // send green byte
SPI.transfer(10, red); // send red byte
digitalWrite(37, LOW); // disable the outputs of the LED driver chips
32. Easy sensor functions
• Send 16-bit word over SPI to touch sensor to set the analog switches
void selectSensorCell(byte col, // Column used by analog switches
byte row, // Row used
byte switch) // Switch to read X (0), Y (1) or Z (2)
• Read stable raw X value at the current col and row (returns 0-4095)
int readX()
• Read stable raw Y value at the current col and row (returns 0-127)
int readY()
• Read stable raw Z value at the current col and row (returns 0-127, 255 feather)
byte readZ()
33. Details of touch sensor control
• Touch sensor control is done through SPI using pin 4,
with mode 0, running at 21MHz
SPI.begin(4);
SPI.setDataMode(4, SPI_MODE0);
SPI.setClockDivider(4, 4); // 84MHz divided by 4
• Write 16-bit data to SPI to set analog switches (see ls_sensor.ino)
SPI.transfer(4, lsb, SPI_CONTINUE); // first byte of data structure
SPI.transfer(4, msb); // second byte of data structure
34. Read touch sensor data
• Touch sensor A/D input is using SPI through pin 52,
with mode 0, running at 21MHz
SPI.begin(52);
SPI.setDataMode(52, SPI_MODE0);
SPI.setClockDivider(52, 4); // 84MHz divided by 4
• Read sensor data
delayUsec(7); // wait for stable current after sensor
// control changes the analog switches
// delay different for each analog switch
byte msb = SPI.transfer(4, 0, SPI_CONTINUE); // first byte of sensor data
byte lsb = SPI.transfer(4, 0); // second byte of sensor data
int raw = (int(msb) << 8 | lsb) >> 2; // pack into int, shift from 16 to 14 bit
35. Reading the foot pedals
• Done in ls_switches.ino, modify this method to add custom behavior
void handleFootSwitchState(byte whichSwitch, boolean state)
• Digital pin 33 and 34, respectively for left and right foot switches, configured as pull-up
inputs (inverted inputs: high is off, low is on)
pinMode(33, INPUT_PULLUP);
pinMode(34, INPUT_PULLUP);
• Read the digital value of foot pedal states (typically every 20ms)
boolean leftPedalState = digitalRead(33);
boolean rightPedalState = digitalRead(34);
36. Details of MIDI / Serial - USB / DIN
• Setting digital switches changes the communication methods from the LinnStrument
to the outside world
• Digital pin 35 switches between Serial and MIDI
pinMode(35, OUTPUT);
digitalWrite(35, HIGH); // high switches to Serial input/output
digitalWrite(35, LOW); // low switches to MIDI input/output
• Digital pin 36 switches between USB and DIN connectors
pinMode(36, OUTPUT);
digitalWrite(36, HIGH); // high switches to USB input/output
digitalWrite(36, LOW); // low switches to DIN input/output
49. Core Files
• linnstrument-firmware.ino: global data structures, setup and main loop
• ls_displayModes.ino: illuminate LEDs for the different display modes
• ls_handleTouches.ino: driven by main loop, handles touch tracking
• ls_rtos.ino: primitive scheduler calling continuous tasks during delay
• ls_settings.ino: switch behavior from UI, store and recall settings
• ls_touchInfo.ino: encapsulate sensor data into touched cells
50. Low-level Files
• ls_calibration.ino: calibration procedure and data conversion
• ls_leds.ino: low-level communication with the LEDs
• ls_midi.ino: MIDI input, NRPN control, clock, output and queue
• ls_sensor.ino: low-level touch sensing with bias and curve
• ls_test.ino: debug functions and low-level reports
51. Auxilliary Features Files
• ls_arpeggiator.ino: arpeggiator logic, tied to internal MIDI clock
• ls_faders.ino: MIDI CC faders touch handling and data sending
• ls_font.ino: tiny, small, and big font display, including scrolling
• ls_lowRow.ino: continuous cell evaluation for low-row features, driven by
the main touch tracking
• ls_noteTouchMapping.ino: track MIDI notes to touched cells, mainly used
by arpeggiator
• ls_switches.ino: handles control switches and foot pedals
52. Support Header Files
• ls_bytebuffer.h: circular byte buffer with independent push and pop
locations, used by ls_midi.ino output queue
• ls_channelbucket.h: hands out MIDI channels from a bucket of
allowed channel numbers.
• ls_debug.h: debug macros and defines
• ls_midi.h: standard MIDI status codes, used by ls_midi.ino
54. Global variables
• byte sensorCol: the column number of the current sensor cell
• byte sensorRow: the row number of the current sensor cell
• byte sensorSplit: the split of the current sensor cell (0: left, 1: right)
• DisplayMode displayMode: the active display mode
(see DisplayMode enum in linnstrument-firmware.ino for the values)
55. Global functions
• TouchInfo &cell(): the last touch data for the current cell
• TouchInfo &cell(byte col, byte row): the last touch data for a cell
• FocusCell &focus(byte split, byte channel): the current cell that has
the focus for a particular split and channel (FocusCell is a structure
that just contains col and row)
57. Per-finger touch-tracking
• With a general purpose CPU, you’d model this as touch ‘sessions’
that are dynamically created and have a life of their own
• Too much memory churn for Arduino, too much book-keeping also
• Instead, have a touch state for each cell
• Transfer data between cells since we don’t support two fingers
touching the same cell
58. Inside ls_handleTouches.ino
void handleNewTouch(byte z) {
// ... snip ...
// check if the new touch could be an ongoing slide to the right
if (potentialSlideTransferCandidate(sensorCol-1)) {
// if the pressure gets higher than adjacent cell,
// the slide is transitioning over
if (isReadyForSlideTransfer(sensorCol-1)) {
transferFromSameRowCell(sensorCol-1);
handleXYZupdate(z);
}
// otherwise act as if this new touch never happened
else {
cellTouched(transferCell);
}
}
// similar for slide to the left
59. Check potential slide transfer
boolean potentialSlideTransferCandidate(int col) {
if (col < 1) return false;
if (sensorSplit != getSplitOf(col)) return false;
if (!isLowRow() && (!Split[sensorSplit].sendX ||
!isFocusedCell(col, sensorRow))) return false;
if (isLowRow() && !lowRowRequiresSlideTracking()) return false;
if (isStrummingSplit(sensorSplit)) return false;
// the sibling cell has an active touch
return cell(col, sensorRow).touched != untouchedCell &&
// either a release is pending to be performed, or
(cell(col, sensorRow).pendingReleaseCount ||
// both cells are touched simultaneously on the edges
abs(cell().calibratedX() - cell(col, sensorRow).calibratedX())
< TRANSFER_SLIDE_PROXIMITY);
}
60. Is the sibling cell ready for the transfer?
boolean isReadyForSlideTransfer(int col) {
// there's a pending release waiting
return cell(col, sensorRow).pendingReleaseCount ||
// the cell pressure is higher
cell().rawZ > cell(col, sensorRow).rawZ;
}
63. Perform the data transfer 3/3
// transfer the focus if this was the focused cell
byte channel = cell().channel;
if (channel != -1 && col == focus(sensorSplit, channel).col &&
sensorRow == focus(sensorSplit, channel).row) {
focus(sensorSplit, channel).col = sensorCol;
focus(sensorSplit, channel).row = sensorRow;
}
}
64. Finding the right MIDI channels
• Note-per-channel distributes up to 16 MIDI channels across notes
• Notes should reuse same channel as late as possible (release trails)
• Intuitively you’d scan all the active notes and determine which channel is
available for a new note, which is again too much overhead
• We use a bucket of available channels, channels bubble up or sink down
• A new note merely has to take the next channel from the top
• Fully encapsulated inside ls_channelbucket.h
65. Low-row functionalities
• Intuitively you’d detect a touch on low-row cells when it’s active
• Then evaluate state of every other cell and trigger behavior
• This is again too much overhead
• Instead keep track of low-row start/stop in a state machine
• Piggy-back when processing each cell in the main loop to evaluate
appropriate low-row behavior
67. Inside ls_lowRow.ino 1/2
void lowRowStart() {
switch (Split[sensorSplit].lowRowMode) {
case lowRowStrum:
lowRowState[sensorCol] = pressed;
break;
// ... snip, different for each low-row mode
}
}
void lowRowStop() {
switch (Split[sensorSplit].lowRowMode) {
case lowRowStrum:
lowRowState[sensorCol] = inactive;
break;
// ... snip, different for each low-row mode
}
}
68. Inside ls_lowRow.ino 2/2
void handleLowRowState(byte z) {
// this is a low-row cell
if (isLowRow()) {
// send out the continuous data for low-row cells
if (cell().velocity) {
// ... snip, different for each low-row mode
}
}
// this is a non low-row cell
else {
switch (Split[sensorSplit].lowRowMode) {
case lowRowStrum:
// uses lowRowState to correlate with column
handleLowRowStrum();
break;
// ... snip, other cases
}
}
}
69. Sending MIDI bytes
• MIDI was causing the LEDs to flicker
• Too much time was spent at once (need more guerrilla!)
• Created a MIDI queue to continuously send byte-by-byte from our
RTOS
• Arduino UART classes still caused problems: synchronous wait for
readiness when sending