SlideShare a Scribd company logo
1 of 58
Download to read offline
From Arduino To LinnStrument
Geert Bevin
Who am I?
• Geert Bevin, Twitter @gbevin
• Software Engineer (Greenpeace, Proximus, Walmart.com,
Terracotta, Eigenlabs, ZeroTurnaround, Roger Linn Design, Moog
Music, …)
• Musician, Composer, Arranger, Singer, Guitar, Chapman Stick,
Harpejji, LinnStrument, Synths, Gamer, Kung-Fu
• Many open-source projects including Gentoo Linux, OpenLaszlo,
RIFE, JUCE, SendMidi, ReceiveMidi, …
Electronic Musical Instrument
Creator
Software for Eigenharp
GECO for Leap Motion
LinnStrument firmware and tools
What is the LinnStrument?
Revolutionary Music Performance
Controller with 5D Note Expression
Open-source firmware and tools
DEMO
What’s inside LinnStrument?
Final prototype before production - actual units are slightly different
Translucent silicone sheet
Chassis + circuit boards
Front-panel
Final prototype before production - actual units are slightly different
Metal chassis with wooden sides
Sensor board
Final prototype before production - actual units are slightly different
LEDs board
Final prototype before production - actual units are slightly different
Connection between circuit boards
Final prototype before production - actual units are slightly different
Arduino Due’s
ARM chip Serial <-> USB MIDI Shield
The Arduino Due
ARM Cortex-M3
32-bit 84MHz
CPU
SPI signals

shared by
LED, Sensor
ADC
Digital 33-37
Footpedals

MIDI <-> Serial
DIN <-> USB
LED control
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 and data
• Digital I/O pins
• Serial Peripheral Interface (SPI) pins with Slave Select
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
}
Arduino code
• Language based on C/C++
• Concise reference with all language structures, values and functions
• Arduino IDE to get started
• ‘setup’ function runs once, when the board starts up
• ‘loop’ function runs at 100% CPU, over and over again
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
LinnStrument hardware access
through software
LED APIs
• Change the color and brightness of a single LED


void setLed(byte col, // Column (0-25 or 0-16 on LS128)
byte row, // Row (0-7)
byte color, // Color (12 options)
CellDisplay d, // Display type of LED (Off, On, Pulse, …)
byte layer) // Layer (Main, Played, User, Sequencer, …)
• Clear a single LED


void clearLed(byte col, // Column (0-25 or 0-16 on LS128)
byte row) // Row (0-7)
Details of LED control
• LED control through SPI pin 10, with mode 0, running at 21MHz


SPI.begin(10);
SPI.setDataMode(10, SPI_MODE0);
SPI.setClockDivider(10, 4); // 84MHz divided by 4

pinMode(37, OUTPUT); // pin 37 is output and connected to LED driver
• Write 32-bit data to SPI to control the LEDs, refreshed every 100μs


digitalWrite(37, HIGH); // enable the outputs of the LED driver
SPI.transfer(10, column, SPI_CONTINUE); // send column mask (special encoding)
SPI.transfer(10, blue, SPI_CONTINUE); // send blue byte mask for row
SPI.transfer(10, green, SPI_CONTINUE); // send green byte mask for row
SPI.transfer(10, red); // send red byte mask for row
digitalWrite(37, LOW); // disable the outputs of the LED driver
Sensor API
• 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 uncalibrated X, Y, Z values at the current col and row


short readX()


short readY()


short readZ()
Details of touch sensor control
• Touch sensor control through SPI 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

Custom encoding to select column, row and axis (X, Y, Z)


SPI.transfer(4, lsb, SPI_CONTINUE); // first byte of data structure
SPI.transfer(4, msb); // second byte of data structure
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 analog switch change
byte msb = SPI.transfer(52, 0, SPI_CONTINUE); // first byte of sensor data
byte lsb = SPI.transfer(52, 0); // second byte of sensor data

int raw = (int(msb) << 8 | lsb) >> 2; // pack to int, shift to 14 bit
MIDI/Serial - USB/DIN
• Digital switches change communication method to outside world,
handled by separate Arduino shield that redirects the data
• 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
That’s all the important
hardware stuff!
Concrete Firmware Examples
That might surprise Java programmers
Global Variables
Global Variables
• Master of the whole machine, global is good!
• Some examples of variables:



byte sensorCol; // column number of the current sensor

byte sensorRow; // row number of the current sensor

byte sensorSplit; // split of the current sensor

TouchInfo* sensorCell; // all touch data of current sensor

TouchInfo touchInfo[MAXCOLS][MAXROWS]; // grid with all touch data



struct Configuration config; // entry-point towards all the settings



DisplayMode displayMode; // the active display mode
No Threads, No Locks,

No Coordination
Poor-man’s RTOS 1/2
// Use instead of Arduino's delayMicroseconds()
void delayUsec(unsigned long delayTime) {
unsigned long start = micros();
unsigned long now = start;
while (calcTimeDelta(now, start) < delayTime) {
performContinuousTasks(now);
now = micros();
}
}
Poor-man’s RTOS 2/2
inline void performContinuousTasks(unsigned long nowMicros) {
boolean ledsRefreshed = false;
static boolean continuousRefreshLeds = false;
if (!continuousRefreshLeds) {
continuousRefreshLeds = true;
ledsRefreshed = checkRefreshLedColumn(nowMicros);
continuousRefreshLeds = false;
}
if (ledsRefreshed) {
// other continuous tasks : foot switches, animation, clock, MIDI, ...
}
}



inline boolean checkRefreshLedColumn(unsigned long now) {
if (calcTimeDelta(now, prevLedTimerCount) > 333) {
refreshLedColumn(now);
prevLedTimerCount = now;
return true;
}
return false;
}
Fast main loop with panel scanning
void loop() {
TouchState previous = sensorCell->touched;
if (previous != touchedCell &&
previous != ignoredCell &&
sensorCell->isMeaningfulTouch()) { // touched now but not before
handleNewTouch();
}
else if (previous == touchedCell && // touched now and touched before
sensorCell->isActiveTouch()) {
handleXYZupdate();
}
else if (previous != untouchedCell && // not touched now but touched before
!sensorCell->isActiveTouch()) {
handleTouchRelease();
}
performContinuousTasks();
nextSensorCell();
}
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 and bookkeeping
• Instead, have a touch state for each cell
• Transfer data between cells since we don’t support two fingers
touching the same cell
Check if a new touch is actually a slide
boolean handleNewTouch() {
// ... snip ...
  cellTouched(touchedCell);
// 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);
// process the 3D touch data
handleXYZupdate();
}
// otherwise act as if this new touch never happened
else {
cellTouched(transferCell);
}
}
// similar for slide to the left
Check potential slide transfer
boolean potentialSlideTransferCandidate(int col) {
// ... snip ...
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;
// ... snip ...
 
// 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);
}
Is sibling cell ready for slide?
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;
}
Perform the data transfer
void transferFromSameRowCell(byte col) {
// ... snip ...
cell().lastTouch = cell(col, sensorRow).lastTouch;
cell().initialX = cell(col, sensorRow).initialX;
cell().initialColumn = cell(col, sensorRow).initialColumn;
cell().lastMovedX = cell(col, sensorRow).lastMovedX;
cell().fxdRateX = cell(col, sensorRow).fxdRateX;
cell().fxdRateCountX = cell(col, sensorRow).fxdRateCountX;
// ... snip ...
cell().initialY = cell(col, sensorRow).initialY;
cell().note = cell(col, sensorRow).note;
cell().channel = cell(col, sensorRow).channel;
cell().fxdPrevPressure = cell(col, sensorRow).fxdPrevPressure;
cell().fxdPrevTimbre = cell(col, sensorRow).fxdPrevTimbre;
cell().velocity = cell(col, sensorRow).velocity;
cell().vcount = cell(col, sensorRow).vcount;
// ... snip ...
} 
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
Queuing of messages
ByteBuffer<4096> midiOutQueue;
// called for each MIDI message that is sent
void queueMidiMessage(MIDIStatus type, byte param1, byte param2, byte channel) {
param1 &= 0x7F; param2 &= 0x7F;
midiOutQueue.push((byte)type | (channel & 0x0F));
midiOutQueue.push(param1);
if (type != MIDIProgramChange && type != MIDIChannelPressure) {
midiOutQueue.push(param2);
}
}
// continuously called by our RTOS
void handlePendingMidi() {
if (!midiOutQueue.empty()) {
if (Serial.write(midiOutQueue.peek(), false) > 0) { // patched UART method
midiOutQueue.pop();
}
}
}
Patched UARTClass
--- UARTClass.cpp 2014-11-10 14:55:10.000000000 +0100
+++ UARTClass.cpp 2014-10-10 19:39:43.000000000 +0200
@@ -109,9 +109,15 @@
 
size_t UARTClass::write( const uint8_t uc_data )
{
+ return write(uc_data, true);
+}
+
+size_t UARTClass::write( const uint8_t uc_data, const bool wait )
+{
// Check if the transmitter is ready
- while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
- ;
+ while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) {
+ if ( !wait ) return 0;
+ }
 
// Send character
_pUart->UART_THR = uc_data;
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
Hooks into the touch functions
boolean handleXYZupdate() {
// ... snip ...
  if (newVelocity) {
if (isLowRow()) {
lowRowStart();
}
}
// ... snip ...
if (!newVelocity || !isLowRow()) {
handleLowRowState(newVelocity,
valueX,
valueY,
valueZ);
}
// ... snip ...
}
void handleTouchRelease() {
// ... snip ...
if (isLowRow()) {
lowRowStop();
}
// ... snip ...
}
Low-row functions 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
}
}
Low-row functions 2/2
void handleLowRowState(boolean newVelocity, short pitchBend,
short timbre, byte pressure) {
// this is a low-row cell
if (isLowRow()) {
// ... snip, send out the continuous data for low-row cells
}
// 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
}
}
}
Precise velocity detection
• Complete panel scan takes 4ms
• Strike velocity calculation needs much more detailed samples
• Full control over execution allows for temporary rapid successive
pressure measurements at initial touch
• Short-circuit in main-loop to re-process the cell at initial touch
• Velocity state machine in touch handling functions
Main loop short-circuit
boolean canShortCircuit = false;
if (previous != touchedCell && previous != ignoredCell &&
sensorCell->isMeaningfulTouch()) { // touched now but not before
canShortCircuit = handleNewTouch();
}
else if (previous == touchedCell && // touched now and touched before
sensorCell->isActiveTouch()) {
canShortCircuit = handleXYZupdate();
}
else if (previous != untouchedCell && // not touched now but touched before
!sensorCell->isActiveTouch()) {
canShortCircuit = handleTouchRelease();
}
if (canShortCircuit) {
sensorCell->shouldRefreshData(); // immediately process this cell again
}
else {
performContinuousTasks();
nextSensorCell();
}
Reduce power consumption
• LinnStrument is usually bus-powered over USB
• Would be awesome if it could be bus-powered from iPhone or iPad
• Power consumption too high, iOS shuts it off:

“The attached accessory uses too much power”
• Code changes can make the CPU relax, update LEDs less
frequently, and hence reduce the power consumption
• Yes, code actually controls electricity!!! :-)
Short main loop delay
void loop() {
// ... snip ... : touch handling routines
// When operating in low power mode,
// slow down the sensor scan rate in order to consume less power
// This introduces an overall additional average latency of 2.5ms
if (Device.operatingLowPower) {
delayUsec(25);
}
performContinuousTasks();
nextSensorCell();
}
Only light LEDs half of the time
void refreshLedColumn(unsigned long now) {
static byte displayInterval[MAXCOLS][MAXROWS];
// ... snip ...
for (byte rowCount = 0; rowCount < NUMROWS; ++rowCount) {
if (++displayInterval[actualCol][rowCount] >= 12) {
displayInterval[actualCol][rowCount] = 0;
}
// ... snip ...
if (Device.operatingLowPower) {
if (displayInterval[actualCol][rowCount] % 2 != 0) {
cellDisplay = cellOff;
}
}
// ... snip ...
}
}
More information at
http://www.rogerlinndesign.com
@gbevin

More Related Content

What's hot

Porte à puce - Smart Safety Door based on Arduino UNO R3
Porte à puce - Smart Safety Door based on Arduino UNO R3Porte à puce - Smart Safety Door based on Arduino UNO R3
Porte à puce - Smart Safety Door based on Arduino UNO R3Meifani Sumadijaya
 
ARDUINO AND ITS PIN CONFIGURATION
 ARDUINO AND ITS PIN  CONFIGURATION ARDUINO AND ITS PIN  CONFIGURATION
ARDUINO AND ITS PIN CONFIGURATIONsoma saikiran
 
How to measure frequency and duty cycle using arduino
How to measure frequency and duty cycle using  arduinoHow to measure frequency and duty cycle using  arduino
How to measure frequency and duty cycle using arduinoSagar Srivastav
 
Arduino slides
Arduino slidesArduino slides
Arduino slidessdcharle
 
Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors B...
Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors  B...Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors  B...
Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors B...Faqih Fadhila Ardiansyah
 
Basics of open source embedded development board (
Basics of open source embedded development board (Basics of open source embedded development board (
Basics of open source embedded development board (Dhruwank Vankawala
 
Introduction to arduino ppt main
Introduction to  arduino ppt mainIntroduction to  arduino ppt main
Introduction to arduino ppt maineddy royappa
 
Getting startedwitharduino ch04
Getting startedwitharduino ch04Getting startedwitharduino ch04
Getting startedwitharduino ch04Anil Yadav
 
IOTC08 The Arduino Platform
IOTC08 The Arduino PlatformIOTC08 The Arduino Platform
IOTC08 The Arduino PlatformEoin Brazil
 
Arduino spooky projects_class3
Arduino spooky projects_class3Arduino spooky projects_class3
Arduino spooky projects_class3Anil Yadav
 

What's hot (19)

Porte à puce - Smart Safety Door based on Arduino UNO R3
Porte à puce - Smart Safety Door based on Arduino UNO R3Porte à puce - Smart Safety Door based on Arduino UNO R3
Porte à puce - Smart Safety Door based on Arduino UNO R3
 
ARDUINO AND ITS PIN CONFIGURATION
 ARDUINO AND ITS PIN  CONFIGURATION ARDUINO AND ITS PIN  CONFIGURATION
ARDUINO AND ITS PIN CONFIGURATION
 
Arduino uno
Arduino unoArduino uno
Arduino uno
 
Lab2ppt
Lab2pptLab2ppt
Lab2ppt
 
How to measure frequency and duty cycle using arduino
How to measure frequency and duty cycle using  arduinoHow to measure frequency and duty cycle using  arduino
How to measure frequency and duty cycle using arduino
 
Porte à puce
Porte à pucePorte à puce
Porte à puce
 
Introduction to Arduino
Introduction to ArduinoIntroduction to Arduino
Introduction to Arduino
 
Arduino slides
Arduino slidesArduino slides
Arduino slides
 
Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors B...
Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors  B...Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors  B...
Smart Safety Door with Servo Motors as Actuators, Passcode and DHT Sensors B...
 
Basics of open source embedded development board (
Basics of open source embedded development board (Basics of open source embedded development board (
Basics of open source embedded development board (
 
Introduction to arduino ppt main
Introduction to  arduino ppt mainIntroduction to  arduino ppt main
Introduction to arduino ppt main
 
Getting startedwitharduino ch04
Getting startedwitharduino ch04Getting startedwitharduino ch04
Getting startedwitharduino ch04
 
Arduino course
Arduino courseArduino course
Arduino course
 
Arduino workshop sensors
Arduino workshop sensorsArduino workshop sensors
Arduino workshop sensors
 
IOTC08 The Arduino Platform
IOTC08 The Arduino PlatformIOTC08 The Arduino Platform
IOTC08 The Arduino Platform
 
Arduino spooky projects_class3
Arduino spooky projects_class3Arduino spooky projects_class3
Arduino spooky projects_class3
 
Introduction to Arduino
Introduction to ArduinoIntroduction to Arduino
Introduction to Arduino
 
Introduction to Arduino
Introduction to ArduinoIntroduction to Arduino
Introduction to Arduino
 
Ardui no
Ardui no Ardui no
Ardui no
 

Similar to From Arduino to LinnStrument

arduino introduction for vocational students
arduino introduction for vocational studentsarduino introduction for vocational students
arduino introduction for vocational studentsanggalima5
 
Arduino Slides With Neopixels
Arduino Slides With NeopixelsArduino Slides With Neopixels
Arduino Slides With Neopixelssdcharle
 
Introduction to Arduino Hardware and Programming
Introduction to Arduino Hardware and ProgrammingIntroduction to Arduino Hardware and Programming
Introduction to Arduino Hardware and ProgrammingEmmanuel Obot
 
Arduino and Internet of Thinks: ShareIT TM: march 2010, TM
Arduino and Internet of Thinks: ShareIT TM: march 2010, TMArduino and Internet of Thinks: ShareIT TM: march 2010, TM
Arduino and Internet of Thinks: ShareIT TM: march 2010, TMAlexandru IOVANOVICI
 
arduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdfarduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdfssusere5db05
 
teststststststLecture_3_2022_Arduino.pptx
teststststststLecture_3_2022_Arduino.pptxteststststststLecture_3_2022_Arduino.pptx
teststststststLecture_3_2022_Arduino.pptxethannguyen1618
 
INT4073 L07(Sensors and AcutTORS).pdf
INT4073 L07(Sensors and AcutTORS).pdfINT4073 L07(Sensors and AcutTORS).pdf
INT4073 L07(Sensors and AcutTORS).pdfMSingh88
 
Microcontrollers (Rex St. John)
Microcontrollers (Rex St. John)Microcontrollers (Rex St. John)
Microcontrollers (Rex St. John)Future Insights
 
Multi Sensory Communication 1/2
Multi Sensory Communication 1/2Multi Sensory Communication 1/2
Multi Sensory Communication 1/2Satoru Tokuhisa
 
Arduino by yogesh t s'
Arduino by yogesh t s'Arduino by yogesh t s'
Arduino by yogesh t s'tsyogesh46
 
Multi Sensory Communication 2/2
Multi Sensory Communication 2/2Multi Sensory Communication 2/2
Multi Sensory Communication 2/2Satoru Tokuhisa
 
Automatic room light controller with visible counter
Automatic room light controller with visible counterAutomatic room light controller with visible counter
Automatic room light controller with visible counterMafaz Ahmed
 

Similar to From Arduino to LinnStrument (20)

arduino introduction for vocational students
arduino introduction for vocational studentsarduino introduction for vocational students
arduino introduction for vocational students
 
Arduino Slides With Neopixels
Arduino Slides With NeopixelsArduino Slides With Neopixels
Arduino Slides With Neopixels
 
Introduction to Arduino Hardware and Programming
Introduction to Arduino Hardware and ProgrammingIntroduction to Arduino Hardware and Programming
Introduction to Arduino Hardware and Programming
 
Arduino and Internet of Thinks: ShareIT TM: march 2010, TM
Arduino and Internet of Thinks: ShareIT TM: march 2010, TMArduino and Internet of Thinks: ShareIT TM: march 2010, TM
Arduino and Internet of Thinks: ShareIT TM: march 2010, TM
 
arduino4.ppt
arduino4.pptarduino4.ppt
arduino4.ppt
 
arduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdfarduinocourse-180308074529 (1).pdf
arduinocourse-180308074529 (1).pdf
 
teststststststLecture_3_2022_Arduino.pptx
teststststststLecture_3_2022_Arduino.pptxteststststststLecture_3_2022_Arduino.pptx
teststststststLecture_3_2022_Arduino.pptx
 
arduinoedit.pptx
arduinoedit.pptxarduinoedit.pptx
arduinoedit.pptx
 
INT4073 L07(Sensors and AcutTORS).pdf
INT4073 L07(Sensors and AcutTORS).pdfINT4073 L07(Sensors and AcutTORS).pdf
INT4073 L07(Sensors and AcutTORS).pdf
 
Audible Objects
Audible ObjectsAudible Objects
Audible Objects
 
Microcontrollers (Rex St. John)
Microcontrollers (Rex St. John)Microcontrollers (Rex St. John)
Microcontrollers (Rex St. John)
 
Arduino Programming Basic
Arduino Programming BasicArduino Programming Basic
Arduino Programming Basic
 
Multi Sensory Communication 1/2
Multi Sensory Communication 1/2Multi Sensory Communication 1/2
Multi Sensory Communication 1/2
 
Iot Workshop NITT 2015
Iot Workshop NITT 2015Iot Workshop NITT 2015
Iot Workshop NITT 2015
 
Arduino: Arduino starter kit
Arduino: Arduino starter kitArduino: Arduino starter kit
Arduino: Arduino starter kit
 
Arduino by yogesh t s'
Arduino by yogesh t s'Arduino by yogesh t s'
Arduino by yogesh t s'
 
Multi Sensory Communication 2/2
Multi Sensory Communication 2/2Multi Sensory Communication 2/2
Multi Sensory Communication 2/2
 
Lecture1
Lecture1Lecture1
Lecture1
 
Arduino
ArduinoArduino
Arduino
 
Automatic room light controller with visible counter
Automatic room light controller with visible counterAutomatic room light controller with visible counter
Automatic room light controller with visible counter
 

Recently uploaded

Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...OnePlan Solutions
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdfAndrey Devyatkin
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITmanoharjgpsolutions
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesKrzysztofKkol1
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfkalichargn70th171
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingOpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingShane Coughlan
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesVictoriaMetrics
 
Copilot para Microsoft 365 y Power Platform Copilot
Copilot para Microsoft 365 y Power Platform CopilotCopilot para Microsoft 365 y Power Platform Copilot
Copilot para Microsoft 365 y Power Platform CopilotEdgard Alejos
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfmaor17
 

Recently uploaded (20)

Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
Tech Tuesday Slides - Introduction to Project Management with OnePlan's Work ...
 
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
2024-04-09 - From Complexity to Clarity - AWS Summit AMS.pdf
 
Best Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh ITBest Angular 17 Classroom & Online training - Naresh IT
Best Angular 17 Classroom & Online training - Naresh IT
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilitiesAmazon Bedrock in Action - presentation of the Bedrock's capabilities
Amazon Bedrock in Action - presentation of the Bedrock's capabilities
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full RecordingOpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
OpenChain Education Work Group Monthly Meeting - 2024-04-10 - Full Recording
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
What’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 UpdatesWhat’s New in VictoriaMetrics: Q1 2024 Updates
What’s New in VictoriaMetrics: Q1 2024 Updates
 
Copilot para Microsoft 365 y Power Platform Copilot
Copilot para Microsoft 365 y Power Platform CopilotCopilot para Microsoft 365 y Power Platform Copilot
Copilot para Microsoft 365 y Power Platform Copilot
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdf
 

From Arduino to LinnStrument

  • 1. From Arduino To LinnStrument Geert Bevin
  • 2. Who am I? • Geert Bevin, Twitter @gbevin • Software Engineer (Greenpeace, Proximus, Walmart.com, Terracotta, Eigenlabs, ZeroTurnaround, Roger Linn Design, Moog Music, …) • Musician, Composer, Arranger, Singer, Guitar, Chapman Stick, Harpejji, LinnStrument, Synths, Gamer, Kung-Fu • Many open-source projects including Gentoo Linux, OpenLaszlo, RIFE, JUCE, SendMidi, ReceiveMidi, …
  • 5. GECO for Leap Motion
  • 7. What is the LinnStrument?
  • 10. DEMO
  • 12. Final prototype before production - actual units are slightly different Translucent silicone sheet Chassis + circuit boards Front-panel
  • 13. Final prototype before production - actual units are slightly different Metal chassis with wooden sides Sensor board
  • 14. Final prototype before production - actual units are slightly different LEDs board
  • 15. Final prototype before production - actual units are slightly different Connection between circuit boards
  • 16. Final prototype before production - actual units are slightly different Arduino Due’s ARM chip Serial <-> USB MIDI Shield
  • 18. ARM Cortex-M3 32-bit 84MHz CPU SPI signals
 shared by LED, Sensor ADC Digital 33-37 Footpedals
 MIDI <-> Serial DIN <-> USB LED control
  • 19. 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 and data • Digital I/O pins • Serial Peripheral Interface (SPI) pins with Slave Select
  • 20. 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 }
  • 21. Arduino code • Language based on C/C++ • Concise reference with all language structures, values and functions • Arduino IDE to get started • ‘setup’ function runs once, when the board starts up • ‘loop’ function runs at 100% CPU, over and over again
  • 22. 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
  • 24. LED APIs • Change the color and brightness of a single LED 
 void setLed(byte col, // Column (0-25 or 0-16 on LS128) byte row, // Row (0-7) byte color, // Color (12 options) CellDisplay d, // Display type of LED (Off, On, Pulse, …) byte layer) // Layer (Main, Played, User, Sequencer, …) • Clear a single LED 
 void clearLed(byte col, // Column (0-25 or 0-16 on LS128) byte row) // Row (0-7)
  • 25. Details of LED control • LED control through SPI pin 10, with mode 0, running at 21MHz 
 SPI.begin(10); SPI.setDataMode(10, SPI_MODE0); SPI.setClockDivider(10, 4); // 84MHz divided by 4
 pinMode(37, OUTPUT); // pin 37 is output and connected to LED driver • Write 32-bit data to SPI to control the LEDs, refreshed every 100μs 
 digitalWrite(37, HIGH); // enable the outputs of the LED driver SPI.transfer(10, column, SPI_CONTINUE); // send column mask (special encoding) SPI.transfer(10, blue, SPI_CONTINUE); // send blue byte mask for row SPI.transfer(10, green, SPI_CONTINUE); // send green byte mask for row SPI.transfer(10, red); // send red byte mask for row digitalWrite(37, LOW); // disable the outputs of the LED driver
  • 26. Sensor API • 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 uncalibrated X, Y, Z values at the current col and row 
 short readX() 
 short readY() 
 short readZ()
  • 27. Details of touch sensor control • Touch sensor control through SPI 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
 Custom encoding to select column, row and axis (X, Y, Z) 
 SPI.transfer(4, lsb, SPI_CONTINUE); // first byte of data structure SPI.transfer(4, msb); // second byte of data structure
  • 28. 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 analog switch change byte msb = SPI.transfer(52, 0, SPI_CONTINUE); // first byte of sensor data byte lsb = SPI.transfer(52, 0); // second byte of sensor data
 int raw = (int(msb) << 8 | lsb) >> 2; // pack to int, shift to 14 bit
  • 29. MIDI/Serial - USB/DIN • Digital switches change communication method to outside world, handled by separate Arduino shield that redirects the data • 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
  • 30. That’s all the important hardware stuff!
  • 31. Concrete Firmware Examples That might surprise Java programmers
  • 33. Global Variables • Master of the whole machine, global is good! • Some examples of variables:
 
 byte sensorCol; // column number of the current sensor
 byte sensorRow; // row number of the current sensor
 byte sensorSplit; // split of the current sensor
 TouchInfo* sensorCell; // all touch data of current sensor
 TouchInfo touchInfo[MAXCOLS][MAXROWS]; // grid with all touch data
 
 struct Configuration config; // entry-point towards all the settings
 
 DisplayMode displayMode; // the active display mode
  • 34. No Threads, No Locks,
 No Coordination
  • 35. Poor-man’s RTOS 1/2 // Use instead of Arduino's delayMicroseconds() void delayUsec(unsigned long delayTime) { unsigned long start = micros(); unsigned long now = start; while (calcTimeDelta(now, start) < delayTime) { performContinuousTasks(now); now = micros(); } }
  • 36. Poor-man’s RTOS 2/2 inline void performContinuousTasks(unsigned long nowMicros) { boolean ledsRefreshed = false; static boolean continuousRefreshLeds = false; if (!continuousRefreshLeds) { continuousRefreshLeds = true; ledsRefreshed = checkRefreshLedColumn(nowMicros); continuousRefreshLeds = false; } if (ledsRefreshed) { // other continuous tasks : foot switches, animation, clock, MIDI, ... } }
 
 inline boolean checkRefreshLedColumn(unsigned long now) { if (calcTimeDelta(now, prevLedTimerCount) > 333) { refreshLedColumn(now); prevLedTimerCount = now; return true; } return false; }
  • 37. Fast main loop with panel scanning void loop() { TouchState previous = sensorCell->touched; if (previous != touchedCell && previous != ignoredCell && sensorCell->isMeaningfulTouch()) { // touched now but not before handleNewTouch(); } else if (previous == touchedCell && // touched now and touched before sensorCell->isActiveTouch()) { handleXYZupdate(); } else if (previous != untouchedCell && // not touched now but touched before !sensorCell->isActiveTouch()) { handleTouchRelease(); } performContinuousTasks(); nextSensorCell(); }
  • 38. 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 and bookkeeping • Instead, have a touch state for each cell • Transfer data between cells since we don’t support two fingers touching the same cell
  • 39. Check if a new touch is actually a slide boolean handleNewTouch() { // ... snip ...   cellTouched(touchedCell); // 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); // process the 3D touch data handleXYZupdate(); } // otherwise act as if this new touch never happened else { cellTouched(transferCell); } } // similar for slide to the left
  • 40. Check potential slide transfer boolean potentialSlideTransferCandidate(int col) { // ... snip ... 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; // ... snip ...   // 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); }
  • 41. Is sibling cell ready for slide? 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; }
  • 42. Perform the data transfer void transferFromSameRowCell(byte col) { // ... snip ... cell().lastTouch = cell(col, sensorRow).lastTouch; cell().initialX = cell(col, sensorRow).initialX; cell().initialColumn = cell(col, sensorRow).initialColumn; cell().lastMovedX = cell(col, sensorRow).lastMovedX; cell().fxdRateX = cell(col, sensorRow).fxdRateX; cell().fxdRateCountX = cell(col, sensorRow).fxdRateCountX; // ... snip ... cell().initialY = cell(col, sensorRow).initialY; cell().note = cell(col, sensorRow).note; cell().channel = cell(col, sensorRow).channel; cell().fxdPrevPressure = cell(col, sensorRow).fxdPrevPressure; cell().fxdPrevTimbre = cell(col, sensorRow).fxdPrevTimbre; cell().velocity = cell(col, sensorRow).velocity; cell().vcount = cell(col, sensorRow).vcount; // ... snip ... } 
  • 43. 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
  • 44. Queuing of messages ByteBuffer<4096> midiOutQueue; // called for each MIDI message that is sent void queueMidiMessage(MIDIStatus type, byte param1, byte param2, byte channel) { param1 &= 0x7F; param2 &= 0x7F; midiOutQueue.push((byte)type | (channel & 0x0F)); midiOutQueue.push(param1); if (type != MIDIProgramChange && type != MIDIChannelPressure) { midiOutQueue.push(param2); } } // continuously called by our RTOS void handlePendingMidi() { if (!midiOutQueue.empty()) { if (Serial.write(midiOutQueue.peek(), false) > 0) { // patched UART method midiOutQueue.pop(); } } }
  • 45. Patched UARTClass --- UARTClass.cpp 2014-11-10 14:55:10.000000000 +0100 +++ UARTClass.cpp 2014-10-10 19:39:43.000000000 +0200 @@ -109,9 +109,15 @@   size_t UARTClass::write( const uint8_t uc_data ) { + return write(uc_data, true); +} + +size_t UARTClass::write( const uint8_t uc_data, const bool wait ) +{ // Check if the transmitter is ready - while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) - ; + while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) { + if ( !wait ) return 0; + }   // Send character _pUart->UART_THR = uc_data;
  • 46. 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
  • 47. Hooks into the touch functions boolean handleXYZupdate() { // ... snip ...   if (newVelocity) { if (isLowRow()) { lowRowStart(); } } // ... snip ... if (!newVelocity || !isLowRow()) { handleLowRowState(newVelocity, valueX, valueY, valueZ); } // ... snip ... } void handleTouchRelease() { // ... snip ... if (isLowRow()) { lowRowStop(); } // ... snip ... }
  • 48. Low-row functions 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 } }
  • 49. Low-row functions 2/2 void handleLowRowState(boolean newVelocity, short pitchBend, short timbre, byte pressure) { // this is a low-row cell if (isLowRow()) { // ... snip, send out the continuous data for low-row cells } // 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 } } }
  • 50. Precise velocity detection • Complete panel scan takes 4ms • Strike velocity calculation needs much more detailed samples • Full control over execution allows for temporary rapid successive pressure measurements at initial touch • Short-circuit in main-loop to re-process the cell at initial touch • Velocity state machine in touch handling functions
  • 51. Main loop short-circuit boolean canShortCircuit = false; if (previous != touchedCell && previous != ignoredCell && sensorCell->isMeaningfulTouch()) { // touched now but not before canShortCircuit = handleNewTouch(); } else if (previous == touchedCell && // touched now and touched before sensorCell->isActiveTouch()) { canShortCircuit = handleXYZupdate(); } else if (previous != untouchedCell && // not touched now but touched before !sensorCell->isActiveTouch()) { canShortCircuit = handleTouchRelease(); } if (canShortCircuit) { sensorCell->shouldRefreshData(); // immediately process this cell again } else { performContinuousTasks(); nextSensorCell(); }
  • 52. Reduce power consumption • LinnStrument is usually bus-powered over USB • Would be awesome if it could be bus-powered from iPhone or iPad • Power consumption too high, iOS shuts it off:
 “The attached accessory uses too much power” • Code changes can make the CPU relax, update LEDs less frequently, and hence reduce the power consumption • Yes, code actually controls electricity!!! :-)
  • 53. Short main loop delay void loop() { // ... snip ... : touch handling routines // When operating in low power mode, // slow down the sensor scan rate in order to consume less power // This introduces an overall additional average latency of 2.5ms if (Device.operatingLowPower) { delayUsec(25); } performContinuousTasks(); nextSensorCell(); }
  • 54. Only light LEDs half of the time void refreshLedColumn(unsigned long now) { static byte displayInterval[MAXCOLS][MAXROWS]; // ... snip ... for (byte rowCount = 0; rowCount < NUMROWS; ++rowCount) { if (++displayInterval[actualCol][rowCount] >= 12) { displayInterval[actualCol][rowCount] = 0; } // ... snip ... if (Device.operatingLowPower) { if (displayInterval[actualCol][rowCount] % 2 != 0) { cellDisplay = cellOff; } } // ... snip ... } }
  • 55.
  • 56.
  • 57.