Teensy-LC Beta Testing

Question: are you going to add an SPI1 object that makes use of your new class,

Yes

Re: LC Wire slave and no interrupt on 18

The Wire library for slave appears to use attachInterrupt for pin 18 (SDA),

Indeed, slave mode isn't going to work on Teensy-LC.

Maybe another workaround can be found. It might involve a simple busy loop in the interrupt routine, since we don't get interrupts on those pins.
 

I downloaded your stuff and added the defines to the SPI.h and SPI.cpp
Code:
#if defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
extern SPI1Class SPI1;
#endif

But the code fails to build as SPI1 is defined in the low level: #define SPI1 (*(KINETISL_SPI_t *)0x40077000)

My current workaround is to:
Code:
#if defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
#ifdef SPI1
#undef SPI1
#endif
extern SPI1Class SPI1;
#endif

Stuff builds again. Now will play with using it.
 
Indeed, slave mode isn't going to work on Teensy-LC.

Maybe another workaround can be found. It might involve a simple busy loop in the interrupt routine, since we don't get interrupts on those pins.

earlier in this thread, nox771 noted that LC ref. manual for I2Cx_FLT has some additional bits for STOP management. maybe those will be useful ...
 
My LC arrived in the post today. Thanks, PJRC!

I get the usual "new board" issues with Windows looking for device drivers. I'm wondering if it is worthwhile adding to the getting started instructions something for Windows users, who might be troubled by messages like "upload failed" in Teensy loader or (a new one to me)
Sketch uses 11,888 bytes (18%) of program storage space. Maximum is 63,488 bytes.
Global variables use 2,656 bytes (32%) of dynamic memory, leaving 5,536 bytes for local variables. Maximum is 8,192 bytes.
Teensy Loader is currently busy with another operation (r). Please try again in a few seconds, or restart Teensy Loader.
These occur when you try to upload a sketch that uses a USB type you haven't used before. Windows tries to find drivers, and this takes a while because it insists on going online and searching Windows Update for the latest drivers. You can either wait for this to time out, or click to show details and cancel the windows update search. meanwhile Teensy loader is finding the board is not responding, and gives an error.

All of these things are harmless and temporary (they will occur once per board type, per USB port and per USB type (MIDI, Keyboard, etc) but could be worrying for new users. Repeating the upload after drivers are installed always works.
 
Sounds great, I will try your version of the fixes out later. Functionally should not make difference in what I did.
I pushed an updated version of the Adafruit_ST7735 driver up that if you pass in the SCLK/MOSI of any of the hardware pin combinations for SPI0 or SPI1 it sets up to use it.
I tried:
//#define TFT_SCLK 13 // set these to be whatever pins you like!
//#define TFT_MOSI 11 // set these to be whatever pins you like!
// Teency Alternate
//#define TFT_SCLK 14 // set these to be whatever pins you like!
//#define TFT_MOSI 7 // set these to be whatever pins you like!
// Teency LC SPI1
//#define TFT_SCLK 20 // set these to be whatever pins you like!
//#define TFT_MOSI 0 // set these to be whatever pins you like!

#define TFT_SCLK 20 // set these to be whatever pins you like!
#define TFT_MOSI 21 // set these to be whatever pins you like!
Again changes pushed up to my branch of github... Should I also try on ILI9341/STMPE610?

Kurt
 
My LC arrived in the post today. Thanks, PJRC!
These occur when you try to upload a sketch that uses a USB type you haven't used before. Windows tries to find drivers, and this takes a while because it insists on going online and searching Windows Update for the latest drivers. You can either wait for this to time out, or click to show details and cancel the windows update search.

I find it happens periodically as well. every 10 or so downloads windows decides it needs a new driver.

This is a windows issue though.

The other issues i had seem to have vanished completely now, no rebooting required, much more stable. I can code all night and do 10 or 20 downloads without rebooting.

I'm going to post my current code in case it is helpful to Paul to review against my previous code i posted.

My gut feeling is windows is being rubbish, and this can sometimes expose some weaknesses in teensy loader's process somewhere. It certainly seems to have gone away, and i haven't updated teensyduino since I last had the problems.

Code:
#include <Wire.h> // i2C library for comms with Trellis modules.
#include "Adafruit_Trellis.h" // Trellis library
#include <Metro.h> // Interrupt free timer library for querying and midi note sending.
#include <EEPROM.h> // save settings to the eeprom
#include <Bounce.h>
#include <Adafruit_NeoPixel.h>

Bounce pushbutton = Bounce(1, 10);  // 10 ms debounce

elapsedMicros seqTimer;

#define NEOPIN 17

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, NEOPIN, NEO_GRB + NEO_KHZ800);
byte pixRed = 255;
byte pixGrn = 0;
byte pixBlu= 255;


//EEPROM Locations
const uint8_t EEPROM_Brightness = 0;
const uint8_t EEPROM_Octave = 1;
const uint8_t EEPROM_Mode = 2;
const uint8_t EEPROM_Channel = 3;
uint8_t trellisBrightness=5;

//MIDI Sequencer
byte currentStep = 0;
int16_t currentPad = 0;
byte currentPatternLoops = 0;
byte currentBPM;
byte minimumBPM=60; //this sets the minimum BPM. Max BPM is minimumBPM + 127;
byte stepLength=32;
byte stepResolution = 16; //1/32    stepLength / stepResolution = time sig - 32/32 = 4/4

uint16_t PatternsNoteOn[3][8][32]; // 3 types of pattern: drum, bass, lead, 8 patterns of each, 32 steps of each
uint16_t PatternsNoteOff[3][8][32]; // 3 types of pattern: drum, bass, lead, 8 patterns of each, 32 steps of each
#define patDrum 0
#define patBass 1
#define patLead 2
#define midiChannelOffset 0 //default:0 chans 0,1,2 Setting this to 5 would use channels 5,6, and 7. patDrum+midiChannelOffset, patBass+midiChannelOffset, patLead+midiChannelOffset
byte currentPattern[3] = {0,0,0};

byte Pattern1NoteLength = 6;
uint16_t padWords[16];


//MIDI Definiations
const int defaultVelocity = 127;
int currentChannel = 0;
int currentOctave = 4; // middle C is number 60, octave 5.
bool currentRecording = false;
bool currentOverdub = false;
bool currentStopped = false;
bool currentPlaying = false;
int currentMode = 0;
#define ModeSeq1 0
#define ModeSeq2 1
#define ModeSeq3 2
#define ModePattern 3
byte seq1MidiChannel = 0;
byte seq2MidiChannel = 1;
byte seq3MidiChannel = 2;


//#define MIDINOTE_C 0
//#define MIDINOTE_C# 1
//#define MIDINOTE_D 2
//#define MIDINOTE_D# 3
//#define MIDINOTE_E 4
//#define MIDINOTE_F 5
//#define MIDINOTE_F# 6
//#define MIDINOTE_G 7
//#define MIDINOTE_G# 8
//#define MIDINOTE_A 9
//#define MIDINOTE_A# 10
//#define MIDINOTE_B 11


// trellis definitions
Adafruit_Trellis matrix0 = Adafruit_Trellis();
Adafruit_Trellis matrix1 = Adafruit_Trellis();
Adafruit_Trellis matrix2 = Adafruit_Trellis();
Adafruit_Trellis matrix3 = Adafruit_Trellis();
Adafruit_TrellisSet trellis =  Adafruit_TrellisSet(&matrix0, &matrix1, &matrix2, &matrix3);
#define NUMTRELLIS 4
#define numKeys (NUMTRELLIS * 16)
#define TRELLISINTPIN 5

const int pot1Pin = A8;    // select the input pins for the pots
const int pot2Pin = A0;    // select the input pins for the pots
const int pot3Pin = A2;    // select the input pins for the pots
const int pot4Pin = A3;    // select the input pins for the pots
const int pot5Pin = A6;    // select the input pins for the pots
const int pot6Pin = A7;    // select the input pins for the pots
const int pot7Pin = A1;    // select the input pins for the pots
const int pot8Pin = A9;    // select the input pins for the pots

int ledPin = 13;      // select the pin for the LED
int pot1Value = 0;  // variable to store the value coming from the pots
int pot2Value = 0;  // variable to store the value coming from the pots
int pot3Value = 0;  // variable to store the value coming from the pots
int pot4Value = 0;  // variable to store the value coming from the pots
int pot5Value = 0;  // variable to store the value coming from the pots
int pot6Value = 0;  // variable to store the value coming from the pots
int pot7Value = 0;  // variable to store the value coming from the pots
int pot8Value = 0;  // variable to store the value coming from the pots
int lastpot1Value = 0;  // variable to store the value coming from the pots
int lastpot2Value = 0;  // variable to store the value coming from the pots
int lastpot3Value = 0;  // variable to store the value coming from the pots
int lastpot4Value = 0;  // variable to store the value coming from the pots
int lastpot5Value = 0;  // variable to store the value coming from the pots
int lastpot6Value = 0;  // variable to store the value coming from the pots
int lastpot7Value = 0;  // variable to store the value coming from the pots
int lastpot8Value = 0;  // variable to store the value coming from the pots

float smoothPot1 = 0;
float smoothPot2 = 0;
float smoothPot3 = 0;
float smoothPot4 = 0;
float smoothPot5 = 0;
float smoothPot6 = 0;
float smoothPot7 = 0;
float smoothPot8 = 0;

unsigned long stepMicros = 62500; //120bpm default (7.5 / 120)ms = 0.0625 s * 1,000,000

const int inputLatency = 30; //in ms, query the inputs every XX mS. Found 30ms Is the fastest reliable time for updating the trellis key inputs, otherwise you get double hits.
const int serialLatency = 1000; //in ms, query the inputs every XX mS

Metro inputsMetro = Metro(inputLatency);  // pickup keypresses
Metro serialMetro = Metro(serialLatency);  // Instantiate an instance

void loopSequencer();
void trellisBootSequence()
{
   // light up all the LEDs in order
  for (uint8_t j=0; j<numKeys; j++) {
    trellis.setLED(j);
    trellis.writeDisplay();    
    delay(5);
  }
  // then turn them off
  for (uint8_t j=0; j<numKeys; j++) {
    trellis.clrLED(j);
    trellis.writeDisplay();    
    delay(5);
  }
}

void updateBPM(byte newBPM) {
  float factor = 32 / stepResolution;
	if (newBPM==0){
		Serial.println("Sequencer Halted");
		Serial.print(currentBPM);
		Serial.println("bpm");
		}
		else
		{
          		stepMicros = int32_t((((float(float(60)/float(newBPM))/(stepLength/4))*1000)*1000)*factor);
			currentBPM = newBPM;
			Serial.print("BPM Updated: ");
                        Serial.print(currentBPM);
                        Serial.print(" - ");
                        Serial.print(stepMicros);
                        Serial.println(" Microseconds per step");
                        
			//tick1 = pulsesPerBar / 4;
			//tick2 = tick1 * 2;
			//tick3 = tick2+tick1;			
		}
}


void setupPatterns()
{
  padWords[0] = 1;
  padWords[1] = 2;
  padWords[2] = 4;
  padWords[3] = 8;
  padWords[4] = 16;
  padWords[5] = 32;
  padWords[6] = 64;
  padWords[7] = 128;
  padWords[8] = 256;
  padWords[9] = 512;
  padWords[10] = 1024;
  padWords[11] = 2048;
  padWords[12] = 4096;
  padWords[13] = 8192;
  padWords[14] = 16384;
  padWords[15] = 32768;  
  
  for (uint8_t x=0; x<3; x++) {
     for (uint8_t y=0; y<8; y++) {
       for (uint8_t z=0; z<32; z++) {
       PatternsNoteOn[x][y][z]=0; // zero all the data to be sure.
       PatternsNoteOff[x][y][z]=0; // zero all the data to be sure.
       }
     }
  }
}

void clearSequencerLEDs(){
  for (uint8_t i=0; i < 32; i++) {
    trellis.clrLED(i);
  }
}

void clearBottomLeftLEDs(){
  for (uint8_t i=0; i < 16; i++) {
    trellis.clrLED(i+32);
  }
}

void setSequencerLED(byte sequencerLED){
  if (sequencerLED < 4) { trellis.setLED(sequencerLED);}
  else if (sequencerLED < 8) { trellis.setLED(sequencerLED+12);}
  else if (sequencerLED < 12) { trellis.setLED(sequencerLED-4);}
  else if (sequencerLED < 16) { trellis.setLED(sequencerLED+8);}
  else if (sequencerLED < 20) { trellis.setLED(sequencerLED-8);}
  else if (sequencerLED < 24) { trellis.setLED(sequencerLED+4);}
  else if (sequencerLED < 28) { trellis.setLED(sequencerLED-12);}
  else {trellis.setLED(sequencerLED);}
}

void flipSequencerLED(byte sequencerLED){
  if (sequencerLED < 4) { if (trellis.isLED(sequencerLED)) {trellis.clrLED(sequencerLED);} else {trellis.setLED(sequencerLED);}}
  else if (sequencerLED < 8) { if (trellis.isLED(sequencerLED+12)) {trellis.clrLED(sequencerLED+12);} else {trellis.setLED(sequencerLED+12);}}
  else if (sequencerLED < 12) { if (trellis.isLED(sequencerLED-4)) {trellis.clrLED(sequencerLED-4);} else {trellis.setLED(sequencerLED-4);}}
  else if (sequencerLED < 16) { if (trellis.isLED(sequencerLED+8)) {trellis.clrLED(sequencerLED+8);} else {trellis.setLED(sequencerLED+8);}}
  else if (sequencerLED < 20) { if (trellis.isLED(sequencerLED-8)) {trellis.clrLED(sequencerLED-8);} else {trellis.setLED(sequencerLED-8);}}
  else if (sequencerLED < 24) { if (trellis.isLED(sequencerLED+4)) {trellis.clrLED(sequencerLED+4);} else {trellis.setLED(sequencerLED+4);}}
  else if (sequencerLED < 28) { if (trellis.isLED(sequencerLED-12)) {trellis.clrLED(sequencerLED-12);} else {trellis.setLED(sequencerLED-12);}}
  else { if (trellis.isLED(sequencerLED)) {trellis.clrLED(sequencerLED);} else {trellis.setLED(sequencerLED);}}
}

byte translateSequencerSteptoPad(byte seqStep){ //could do with checking
  if (seqStep < 4) { return seqStep;}
  else if (seqStep < 8) { return (seqStep+12);}
  else if (seqStep < 12) { return (seqStep-4);}
  else if (seqStep < 16) { return (seqStep+8);}
  else if (seqStep < 20) { return (seqStep-8);}
  else if (seqStep < 24) { return (seqStep+6);}
  else if (seqStep < 28) { return (seqStep-5);}
  else {return seqStep;}
}

byte translateSequencerPadtoStep(byte seqPad){ //correct and tested
  if (seqPad < 4) { return seqPad;}
  else if (seqPad < 8) { return (seqPad+4);}
  else if (seqPad < 12) { return (seqPad+8);}
  else if (seqPad < 16) { return (seqPad+12);}
  else if (seqPad < 20) { return (seqPad-12);}
  else if (seqPad < 24) { return (seqPad-8);}
  else if (seqPad < 28) { return (seqPad-4);}
  else {return seqPad;}
}

void clearSequencerLED(byte sequencerLED){
  if (sequencerLED < 4) { trellis.clrLED(sequencerLED);}
  else if (sequencerLED < 8) { trellis.clrLED(sequencerLED+12);}
  else if (sequencerLED < 12) { trellis.clrLED(sequencerLED-4);}
  else if (sequencerLED < 16) { trellis.clrLED(sequencerLED+8);}
  else if (sequencerLED < 20) { trellis.clrLED(sequencerLED-8);}
  else if (sequencerLED < 24) { trellis.clrLED(sequencerLED+4);}
  else if (sequencerLED < 28) { trellis.clrLED(sequencerLED-12);}
  else {trellis.clrLED(sequencerLED);}
}


void sequencerUpdate(){
  //update other leds that should be on this cycle.
  for (uint8_t i=0; i < 32; i++) {
    if (PatternsNoteOn[currentMode][currentPattern[currentMode]][i] & padWords[currentPad]){setSequencerLED(i);}
  }
}


void patternUpdate()
{
   //Serial.print("MIDI Step: ");
   //Serial.println(currentStep);
   clearSequencerLEDs();
   sequencerUpdate();
   flipSequencerLED(currentStep);
}

void loopSequencer(){
  
    for (uint8_t j=0; j < 16; j++) {
      if (currentStep == 0){ //this fixes the currentStep 0 loop point, if its zero, we can't look at currentStep-1!!
       for (uint8_t instrument=0; instrument < 3; instrument++) {
         if (PatternsNoteOff[instrument][currentPattern[instrument]][currentStep+31] & padWords[j]) { // if there are any noteOffs pending, run them first of all.PatternsNoteOff[0][0][currentStep+31]
            usbMIDI.sendNoteOff(j+64, defaultVelocity, instrument+midiChannelOffset);
            usbMIDI.send_now();
            //PatternsNoteOff[instrument][currentPattern[instrument]][currentStep+31] = PatternsNoteOff[instrument][currentPattern[instrument]][currentStep+31] ^ padWords[j]; //xor clears the bit 
         }
       }
      }
      else { //ok, we're not on zero, we can just look at the step behind us now, currentStep -1 is fine.
        for (uint8_t instrument=0; instrument < 3; instrument++) {
          if (PatternsNoteOff[instrument][currentPattern[instrument]][currentStep-1] & padWords[j]) { // if there are any noteOffs pending, run them first of all.
            usbMIDI.sendNoteOff(j+64, defaultVelocity, instrument+midiChannelOffset);
            usbMIDI.send_now();
            //PatternsNoteOff[instrument][currentPattern[instrument]][currentStep-1] = PatternsNoteOff[instrument][currentPattern[instrument]][currentStep-1] ^ padWords[j]; //xor clears the bit
          }
         }
      }
      
      for (uint8_t instrument=0; instrument < 3; instrument++) {
        if (PatternsNoteOn[instrument][currentPattern[instrument]][currentStep] & padWords[j]){ // Any new notes to trigger on this step? then havea look and see about triggering notes.
          //usbMIDI.sendNoteOff(j+64, defaultVelocity, seq1MidiChannel);
          usbMIDI.sendNoteOn(j+64, defaultVelocity, instrument+midiChannelOffset);
          usbMIDI.send_now();
          
        }
      }
         
  }
  
  if (currentStep < 31){ currentStep++;} else {currentStep = 0;}
}

uint8_t returnMIDINote(uint8_t note, uint8_t octave) // note is a value from 0-11, octave is an octave from 0 to 10 - see MIDINoteDefs
{
    uint8_t result;
    result = (octave*12)+note;
    return result;
}

void loopTrellis()
{
  if (trellis.readSwitches()){
      Serial.println("trellis pressed");
      //Modes
      if (trellis.justPressed(56)) {currentMode=ModeSeq1; trellis.setLED(56); trellis.clrLED(57); trellis.clrLED(58); trellis.clrLED(59);}
      if (trellis.justPressed(57)) {currentMode=ModeSeq2; trellis.setLED(57); trellis.clrLED(56); trellis.clrLED(58); trellis.clrLED(59);}
      if (trellis.justPressed(58)) {currentMode=ModeSeq3; trellis.setLED(58); trellis.clrLED(56); trellis.clrLED(57); trellis.clrLED(59);}
      if (trellis.justPressed(59)) {currentMode=ModePattern; trellis.setLED(59); trellis.clrLED(56); trellis.clrLED(57); trellis.clrLED(58);}
      //Transport
      if (trellis.justPressed(60)) {currentRecording = true; currentOverdub=false; currentPlaying=true; currentStopped=false;
                                    trellis.setLED(60); trellis.setLED(63); trellis.clrLED(61); trellis.clrLED(62);}
      if (trellis.justPressed(61)) {currentRecording = false; currentOverdub=true; currentPlaying=true; currentStopped=false;
                                    trellis.setLED(61); trellis.setLED(63); trellis.clrLED(60); trellis.clrLED(62);}
      if (trellis.justPressed(62)) {if (currentStopped)
                                      {currentStep = 0; clearSequencerLEDs(); trellis.setLED(0);} 
                                    else 
                                      {currentRecording = false; currentOverdub=false; currentPlaying = false; currentStopped=true; 
                                       trellis.clrLED(60); trellis.clrLED(61); trellis.setLED(62); trellis.clrLED(63);}
                                   }
      if (trellis.justPressed(63)) {currentRecording = false; currentOverdub=false; currentStopped = false; currentPlaying = true; 
                                    trellis.clrLED(60); trellis.clrLED(61); trellis.clrLED(62); trellis.setLED(63);}
      if (currentMode<3){
                for (uint8_t i=32; i < 48; i++) { //if the playPad has been pressed....
                  if (trellis.justPressed(i)) {
                    clearBottomLeftLEDs(); 
                    trellis.setLED(i); 
                    currentPad = i-32;
                    if (currentOverdub | currentRecording) { //if we're recording then punch in your note to the sequencer
                      PatternsNoteOn[currentMode][currentPattern[currentMode]][currentStep] = PatternsNoteOn[currentMode][currentPattern[currentMode]][currentStep] | padWords[currentPad]; 
                      } 
                    usbMIDI.sendNoteOn(i+32, defaultVelocity, currentMode+midiChannelOffset); //don't forget to play it!
                    usbMIDI.send_now();
                  }
                  if (trellis.justReleased(i)) {
                    if (currentOverdub | currentRecording) { //if we're recording then punch in your note to the sequencer
                        PatternsNoteOff[currentMode][currentPattern[currentMode]][currentStep] = PatternsNoteOff[currentMode][currentPattern[currentMode]][currentStep] | padWords[currentPad]; 
                      } 
                  usbMIDI.sendNoteOff(i+32, defaultVelocity, currentMode+midiChannelOffset);
                  usbMIDI.send_now();
                  }                                    
                }
                for (uint8_t i=0; i < 32; i++) {
                  if (trellis.justPressed(i)) {
                    byte theStep = translateSequencerPadtoStep(i);
                    Serial.print("Step:");
                    Serial.println(theStep);
                                       
                    if ((PatternsNoteOn[currentMode][currentPattern[currentMode]][theStep] & padWords[currentPad])==padWords[currentPad]) //already set? disable it.
                        {
                          clearSequencerLED(theStep); PatternsNoteOn[currentMode][currentPattern[currentMode]][theStep]  = PatternsNoteOn[currentMode][currentPattern[currentMode]][theStep] ^ padWords[currentPad]; //xor it, if both the padWords bitmap and pattern have any bits set, they will change to 0
                          Serial.print("Clear LED ");
                          Serial.println(theStep);
                        }
                    else                                    // not set, add it.
                        {
                          setSequencerLED(theStep); PatternsNoteOn[currentMode][currentPattern[currentMode]][theStep] = PatternsNoteOn[currentMode][currentPattern[currentMode]][theStep] | padWords[currentPad];
                          //PatternsNoteOff[currentMode][currentPattern[currentMode]][theStep+1] |= padWords[currentPad]; //set the noteoff to run on the next step, for now. 
                          PatternsNoteOff[currentMode][currentPattern[currentMode]][theStep+1] = PatternsNoteOff[currentMode][currentPattern[currentMode]][theStep+1] | padWords[currentPad];
                          Serial.print("Set LED ");
                          Serial.println(theStep);
                        }
                   }                    
                }
                
                }
    
    
    else if (currentMode==ModePattern){ //do patterny stuff 
    }
  }

}

void OnNoteOn(byte channel, byte note, byte velocity)
{
  if (note<64) {  trellis.setLED(note); }
}

void OnNoteOff(byte channel, byte note, byte velocity)
{
  if (note<64) {  trellis.clrLED(note); }
}

void loopAnalogue() {
//  smoothPot1 = 0.9 * smoothPot1 + 0.1 * analogRead(pot1Pin); //signal smoothing
//  pot1Value = int16_t(smoothPot1)/8; // Divide 0-1023 by 8 for 0-127
  smoothPot2 = 0.9 * smoothPot2 + 0.1 * analogRead(pot2Pin);
  pot2Value = int16_t(smoothPot2)/8;
  smoothPot3 = 0.9 * smoothPot3 + 0.1 * analogRead(pot3Pin);
  pot3Value = int16_t(smoothPot3)/8;
  smoothPot4 = 0.9 * smoothPot4 + 0.1 * analogRead(pot4Pin);
  pot4Value = int16_t(smoothPot4)/8;
  smoothPot5 = 0.9 * smoothPot5 + 0.1 * analogRead(pot5Pin);
  pot5Value = int16_t(smoothPot5)/8;
  smoothPot6 = 0.9 * smoothPot6 + 0.1 * analogRead(pot6Pin);
  pot6Value = int16_t(smoothPot6)/8;
  smoothPot7 = 0.9 * smoothPot7 + 0.1 * analogRead(pot7Pin);
  pot7Value = int16_t(smoothPot7)/8;
  smoothPot8 = 0.9 * smoothPot8 + 0.1 * analogRead(pot8Pin);
  pot8Value = int16_t(smoothPot8)/8;

   pot1Value = ((analogRead(pot1Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot2Value = ((analogRead(pot2Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot3Value = ((analogRead(pot3Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot4Value = ((analogRead(pot4Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot5Value = ((analogRead(pot5Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot6Value = ((analogRead(pot6Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot7Value = ((analogRead(pot7Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
//   pot8Value = ((analogRead(pot8Pin)* 0.8)+0.2)/8; // Divide 0-1023 by 8 for 0-127
   
//  smoothPot2 = 0.9 * smoothPot2 + 0.1 * analogRead(pot2Pin);
  
  if (lastpot1Value != pot1Value) {
  //usbMIDI.sendControlChange(70, pot1Value, currentChannel);
  //Serial.print("Pot1 : ");
  //Serial.println(pot1Value);
  int val = pot1Value + minimumBPM; 
  updateBPM(val);
  lastpot1Value = pot1Value;}
  
  if (lastpot2Value != pot2Value) {
  //usbMIDI.sendControlChange(71, pot2Value, currentChannel);
  Serial.print("Pot2 : ");
  Serial.println(pot2Value);
  lastpot2Value = pot2Value;} 
  
  if (lastpot3Value != pot3Value) {
  //usbMIDI.sendControlChange(72, pot3Value, currentChannel);
  Serial.print("Pot3 : ");
  Serial.println(pot3Value);
  pixGrn = pot3Value * 2;
  lastpot3Value = pot3Value;}
  
  if (lastpot4Value != pot4Value) {
  Serial.print("Pot4 : ");
  Serial.println(pot4Value);
  //usbMIDI.sendControlChange(73, pot4Value, currentChannel);
  pixBlu = pot4Value * 2;
  lastpot4Value = pot4Value;}
  
  if (lastpot5Value != pot5Value) {
  //usbMIDI.sendControlChange(74, pot5Value, currentChannel);
  Serial.print("Pot5 : ");
  Serial.println(pot5Value);
  lastpot5Value = pot5Value;} 
  
  if (lastpot6Value != pot6Value) {
  //usbMIDI.sendControlChange(75, pot6Value, currentChannel);
  pixRed = pot6Value * 2;
  Serial.print("Pot6 : ");
  Serial.println(pot6Value);
  lastpot6Value = pot6Value;}
 
 if (lastpot7Value != pot7Value) {
  //usbMIDI.sendControlChange(76, pot7Value, currentChannel);
  
  lastpot7Value = pot7Value;} 
  
 if (lastpot8Value != pot8Value) {
  usbMIDI.sendControlChange(77, pot8Value, currentChannel);
  Serial.print("Pot8 : ");
  Serial.println(pot8Value);
  lastpot8Value = pot8Value;}  
  
  
  //pot2Value = analogRead(pot2Pin);
  //pot3Value = analogRead(pot3Pin);
  //pot4Value = analogRead(pot4Pin);
  //pot5Value = analogRead(pot5Pin);
  //pot6Value = analogRead(pot6Pin);
  //pot7Value = analogRead(pot7Pin);
  //pot8Value = analogRead(pot8Pin);
}


void loopUpdateInputs() {
  Serial.println("loopUpdateInputs ");
  loopTrellis(); // update I/O from trellis
  loopAnalogue(); // update I/O from analogue pots
  patternUpdate(); // update remaining trellis led situation
  //int a = touchRead(0);
  //Serial.print("Touch: ");
  //Serial.println(a);
}

void setup() {
  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT); 
  pinMode(TRELLISINTPIN, INPUT);
  digitalWrite(TRELLISINTPIN, HIGH); 
  Serial.begin(9600);
  delay(1000);
  Serial.println("Serial output running");
  trellis.begin(0x70, 0x71, 0x72, 0x73);  
  trellis.setBrightness(trellisBrightness);
    trellisBootSequence();
    usbMIDI.setHandleNoteOff(OnNoteOff);
    usbMIDI.setHandleNoteOn(OnNoteOn);
   Serial.println("setupPatterns();");
   setupPatterns(); 
   currentMode=ModeSeq1; //boot into sequencer
   trellis.setLED(56);  //tell the user the mode
   trellis.setLED(62); // start in stopped mode.
   trellis.setLED(0); // start in stopped mode.
   currentStep = 0;
   // setMode at bootup
   trellis.setLED(32); //set to 
   currentPad = 0;
   //
   currentPlaying = false;
   currentStopped = true;
   currentRecording = false;
   currentOverdub = false;
   Serial.println("updateBPM(96);");
   updateBPM(96);
   Serial.println("trellis.writeDisplay();");
   trellis.writeDisplay();
   strip.begin();
   strip.show(); // Initialize all pixels to 'off'
}


void loop() {
  // This is the high technology sequencer - no interrupts, just exists in the loop. It is quite possible it could lose time at some point. 
  if (seqTimer > stepMicros) {
    seqTimer = 0; //reset the timer
    if (currentPlaying) {loopSequencer();
    }
  }
  
  
  if (inputsMetro.check() == 1) { // check if the metro has passed it's interval .
      loopUpdateInputs();
      strip.setPixelColor(0, pixRed, pixGrn, pixBlu);
      strip.show();
      
      
      while (usbMIDI.read(currentChannel)) { }// check for midi input and update the LEDs.
      trellis.writeDisplay();
      }
       
      if (serialMetro.check() == 1) { // check if the metro has passed it's interval .
      }
      
}
 
It's safe to say usbMidi noteon and noteoff work just fine, as well as midi reads, they work great as well.
 
I've uploaded 1.21-beta8.

This version has new Tools > CPU Speed options, for optimized speed vs optimized size (formerly the only choice).

The SPI library has SPI1. Lots of internal changes are in kinetis.h, for how the registers are defined. Hopefully I didn't break anything?
 
voltage of analogReference(INTERNAL) vs (EXTERNAL)

I have been running the same code alternately on Teensy 3.0, 3.1 and Teensy LC, on Windows 7 (currently Arduino 1.0.6 / Teensyduino 1.21-beta8). When I plug in the Teensy LC, Win7 says "downloading driver" although it had done so already.

I gather the LC version has no 1.2V internal reference? At any rate, code that has analogReference(INTERNAL) reads values indicating that Vref is about Vdd = 3.3 V, and not 1.2 V as with Teensy 3.0 / 3.1

The below code assumes a system clock frequency of 48 MHz. It takes a 1-PPS signal input from a GPS, and ambient temperature as an analog level from an LM35 sensor, and averages readings over 60 seconds to calculate the absolute error in PPM of the crystal relative to the assumed-correct 1 PPS input signal. Plotting the output over some temperature range allows calculation of ppm/C drift. A few boards I measured are below. I am sure the measured variation is everything to do with the particular crystal, and nothing to do with the particular device. "garden variety" CPU crystals are usually only guaranteed to be within +/- 100 ppm absolute and often have no particular temperature tolerance specified, so all three tested units look fine to me in this regard.

T3.0: -4.21 ppm @ 20.2 C, -0.138 ppm/C
T3.1: -14.47 ppm @ 21.0 C, -0.156 ppm/C
T_LC: +16.9 ppm @ 19.58 C, -0.309 ppm/C

Code:
Rdg , degC , ppm
# from Teensy 3.1
1 , 21.3820 , -14.555
2 , 21.3966 , -14.559
3 , 21.4091 , -14.563
4 , 21.4212 , -14.564
5 , 21.4327 , -14.563
6 , 21.4452 , -14.568
7 , 21.4583 , -14.569
8 , 21.4705 , -14.570
9 , 21.4828 , -14.574
10 , 21.4956 , -14.575

Rdg , degC , ppm
# from Teensy LC (green beta)
Rdg , degC , ppm
1 , 21.5658 , 16.222
2 , 21.5536 , 16.223
3 , 21.5441 , 16.228
4 , 21.5399 , 16.230
5 , 21.5323 , 16.233
6 , 21.5278 , 16.234
7 , 21.5255 , 16.235
8 , 21.5238 , 16.236
9 , 21.5215 , 16.235
10 , 21.5234 , 16.236


Code:
// based on PaulS's FreqMeasure for Teensy example
// Digital Input: 1 PPS signal : on Teensy LC: Pin 16  on Teensy 3/3.1: Pin 3
//  Analog Input: 10 mV/degC temp from LM35 : Analog 1

#include <FreqMeasure.h>

#define TEMP_IN A1           // analog input with 10 mV/deg.C from LM35 temp sensor
#define AVERAGES 60          // how many input pulses to integrate over
//#define VREF (3.316)         // Teensy LC ADC reference voltage (= Vdd power supply)
#define VREF (1.2)         // Teensy 3.0/3.1 ADC internal reference voltage
#define ADCMAX (65535)       // maximum possible reading from ADC
#define NOMCOUNT (48000000)  // nominal oscillator frequency count
#define NOMCM (48)           // nominal count divided by 1E6 (for ppm calculation)

void setup() {
  pinMode(TEMP_IN,INPUT);   
  analogReference(INTERNAL);  // set analog reference to internal ref
//  analogReference(EXTERNAL);  // set analog reference to external
  analogReadRes(16);          // Teensy: set ADC resolution to this many bits
  analogReadAveraging(16);    // average this many readings
 
  Serial.begin(115200);
  FreqMeasure.begin();
}

double sum=0;
double ppm;  // frequency error in ppm
int count=0;
unsigned long lastT = 0;
unsigned long deltaT;
unsigned long newT;
unsigned long reading = 0;  // how many measurements we've reported
boolean firstTime = true;
double x=0; // analog temperature reading (LM35)
unsigned long tsamp=0;  // how many temperature readings we've done
long fcount;  // raw frequency count value

void loop() {
  if (FreqMeasure.available()) {
    newT = micros();
    fcount = FreqMeasure.read();
    // Serial.println(fcount);
    sum = sum + (fcount - (NOMCOUNT));
    count = count + 1;
    if (count >= AVERAGES) {
      deltaT = newT - lastT;
      lastT = newT;
      if (firstTime) {
        firstTime = false;
        Serial.println("Rdg , degC , ppm");
      } else {
        ppm = sum / (NOMCM * AVERAGES);
        x /= tsamp;
        float degC = 100 * (VREF/ADCMAX)*x; // LM35 temp sensor = 10 mV/C
        float freq = FreqMeasure.countToFrequency(sum / count);
        reading++;
        Serial.print(reading);       Serial.print(" , ");
        Serial.print(degC,4);        Serial.print(" , ");
        Serial.print(ppm,3);
        Serial.println();
      }
      sum = 0;
      count = 0;
      x = 0;
      tsamp = 0;
    }
  } else {
    x += analogRead(TEMP_IN); 
    tsamp++;
  }
} // end loop()

T31-PPM-150307.jpg
 
nit: 'double' is 64 bit flloating point. On many MCUs it is silently converted to 'float' which is 32 bits.
I tend to not use 'double' on MCUs with hardware floating point as it is rarely implemented.
 
There's one thing I noticed, using 48Mhz optimized on Teensy LC almost doubles the memory used.
Almost same thing the 96Mhz optimized vs 96Mhz on Teensy 3.1.
What is the difference between normal and optimized?
 
precision of float vs. double

nit: 'double' is 64 bit flloating point. On many MCUs it is silently converted to 'float' which is 32 bits.
I tend to not use 'double' on MCUs with hardware floating point as it is rarely implemented.

I'm not sure if you're referring to Teensy 3/3.1/LC or some other platform. I can confirm that Teensy LC has doubles that work they way they should. You can try running the code below on whatever platform you prefer and see how it works. In loop(), try changing the definition of 'f' to float instead of double and see what happens.

Code:
// Test of function that builds a C-style "string" for a floating point
// number in scientific notation.
//
// original by davekw7x December, 2010  
// http://arduino.cc/forum/index.php/topic,46931.0.html
// modified to use "double" and to run to smaller / larger values  March 12 2013 JPB

void setup()
{
    Serial.begin(115200);
    delay(3000);
    Serial.println("Starting...");
    
} // ===== end double2s()

void loop() {
    double f;
//    float f;
  
    delay(3000);
    Serial.println("double precision floating point test");

    f = 0.0;
    // No "digits" argument means 2 digits
    Serial.print("0.0 = ");
    Serial.println(double2s(f));Serial.println();
    
    // Rounding with leading zeros in the fractional part
    f = 10.3456;
    Serial.print(f,4);Serial.print(" = ");
    Serial.println(double2s(f, 4));Serial.println();
    
    /* 
       For loops 1 and 2, note that floating point
       overflows result values of"INF"
    */
    f = PI;
    
    Serial.println("Loop 1");
    for (int i=1; i<58; i++)
    {
        Serial.println( double2s(f,16));
        f *=1E6;
    }
    Serial.println();

    f = -PI;
    Serial.println("Loop 2");
    for (int i=1; i< 58; i++)
    {
        Serial.println(double2s(f, 16));
        f *=1E6;
    }  
    Serial.println();

    /*
       For loops 3 and 4 note that floating point
       underflows result in values that go to zero.
    */
    f = PI;
    Serial.println("Loop 3");
    for (int i=1; i< 60; i++)
    {
        Serial.println(double2s(f, 16));
        f /= 1E6;
    }
    Serial.println();

    f = -PI;
    Serial.println("Loop 4");
    for (int i=1; i< 58; i++)
    {
        Serial.println(double2s(f, 16));
        f /= 1E6;
    }
    Serial.println();

    /*
       Loop 5 shows rounding as follows:
        6: 1.999518 E+20
        5: 1.99952 E+20
        4: 1.9995 E+20
        3: 2.000 E+20
        2: 2.00 E+20
        1: 2.0 E+20
        0: 2 E+20
    */

    f = 1.999518e20;
    Serial.println("Loop 5");
    for (int i = 16; i >= 0; i--) {
        Serial.print(i);Serial.print(": ");Serial.println(double2s(f, i));
    }
    Serial.println();
    
    /* 
       Loop 6 shows rounding as follows:
        6: 1.999496 E+20
        5: 1.99950 E+20
        4: 1.9995 E+20
        3: 1.999 E+20
        2: 2.00 E+20
        1: 2.0 E+20
        0: 2 E+2
    */
    
    f = 1.999496e20;
    Serial.println("Loop 6");
    for (int i = 16; i >= 0; i--) {
        Serial.print(i);Serial.print(": ");Serial.println(double2s(f, i));
    }    
    Serial.println();
    
    Serial.println("NaN tests");
    f = sqrt(-1);
    Serial.print("sqrt(-1) = ");Serial.println(double2s(f, 3));

    f = 0.0/0.0;
    Serial.print("0.0/0.0 = ");Serial.println(double2s(f, 4));

    f = INFINITY * 0;
    Serial.print("INFINITY*0 = ");Serial.println(double2s(f, 5));Serial.println();

    
    Serial.println("INFINITY tests");
    f = 1.0/0;
    Serial.print("1.0/0 = ");Serial.println(double2s(f, 1));
    //printBytes(f); 

    f = -1.0/0;
    Serial.print("1.0/-0 = ");Serial.println(double2s(f, 1)); 
    //printBytes(f); 

    f = -1.0/0L;
    Serial.print("1.0/0L = ");Serial.println(double2s(f, 2));
    
    f = 1.0/0UL;
    Serial.print("1.0/0UL = ");Serial.println(double2s(f, 3));
    
    Serial.println();
    
    // Note that tan(pi/2) may not result in INF due
    // to limited precision.
    //
    f = tan(HALF_PI);
    Serial.print("tan(");Serial.print(HALF_PI, 6);Serial.print(") = ");  
    Serial.println(double2s(f, 6));
    
      do {} while (true);
}  // end loop()


// ====== double2s(): print out up to 16 digits of input double-precision value
// This version enables double-precision for Teensy 3, etc. 
// by J.Beale March 2013
// modified from original float2s() posted by davekw7x on December, 2010
// http://arduino.cc/forum/index.php/topic,46931.0.html

char * double2s(double f)
{
  return double2s(f, 2);
}

char * double2s(double f, unsigned int digits) {    
int d;
static char s[26];  // formated number as string
int index=0;

  // handle sign
  if (f < 0.0)
  {
    s[index++] = '-';
    f = -f;
  } 
  // handle infinite values
  if (isinf(f))
  {
    strcpy(&s[index], "INF");
    return s;
  }
  // handle Not a Number
  if (isnan(f)) 
  {
    strcpy(&s[index], "NaN");
    return s;
  }

  // max digits
  if (digits > 16) digits = 16;
  int exponent = int(log10(f));
  double g = f / pow(10, exponent);
  if ((g < 1.0) && (g != 0.0))      
  {
    g *= 10;
    exponent--;
  }
  if (exponent < -324) {  // lower limit of double-precision on Teensy 3
    g = 0;
    exponent = 0;
  }
  if (digits < 16) {  // display number rounded at last digit
    g += 0.5 / pow(10,digits);
  }
  
  d = g;   
  sprintf(&s[index++],"%d",d);  
  sprintf(&s[index++],".");
  for (unsigned int i=0;i<digits;i++) {
      g = (g - d) * 10.0;  // shift one decimal place to the left
      d = int(g);
      sprintf(&s[index++],"%d",d);
  }
  sprintf(&s[index], " E%+d", exponent);
  return s;
}

Output of Teensy 3.1 and Teensy LC with f defined as double:

Code:
Starting...
double precision floating point test
0.0 = 0.00 E+0

10.3456 = 1.0346 E+1

Loop 1
3.1415926535897931 E+0
3.1415926535897931 E+6
3.1415926535897931 E+12
3.1415926535897926 E+18
3.1415926535897931 E+24
3.1415926535897926 E+30
3.1415926535897926 E+36
3.1415926535897931 E+42
3.1415926535897922 E+48
3.1415926535897922 E+54
3.1415926535897926 E+60
3.1415926535897931 E+66
3.1415926535897931 E+72
3.1415926535897926 E+78
3.1415926535897926 E+84
3.1415926535897926 E+90
3.1415926535897926 E+96
3.1415926535897926 E+102
3.1415926535897922 E+108
3.1415926535897926 E+114
3.1415926535897926 E+120
3.1415926535897926 E+126
3.1415926535897931 E+132
3.1415926535897931 E+138
3.1415926535897931 E+144
3.1415926535897931 E+150
3.1415926535897931 E+156
3.1415926535897931 E+162
3.1415926535897931 E+168
3.1415926535897926 E+174
3.1415926535897926 E+180
3.1415926535897926 E+186
3.1415926535897922 E+192
3.1415926535897922 E+198
3.1415926535897922 E+204
3.1415926535897917 E+210
3.1415926535897922 E+216
3.1415926535897922 E+222
3.1415926535897926 E+228
3.1415926535897922 E+234
3.1415926535897926 E+240
3.1415926535897922 E+246
3.1415926535897922 E+252
3.1415926535897922 E+258
3.1415926535897922 E+264
3.1415926535897926 E+270
3.1415926535897926 E+276
3.1415926535897926 E+282
3.1415926535897926 E+288
3.1415926535897926 E+294
3.1415926535897922 E+300
3.1415926535897922 E+306
INF
INF
INF
INF
INF

Loop 2
-3.1415926535897931 E+0
-3.1415926535897931 E+6
-3.1415926535897931 E+12
-3.1415926535897926 E+18
-3.1415926535897931 E+24
-3.1415926535897926 E+30
-3.1415926535897926 E+36
-3.1415926535897931 E+42
-3.1415926535897922 E+48
-3.1415926535897922 E+54
-3.1415926535897926 E+60
-3.1415926535897931 E+66
-3.1415926535897931 E+72
-3.1415926535897926 E+78
-3.1415926535897926 E+84
-3.1415926535897926 E+90
-3.1415926535897926 E+96
-3.1415926535897926 E+102
-3.1415926535897922 E+108
-3.1415926535897926 E+114
-3.1415926535897926 E+120
-3.1415926535897926 E+126
-3.1415926535897931 E+132
-3.1415926535897931 E+138
-3.1415926535897931 E+144
-3.1415926535897931 E+150
-3.1415926535897931 E+156
-3.1415926535897931 E+162
-3.1415926535897931 E+168
-3.1415926535897926 E+174
-3.1415926535897926 E+180
-3.1415926535897926 E+186
-3.1415926535897922 E+192
-3.1415926535897922 E+198
-3.1415926535897922 E+204
-3.1415926535897917 E+210
-3.1415926535897922 E+216
-3.1415926535897922 E+222
-3.1415926535897926 E+228
-3.1415926535897922 E+234
-3.1415926535897926 E+240
-3.1415926535897922 E+246
-3.1415926535897922 E+252
-3.1415926535897922 E+258
-3.1415926535897922 E+264
-3.1415926535897926 E+270
-3.1415926535897926 E+276
-3.1415926535897926 E+282
-3.1415926535897926 E+288
-3.1415926535897926 E+294
-3.1415926535897922 E+300
-3.1415926535897922 E+306
-INF
-INF
-INF
-INF
-INF

Loop 3
3.1415926535897931 E+0
3.1415926535897935 E-6
3.1415926535897931 E-12
3.1415926535897935 E-18
3.1415926535897935 E-24
3.1415926535897935 E-30
3.1415926535897935 E-36
3.1415926535897940 E-42
3.1415926535897940 E-48
3.1415926535897940 E-54
3.1415926535897940 E-60
3.1415926535897948 E-66
3.1415926535897948 E-72
3.1415926535897948 E-78
3.1415926535897948 E-84
3.1415926535897940 E-90
3.1415926535897940 E-96
3.1415926535897940 E-102
3.1415926535897948 E-108
3.1415926535897948 E-114
3.1415926535897948 E-120
3.1415926535897953 E-126
3.1415926535897953 E-132
3.1415926535897953 E-138
3.1415926535897953 E-144
3.1415926535897948 E-150
3.1415926535897948 E-156
3.1415926535897948 E-162
3.1415926535897948 E-168
3.1415926535897948 E-174
3.1415926535897948 E-180
3.1415926535897948 E-186
3.1415926535897948 E-192
3.1415926535897948 E-198
3.1415926535897948 E-204
3.1415926535897948 E-210
3.1415926535897953 E-216
3.1415926535897948 E-222
3.1415926535897948 E-228
3.1415926535897948 E-234
3.1415926535897948 E-240
3.1415926535897953 E-246
3.1415926535897948 E-252
3.1415926535897953 E-258
3.1415926535897948 E-264
3.1415926535897953 E-270
3.1415926535897948 E-276
3.1415926535897953 E-282
3.1415926535897948 E-288
3.1415926535897948 E-294
3.1415926535897948 E-300
3.1415926535897948 E-306
3.1415926535886367 E-312
3.1415897941871211 E-318
5.0000000000000000 E-324
0.0000000000000000 E+0
0.0000000000000000 E+0
0.0000000000000000 E+0
0.0000000000000000 E+0

Loop 4
-3.1415926535897931 E+0
-3.1415926535897935 E-6
-3.1415926535897931 E-12
-3.1415926535897935 E-18
-3.1415926535897935 E-24
-3.1415926535897935 E-30
-3.1415926535897935 E-36
-3.1415926535897940 E-42
-3.1415926535897940 E-48
-3.1415926535897940 E-54
-3.1415926535897940 E-60
-3.1415926535897948 E-66
-3.1415926535897948 E-72
-3.1415926535897948 E-78
-3.1415926535897948 E-84
-3.1415926535897940 E-90
-3.1415926535897940 E-96
-3.1415926535897940 E-102
-3.1415926535897948 E-108
-3.1415926535897948 E-114
-3.1415926535897948 E-120
-3.1415926535897953 E-126
-3.1415926535897953 E-132
-3.1415926535897953 E-138
-3.1415926535897953 E-144
-3.1415926535897948 E-150
-3.1415926535897948 E-156
-3.1415926535897948 E-162
-3.1415926535897948 E-168
-3.1415926535897948 E-174
-3.1415926535897948 E-180
-3.1415926535897948 E-186
-3.1415926535897948 E-192
-3.1415926535897948 E-198
-3.1415926535897948 E-204
-3.1415926535897948 E-210
-3.1415926535897953 E-216
-3.1415926535897948 E-222
-3.1415926535897948 E-228
-3.1415926535897948 E-234
-3.1415926535897948 E-240
-3.1415926535897953 E-246
-3.1415926535897948 E-252
-3.1415926535897953 E-258
-3.1415926535897948 E-264
-3.1415926535897953 E-270
-3.1415926535897948 E-276
-3.1415926535897953 E-282
-3.1415926535897948 E-288
-3.1415926535897948 E-294
-3.1415926535897948 E-300
-3.1415926535897948 E-306
-3.1415926535886367 E-312
-3.1415897941871211 E-318
-5.0000000000000000 E-324
0.0000000000000000 E+0
0.0000000000000000 E+0

Loop 5
16: 1.9995179999999999 E+20
15: 1.999518000000000 E+20
14: 1.99951800000000 E+20
13: 1.9995180000000 E+20
12: 1.999518000000 E+20
11: 1.99951800000 E+20
10: 1.9995180000 E+20
9: 1.999518000 E+20
8: 1.99951800 E+20
7: 1.9995180 E+20
6: 1.999518 E+20
5: 1.99952 E+20
4: 1.9995 E+20
3: 2.000 E+20
2: 2.00 E+20
1: 2.0 E+20
0: 2. E+20

Loop 6
16: 1.9994959999999998 E+20
15: 1.999496000000000 E+20
14: 1.99949600000000 E+20
13: 1.9994960000000 E+20
12: 1.999496000000 E+20
11: 1.99949600000 E+20
10: 1.9994960000 E+20
9: 1.999496000 E+20
8: 1.99949600 E+20
7: 1.9994960 E+20
6: 1.999496 E+20
5: 1.99950 E+20
4: 1.9995 E+20
3: 1.999 E+20
2: 2.00 E+20
1: 2.0 E+20
0: 2. E+20

NaN tests
sqrt(-1) = NaN
0.0/0.0 = NaN
INFINITY*0 = NaN

INFINITY tests
1.0/0 = INF
1.0/-0 = -INF
1.0/0L = -INF
1.0/0UL = INF

tan(1.570796) = 1.633124 E+16
 
If the target MCU has no floating point hardware, a software floating point library for 64 bit doubles might exist, again, depending on the target MCU.
I understand that the LC's M0+ has no hardware floating point, so a software emulation is done.
Whether that emulation always or optionally converts doubles to floats (32 bits) - someone on the forum would know. Depends on what libraries are used.
 
Steve, double uses 64 bits on Teensy LC, 3.0 and 3.1. I've seen you raise (but not answer) this question at least a few times.

Please allow this simple test program to put this question to rest. Double is 64 bits and float is 32 bit on ARM-based Teensy.

Code:
void setup() {
  while (!Serial);
  delay(100);
  Serial.printf("float is  %d bytes\n", sizeof(float));
  Serial.printf("double is %d bytes\n", sizeof(double));
  float fa = 1000000000;
  float fb = 1234;
  unsigned long n = fa + fb;
  Serial.printf("sum (using float) =  %ld\n", n);
  double da = 1000000000;
  double db = 1234;
  n = da + db;
  Serial.printf("sum (using double) = %ld\n", n);
}

void loop() {
}

If you run this on Teensy-LC, or Teensy 3.0 or Teensy 3.1, you'll see this in the serial monitor:

Code:
float is  4 bytes
double is 8 bytes
sum (using float) =  1000001216
sum (using double) = 1000001234

On AVR chips (Teensy 2.0, regular AVR Arduino, etc), double and float are both 32 bits.
 
There's one thing I noticed, using 48Mhz optimized on Teensy LC almost doubles the memory used.
Almost same thing the 96Mhz optimized vs 96Mhz on Teensy 3.1.
What is the difference between normal and optimized?

Optimized compiles all files with "-O" optimization (which is actually faster than -O2 or -O3) and then links the regular (speed optimized) newlib library.

The others compile all files with "-Os" optimization, which produces much smaller code, and then links with the size-optimized newlib-nano library.

If you use printf(), newlib-nano defaults to a compact printf that lacks support for printing floating point numbers. That saves about 20K of code space. The regular newlib library supports floats. It also has speed optimized functions, like memcpy() and memset(), as recently discussed on another thread.

I arranged the Tools > CPU Speed menu differently on LC & 3.1, so speed optimized would be the default on 3.1, but size optimized would be the default for LC.
 
I should probably also mention, in some benchmarking I did recently, changing between -Os to -O makes a pretty substantial speed improvement on Cortex M4 (Teensy 3.1).

However, on Cortex M0+ (Teensy-LC), there seems to be very little difference in speed. Perhaps future compilers will change that, but with gcc 4.8.4 we're using today, it seems the optimizations do very little good.
 
nit: 'double' is 64 bit flloating point. On many MCUs it is silently converted to 'float' which is 32 bits.
I tend to not use 'double' on MCUs with hardware floating point as it is rarely implemented.
Depends on the microprocessor. Some have both single and double precision floating point. On some, double precision is in fact faster than single precision, such as the PDP-11 that the original C compiler was written for, and the PowerPC.

Note, if you only use float, you should also make sure that all floating point constants have a 'f' suffix. Otherwise, the compiler will need to convert the expression to double and then back to float.
 
Steve, double uses 64 bits on Teensy LC, 3.0 and 3.1. I've seen you raise (but not answer) this question at least a few times.

Please allow this simple test program to put this question to rest. Double is 64 bits and float is 32 bit on ARM-based Teensy.

On AVR chips (Teensy 2.0, regular AVR Arduino, etc), double and float are both 32 bits.


I humbly apologize. I was trying to explain to people coming from PCs where there is always hardware floating point and doubles.
MCUs that lack hardware floating point are, of course, much slower at floating point. Few or no ARM Cortex have doubles in hardware.
Some people here don't know that.

I'll refrain.
 
Float and Double work as in the samples nice to see it clearly to know the support they have - without an FPU they come at a cost in code size and cycles. The .asm method to enable when otherwise optimized out worked to split the difference in the sample presented. In this case that is simpler than menu creep, already tough to label them.
 
I've uploaded 1.21-beta8.

This version has new Tools > CPU Speed options, for optimized speed vs optimized size (formerly the only choice).

The SPI library has SPI1. Lots of internal changes are in kinetis.h, for how the registers are defined. Hopefully I didn't break anything?

most of my little benchmarks ran OK with optimized speed, most a little faster (some not). However, the DMA memory copy sketch here
https://github.com/manitou48/teensy3/blob/master/mem2mem.pde
hangs after the first println when compiled optimized (-O). if rebuild unoptimized (-Os) it runs ok. teensy 3.1, 1.6.0 1.21-beta* on Ubuntu.
 
I've been working on the low power support in the bootloader this weekend. After many long hours of adjusting settings and testing, I believe it's finally working.

Previously, the KL02 chip (replacing the Mini54) was running about 5 mA all the time.

The one on my bench is running about 0.1 mA (just the KL02 chip) when Teensy-LC runs normally, and about 4 uA when Teensy-LC goes into a deep sleep mode.

Like the Mini54, once it's into the 4 uA mode, Arduino can't auto-reboot Teensy-LC, even if the main processor returns to a proper run mode. You have to press the pushbutton to reprogram.

I'm going to do another round of testing tonight. If all looks good, my plan is to published 1.21-beta9 with the low power bootloader upgrade. Only the green boards with gold plating will upgrade. The purple and green-tin boards are forever stuck with the original not-low-power bootloader.

I had originally hoped to be at this point 2 weeks ago. Supporting Arduino 1.6.0 really set the schedule back! This doesn't leave much time for beta testing the low power feature. :(
 
While testing "-flto", I got an error because of multiple definitions of "strlen".
Indeed, there is a strlen defined in "nonstd.c". I think, strlen is now defined in newlib, so perhaps it would be good to comment this out, or delete it (for beta 9?) But i did not test this!
I noticed that the compiled result gets some bytes smaller.
 
Last edited:
perhaps add __attribute__ ((optimize("Os"))) to some teensyduino functions (for example ResetHandler()).
Not all needs to be speed-optimized. Perhaps in teensyduino 122 ?
 
Last edited:
Paul, while playing around with supporting SPI displays, I have been looking at different things like: how your AVR emulation works. I am wondering about the SPDR stuff.
Code:
class SPDRemulation
{
public:
	inline SPDRemulation & operator = (int val) __attribute__((always_inline)) {
		if ((SPI0_S & SPI_S_SPTEF)) {
			uint32_t tmp __attribute__((unused)) = SPI0_DL;
		}
		SPI0_DL = val;
		return *this;
	}
I am probably wrong, but I don't understand looking at: SPI_S_SPTEF and doing a read. I believe SPI_S_SPTEF is the Transmit empty flag. Shouldn't it look at: SPI_S_SPRF (Read Full) instead?

Again I am probably wrong...

Kurt
 
Back
Top