Arduino 1.8.3

Status
Not open for further replies.
Thanks Paul,

I was also wondering if it would make sense to add a new API that takes care of it for you... Something like:
static SPIClass *mapPinsToBuss(uint8_t sck, uint8_t mosi=0xff, uint8_t miso=0xff)

Then user classes/programs, could simply pass the values in a get a pointer to the appropriate buss... Thought maybe could be reference instead, but not sure if references work inside classes very well unless used in constructor...

Also in my version I had functions to return back a pointer to the KINETISK_SPI or KINESTL_SPI registers... (Also in case of K how big the Queue sizes are)
I find them useful for programs that which to work like the ILI9341_t3 library, but not sure how many might want it... Should probably take that part up later..

Again thanks!
 
Was doing some troubleshooting with the usb2.0 library and I got it working by changing buffered spi.transfers with essentially single byte transfers.(posted here https://forum.pjrc.com/threads/4441...ensyduino-1-36?p=144890&viewfull=1#post144890 ) When @jgeorge suggested that I download the latest SPI library and give it a try. So of course I did but on compile of the board_qc sketch I received the following error:
Code:
C:\Local Programs\arduino-1.8.2\hardware\teensy\avr\libraries\SPI\SPI.cpp:191:10: error: 'DMAMUX_SOURCE_SPI1' was not declared in this scope

  511, 0, DMAMUX_SOURCE_SPI1,

          ^

C:\Local Programs\arduino-1.8.2\hardware\teensy\avr\libraries\SPI\SPI.cpp:210:10: error: 'DMAMUX_SOURCE_SPI2' was not declared in this scope

  511, 0, DMAMUX_SOURCE_SPI2,

          ^

Just wanted to let you know on this thread as well just in case.

Mike
 
Last edited:
Probably needed updated core file kinetis...h. I think my version had a conditional define if it was not defined. Although if my async apis were not included, then probably not used, can probably, just change to 0...
 
Thanks Paul,

I was also wondering if it would make sense to add a new API that takes care of it for you... Something like:
static SPIClass *mapPinsToBuss(uint8_t sck, uint8_t mosi=0xff, uint8_t miso=0xff)
There could be multiple SPI modules per pin. I don't think this is the case for current Teensies (except for shared hardware chip selects), but there are MCUs that can remux all pins to anything.

Simply returning the first SPI module that supports the pin isn't a good choice. The SPI module most likely can only use a single set of pins but different SPI library users may end up wanting to use it with different pin sets.

So for the larger Arduino picture, there needs to be a way to select both pins and a specific SPI module.
 
@tni - I understand what you are saying. Which is why when we have code adapting to the ability for multiple SPI objects, I would suggest allowing them to pass in pointer or reference to desired SPI object. But it is nice to allow code to recover if they don't... For example in my Teensyview code I first try to verify if the passed in pins are valid on the SPI object that was passed in (Note I default to SPI in the header). If they are not valid, I try to then recover and see if there is an SPI buss that will work... So was wondering if we should make that easier and provide a helper function.

@mjs513 - Again a couple of possible fixes
a) Grab the Kinetis.h file from the beta...
b) Edit SPI.cpp and add some defines maybe around line 168 like:
Code:
#if defined(__MK64FX512__)  && !defined( DMAMUX_SOURCE_SPI1)
#define DMAMUX_SOURCE_SPI1		16
#define DMAMUX_SOURCE_SPI2		17
#endif

@Paul and @mjs513 - There is part of my Hardware objects here including this one that is only needed if we are going to include my ASYNC (DMA) transfer code. I will try to do a quick Delta (PR) to this to remove some of this (hopefully for just now)...
 
Please install 1.37-beta1 to resolve the missing symbols.

Let's leave the DMA hardware description in place. It only adds a few extra bytes of flash usage. Keeping it in the released SPI lib will make experimenting with DMA easier.

On the matter of representing hardware capability, I'd prefer to take a slow & deliberate approach. The future is likely to bring far more configurable hardware. In addition to more flexible pin assignment, some new chips are providing flexible switch matrix interconnect and even some programmable logic for internal event, interrupt & DMA signals. NXP/Freecale's new KV5 chips (which are meant for machine control and lack USB) are one example. I must admit, at this point I'm still having a hard time trying to imagine the incredible flexibility this will bring....

On async APIs, I'm concerned about offering interrupt context callbacks.
 
Thanks Paul,

I have an updated version of the Sparkfun_teensyview code that I have modified to use this verison. Had to remove (#ifdef) out code that uses the transfer buffer function (so instead does copy to temp locations and then output with the destructive buffer transfer). Also #ifdef out the Async support.

I now have tried it out on T3.5 on SPI/SPI1/SPI2... So that part is working! Will try out on at least one or two other boards as well...

Only testing using one display at a time. My multi-display test relies too much on ASYNC support... But may update to round robin

Also thinking of generating a version of the Adafruit_SSD1306 code to work with this as well. However I strongly dislike that they have you edit the the header file to define if you are using 32 line or 64 line displays. I understand why they did this, as to be able to define the right size buffer without using malloc... I may instead use two sub-classes for this....

As for the Async API - With callback on Interrupt... I see a couple of options here:
a) Don't support async... Obviously the easiest.
b) Don't have callback function, the user has to query to see if it is done or not.
c) Could do on interrupt as I have it... So far I did not run into issues, but...
d) Maybe could setup to have the yield function be able to do the callback...

Which reminds me - Should I try to implement a version of yield, where maybe we generate a bitmask of possible things to test. So We only test Serial1 if Serial1 has had begin called... And the default SerialEvent callback functions will unset this option... So then for those apps that have not implemented any serialEvent functions, hopefully soon the code will reduce to simply checking the bitmask and return...
 
Did you decide against C++14?

Yes and no...

Yes, for 1.37 I believe going from gnu++0x to gnu++14 is too big a jump. I want to have at least 2 stable releases using gnu++11. Or perhaps even 1 release will be enough, if there are no issues. If compatibility problems are found, we might need more than 2.

And no, gnu++14 has not been ruled out, only delayed. Perhaps I'm being a little too paranoid? But *any* compile error in any of the thousands of Arduino libraries, many of which are poorly written by authors not even enabling compiler warnings, is a huge problem for novice users.
 
I updated to 1.37 beta usind IDE 1.8.2 just now and ran it with Host Shield 2.0 without any modifications and it worked fine with no need for my crazy work around which is a good thing. Looks like the changes made to SPI cleared up the issues I was having with SPI and Host Shield 2.0.

Also, compiled for a sketch that I am using that uses vector and received the following error message:
Arduino: 1.8.2 (Windows 10), TD: 1.37-beta1, Board: "Teensy 3.5, Serial, 120 MHz, Faster, US English"

Code:
In file included from c:\local programs\arduino-1.8.2\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1\vector:60:0,

                 from C:\Users\CyberPalin\Documents\Arduino\TeensyOpenMV\TeensyOpenMV.ino:7:

c:\local programs\arduino-1.8.2\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1\bits\stl_algobase.h:243:56: error: macro "min" passed 3 arguments, but takes just 2

     min(const _Tp& __a, const _Tp& __b, _Compare __comp)

                                                        ^

c:\local programs\arduino-1.8.2\hardware\tools\arm\arm-none-eabi\include\c++\5.4.1\bits\stl_algobase.h:265:56: error: macro "max" passed 3 arguments, but takes just 2

     max(const _Tp& __a, const _Tp& __b, _Compare __comp)

                                                        ^

Line 7 is just the declaration #include <vector>. Compiled no issue with 1.36.

Also, ran the TeensyThreads test sketch and passed all tests.

Mike
 
@paul - not sure if I should move to different thread for SPI updates for this release?

But wondering: How best to know how many SPI Interfaces are supported by the current board?

Lots of old code probably does it by doing things like:
Test for T3.5/6 or LC to know that SPI1 is valid
Test for T3.5/6 for SPI2 valid...

I have in my version of SPI #define SPI_INTERFACES_COUNT
As that is what I believe many oof the other SPI implementations use it (Arduino SAMD, SAM) and those derived from them Adafruit...

Could do like you did in Wire library
#elif defined(__MK64FX512__)
#define WIRE_IMPLEMENT_WIRE
#define WIRE_IMPLEMENT_WIRE1
#define WIRE_IMPLEMENT_WIRE2

Which is sort of similar how we can also check for UARTS.

------------------------------------------------------------------------------------------------
Edit: Thought I would mention, that I have a version of the Sparkfun_Teensyview which is working with new version of SPI, where I can have multiple Teensyview or other SSD1306 displays working.
https://github.com/KurtE/SparkFun_TeensyView_Arduino_Library/tree/Multiple-SPI

Note: I hacked the library to define the SPI_INTERFACES_COUNT...

I have a version of my test program, that tries to define one of these displays for each SPI interface each board has. The first one is defined as 32 lines wide (Teensyview), the 2nd a 64 line version (Purchased a few from amazon), and 3rd another Teensyview...

So far this morning I have tested on:
T3.5 - All three busses
T3.2 - One buss
TLC - Both Busses.

Test program:
Code:
/******************************************************************************
TeensyView_Demo.ino
SFE_TeensyView Library Demo
Jim Lindblom @ SparkFun Electronics
Original Creation Date: October 27, 2014
Modified Febuary 2, 2017
This sketch uses the TeensyView library to draw a 3-D projected
cube, and rotate it along all three axes.
Development environment specifics:
Arduino IDE 1.6.12 w/ Teensyduino 1.31
Arduino IDE 1.8.1 w/ Teensyduino 1.35
TeensyView v1.0
This code is beerware; if you see me (or any other SparkFun employee) at thewa
local, and you've found our code helpful, please buy us a round!
Distributed as-is; no warranty is given.
******************************************************************************/
#include <SPI.h>
#include <TeensyView.h> // Include the SFE_TeensyView library
// /////////////////////////////////
// TeensyView Object Declaration //
// /////////////////////////////////
// #define TLC_SPI1
// #define T36_SPI1
// #define T36_SPI2
// #define DEFAULT_PINS

#ifdef DEFAULT_PINS
#define PIN_RESET 15
#define PIN_DC 5
#define PIN_CS 10
#define PIN_SCK 13
#define PIN_MOSI 11
#endif

#ifdef TLC_SPI1
#define PIN_RESET 15
#define PIN_SCK 20
#define PIN_MOSI 21
#define PIN_DC 4
#define PIN_CS 3
#endif

#ifdef T36_SPI1
#define PIN_RESET 15
#define PIN_SCK 20
#define PIN_MOSI 21
#define PIN_DC 31
#define PIN_CS 32
#endif

#ifdef T36_SPI2
#define PIN_RESET 15
#define PIN_SCK 53
#define PIN_MOSI 52
#define PIN_DC 55
#define PIN_CS 51
#endif

// Kurt's setup

#ifndef PIN_SCK

#if defined(KINETISK)
#define PIN_RESET 15
#define PIN_SCK 13
#define PIN_MOSI 11
#define PIN_DC 21
#define PIN_CS 20
// Setup 2nd one SPI1
#define PIN_RESET1 16
#define PIN_SCK1 32
#define PIN_MOSI1 0
#define PIN_DC1 31
#define PIN_CS1 30

#elif defined(KINETISL)  // Teensy LC
// For multiple need to change CS to not 20 as only valid sck1 on lc
#define PIN_RESET 15
#define PIN_SCK 13
#define PIN_MOSI 11
#define PIN_DC 21
#define PIN_CS 22
// #undef SPI_INTERFACES_COUNT
// #define SPI_INTERFACES_COUNT 1
#define PIN_RESET1 16
#define PIN_SCK1 20
#define PIN_MOSI1 0
#define PIN_DC1 6
#define PIN_CS1 7
#else // AVR... T2 SS(0), SCK(1), MOSI(2), MISO(3)
#define PIN_RESET 5
#define PIN_SCK 13
#define PIN_MOSI 11
#define PIN_DC 4
#define PIN_CS 0
#endif

// Pins on connector on Beta T3.6 board (3.3, GND)(48, 47)(57 56) (51 52) (53 55)
#define PIN_RESET2 48
// #define PIN_MISO2 51
#define PIN_MOSI2 52
#define PIN_SCK2 53
#define PIN_DC2 55
#define PIN_CS2 56
#endif

TeensyView32 oled(PIN_RESET, PIN_DC, PIN_CS, PIN_SCK, PIN_MOSI);

#if SPI_INTERFACES_COUNT > 1
TeensyView64 oled1(PIN_RESET1, PIN_DC1, PIN_CS1, PIN_SCK1, PIN_MOSI1);

    #if SPI_INTERFACES_COUNT > 2
TeensyView32 oled2(PIN_RESET2, PIN_DC2, PIN_CS2, PIN_SCK2, PIN_MOSI2);
    #endif

#endif

#ifdef SPI_HAS_TRANSFER_ASYNC
#define DO_ASYNC true
#define DISPLAYFUNC displayAsync
#else
#define DO_ASYNC false
#define DISPLAYFUNC display
#endif


TeensyView * oleds[] =
{
#if 0
    & oled,
    & oled1
#else  
    & oled

#if SPI_INTERFACES_COUNT > 1
    , & oled1

    #if SPI_INTERFACES_COUNT > 2
    , & oled2
    #endif
#endif
#endif

};

uint8_t oled_which_test[] =
{
    0, 0, 0
};

uint16_t test_iterations_left[] =
{
    0xffff, 0xffff, 0xffff
};

uint32_t last_test_start_time[] =
{
    0, 0, 0
};

uint32_t next_test_start_time[] =
{
    0, 0, 0
};

extern void testRects(TeensyView * _oled, bool draw_async, uint16_t & iterations_left);
extern void testCircles(TeensyView * _oled, bool draw_async, uint16_t & iterations_left);
extern void TestpixelsAsync(TeensyView * _oled, uint16_t & iterations_left);
extern void TestFillRects(TeensyView * _oled, uint16_t & iterations_left);
extern void testdrawline(TeensyView * _oled, uint16_t & iterations_left, uint32_t & next_test_start_time);
extern void testscrolltext(TeensyView * _oled, uint16_t & iterations_left, uint32_t & next_test_start_time);
void setup()
{
    pinMode(2, OUTPUT);
    digitalWrite(2, LOW);
    pinMode(3, OUTPUT);
    digitalWrite(3, LOW);
    while (!Serial && millis() < 3000);
    Serial.begin(38400);
    oled.begin(); // Initialize the OLED
    oled.display(); // Display what's in the buffer (splashscreen)

#if SPI_INTERFACES_COUNT > 1
    oled1.begin(); // Initialize the OLED
    oled1.display(); // Display what's in the buffer (splashscreen)''
    Serial.println("oled1 displayed");
#endif

#if SPI_INTERFACES_COUNT > 2
    oled2.begin(); // Initialize the OLED
    oled2.display(); // Display what's in the buffer (splashscreen)''
    Serial.println("oled2 displayed");
#endif

    delay(1000); // Delay 1000 ms
    oled.clear(HARDWARE_MEM); // Clear the buffer.

#if SPI_INTERFACES_COUNT > 1
    oled1.clear(HARDWARE_MEM); // Clear the buffer.
#endif

#if SPI_INTERFACES_COUNT > 2
    oled2.clear(HARDWARE_MEM);
#endif
#ifdef A1
    randomSeed(analogRead(A0) + analogRead(A1));
#else
   randomSeed(analogRead(A0) + (analogRead(A0)<<1));
#endif    
}

void loop()
{
    // Lets see which of our displays is ready to display something different
    for (uint8_t i = 0; i < sizeof(oleds) /sizeof(oleds[0]); i++)
    {
#ifdef SPI_HAS_TRANSFER_ASYNC
        if ((millis() > next_test_start_time[i]) && !oleds[i] -> displayAsyncActive())
#else
        if ((millis() > next_test_start_time[i]))
#endif
        {
            last_test_start_time[i] = millis();
            switch (oled_which_test[i])
            {
                case 0:
                    testRects(oleds[i], DO_ASYNC, test_iterations_left[i]);
                    break;
                case 1:
                    testRects(oleds[i], DO_ASYNC, test_iterations_left[i]);
                    break;
                case 2:
                    TestpixelsAsync(oleds[i], test_iterations_left[i]);
                    break;
                case 3:
                    TestFillRects(oleds[i], test_iterations_left[i]);
                    break;
                case 4:
                    testdrawline(oleds[i], test_iterations_left[i], next_test_start_time[i]);
                    break;
                case 5:
                    testscrolltext(oleds[i], test_iterations_left[i], next_test_start_time[i]);
                    break;
            }
            if (test_iterations_left[i] == 0)
            {
                oled_which_test[i] ++;
                if (oled_which_test[i] > 5)
                    oled_which_test[i] = 0;
                test_iterations_left[i] = 0xffff; // mark it special for first call
                next_test_start_time[i] = millis() + 100;
            }
        }
        else
            if ((millis() - last_test_start_time[i]) > 2500)
            {
                Serial.printf("Oled %d hung test: %d iter: %d\n ", i, oled_which_test[i], test_iterations_left[i]);
                printDebugInfo(oleds[i]);
                last_test_start_time[i] = millis();
            }
    }
}

void printDebugInfo(TeensyView * _oled)
{

#ifdef KINETISK

  #ifdef SPI_DEBUG_ASYNC_T3X
    extern void dumpDMA_TCD(const char * psz, DMABaseClass * dmabc);
    dumpDMA_TCD("TX:", _oled -> _spi -> _dmaTX);
    dumpDMA_TCD("RX:", _oled -> _spi -> _dmaRX);
  #endif  
#else

        #ifdef SPI_DEBUG_ASYNC_LC
    extern void dumpDMA_CFG(const char * sz, DMABaseClass * dmabc);
    dumpDMA_CFG("TX:", _oled -> _spi -> _dmaTX);
    dumpDMA_CFG("RX:", _oled -> _spi -> _dmaRX);
        #endif

#endif

}

void testRects(TeensyView * _oled, bool draw_async, uint16_t & iterations_left)
{
    int n, i, i2;
    int cx = _oled -> getLCDWidth() / 2;
    int cy = _oled -> getLCDHeight() / 2;
    _oled -> clear(PAGE);
    n = min(_oled -> getLCDWidth(), _oled -> getLCDHeight());
    for (i = 2; i < n; i += 6)
    {
        i2 = i / 2;
        _oled -> rect(cx - i2, cy - i2, i, i);
    }
    if (draw_async)
    {
        _oled -> DISPLAYFUNC();
    }
    else
    {
        _oled -> display();
    }
    iterations_left = 0;
}

void testCircles(TeensyView * _oled, bool draw_async, uint16_t & iterations_left)
{
    uint16_t radius = 10;
    int x, y, r2 = radius * 2,
    w = _oled -> getLCDWidth() + radius,
    h = _oled -> getLCDHeight() + radius;
    _oled -> clear(PAGE);
    for (x = 0; x < w; x += r2)
    {
        for (y = 0; y < h; y += r2)
        {
            _oled -> circle(x, y, radius);
        }
    }
    if (draw_async)
    {
        _oled -> DISPLAYFUNC();
    }
    else
    {
        _oled -> display();
    }
    iterations_left = 0;
}

void TestpixelsAsync(TeensyView * _oled, uint16_t & iterations_left)
{
    if (iterations_left == 0xffff)
    {
        _oled -> clear(PAGE);
        iterations_left = 1024;
    }
    _oled -> pixel(random(_oled -> getLCDWidth()), random(_oled -> getLCDHeight()));
    _oled -> DISPLAYFUNC();
    iterations_left--;
}

void TestFillRects(TeensyView * _oled, uint16_t & iterations_left)
{
    if (iterations_left == 0xffff)
    {
        _oled -> clear(PAGE);
        iterations_left = 0; // Not really, but makes it simple as we will update
    }
    _oled -> rectFill(iterations_left, iterations_left,
    _oled -> getLCDWidth() - iterations_left * 2, _oled -> getLCDHeight() - iterations_left * 2,(iterations_left & 1)? 0:1, NORM);
    _oled -> DISPLAYFUNC();
    iterations_left += 3;
    if (iterations_left >= _oled -> getLCDHeight() /2)
    {
        iterations_left = 0; // we are done.
    }
}

void testdrawline(TeensyView * _oled, uint16_t & iterations_left, uint32_t & next_test_start_time)
{
    // Serial.printf("testDrawline %x %x\n", _oled, iterations_left);
    if (iterations_left == 0xffff)
    {
        _oled -> clear(PAGE);
        iterations_left = 0; // Not really, but makes it simple as we will update
    }
    uint8_t line_test = iterations_left >> 8;
    uint8_t i = iterations_left & 0xff;
    switch (line_test)
    {
        case 0:
            _oled -> line(0, 0, i, _oled -> getLCDHeight() - 1);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDWidth())
            {
                i = 0;
                line_test++;
            }
            break;
        case 1:
            _oled -> line(0, 0, _oled -> getLCDWidth() - 1, i);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDHeight())
            {
                i = 0;
                line_test++;
                next_test_start_time = millis() + 250;
            }
        case 2:
            if (i == 0)
            {
                _oled -> clear(PAGE);
            }
            _oled -> line(0, _oled -> getLCDHeight() - 1, i, 0);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDWidth())
            {
                i = 0;
                line_test++;
            }
            break;
        case 3:
            _oled -> line(0, _oled -> getLCDHeight() - 1, _oled -> getLCDWidth() - 1, i);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDHeight())
            {
                i = 0;
                line_test++;
                next_test_start_time = millis() + 250;
            }
            break;
        case 4:
            if (i == 0)
            {
                _oled -> clear(PAGE);
            }
            _oled -> line(_oled -> getLCDWidth() - 1, _oled -> getLCDHeight() - 1, i, 0);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDWidth())
            {
                i = 0;
                line_test++;
            }
            break;
        case 5:
            _oled -> line(_oled -> getLCDWidth() - 1, _oled -> getLCDHeight() - 1, 0, i);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDHeight())
            {
                i = 0;
                line_test++;
                next_test_start_time = millis() + 250;
            }
            break;
        case 6:
            if (i == 0)
            {
                _oled -> clear(PAGE);
            }
            _oled -> line(_oled -> getLCDWidth() - 1, 0, 0, i);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDHeight())
            {
                i = 0;
                line_test++;
            }
            break;
        case 7:
            _oled -> line(_oled -> getLCDWidth() - 1, 0, i, _oled -> getLCDHeight() - 1);
            _oled -> DISPLAYFUNC();
            i += 4;
            if (i >= _oled -> getLCDWidth())
            {
                i = 0;
                line_test = 0; // Say we are done
            }
    }
    iterations_left = (line_test << 8) | i;
}

void testscrolltext(TeensyView * _oled, uint16_t & iterations_left, uint32_t & next_test_start_time)
{
    if (iterations_left == 0xffff)
    {
        int middleX = _oled -> getLCDWidth() / 2;
        int middleY = _oled -> getLCDHeight() / 2;
        _oled -> clear(PAGE);
        _oled -> setFontType(1);
        // Try to set the cursor in the middle of the screen
        _oled -> setCursor(middleX - (_oled -> getFontWidth() * (6 / 2)),
        middleY - (_oled -> getFontWidth() / 2));
        // Print the title:
        _oled -> print("Scroll");
        _oled -> DISPLAYFUNC();
        iterations_left = 1; // Not really, but makes it simple as we will update
        return;
    }
    switch (iterations_left)
    {
        case 1:
            _oled -> scrollRight(0x00, 0x0f, true);
            next_test_start_time = millis() + 2000;
            break;
        case 2:
            _oled -> scrollStop();
            next_test_start_time = millis() + 1000;
            break;
        case 3:
            _oled -> scrollLeft(0x00, 0x0f, true);
            next_test_start_time = millis() + 2000;
            break;
        case 4:
            _oled -> scrollStop();
            next_test_start_time = millis() + 1000;
            break;
        case 5:
            _oled -> scrollVertRight(0x00, 0x07, true);
            next_test_start_time = millis() + 2000;
            break;
        case 6:
            _oled -> scrollVertLeft(0x00, 0x07, true);
            next_test_start_time = millis() + 2000;
            break;
        case 7:
            _oled -> scrollStop();
            next_test_start_time = millis() + 50;
            break;
    }
    if (++iterations_left > 7)
        iterations_left = 0;
}
Still need to test on T3.6, but my setup was pilfered to play with ILI9341 displays
Update: Tested on T3.6 with first two display SPI and SPI1 and SPI2
 
Last edited:
Not sure if anyone is interested, but I did hack up a version of the Adafruit_SSD1306 to also work with the new SPI code.
Which is up on my github in a new branch: https://github.com/KurtE/Adafruit_SSD1306/tree/Multi-SPI

The code allows me to pass in a reference to the appropriate SPI object on the constructor...
Note: This is off of my version that also allowed me to pass in reference to Wire object if you have one of the I2C versions.

Then I did some semi-random changes, for my own purposes
a) Moved the buffer into the object instead of global, as to probably allow multiple ones.
b) Made two sub-classes for 32 line and 64 line versions (I hated the editing the header file to change especially if you might have multiple...
c) Currently the main class defaults to the setting from before, there is an optional parameter on constructor to allow you to choose. But in this main class it uses malloc to allocate the object, but the two sub-classes have buffer defined within the actual class...
d) The update screen function call the spi.transfer(x, cnt)... to speed up transfer... Currently has to do copy to temporary buffer... So only do 32 bytes per call...

Again not sure if anyone wishes to also play with this, but here is test program:
Code:
/*********************************************************************
This is an example for our Monochrome OLEDs based on SSD1306 drivers

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/category/63_98

This example is for a 128x32 size display using SPI to communicate
4 or 5 pins are required to interface

Adafruit invests time and resources providing this open source code, 
please support Adafruit and open-source hardware by purchasing 
products from Adafruit!

Written by Limor Fried/Ladyada  for Adafruit Industries.  
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//#define TEST_SPI
//#define TEST_SPI1
#define TEST_SPI2

#ifdef TEST_SPI
// If using software SPI (the default case):
#define OLED_MOSI  11
#define OLED_CLK   13
#define OLED_DC    21
#define OLED_CS    20
#define OLED_RESET 15
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
#endif

#ifdef TEST_SPI1
// If using software SPI (the default case):
#define OLED_MOSI  0
#define OLED_CLK   32
#define OLED_DC    31
#define OLED_CS    30
#define OLED_RESET 16
Adafruit_SSD1306_64 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS, SPI1);
#endif


#ifdef TEST_SPI2
// If using software SPI (the default case):
#define OLED_MOSI  52
#define OLED_CLK   53
#define OLED_DC    55
#define OLED_CS    56
#define OLED_RESET 48
Adafruit_SSD1306_32 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS, SPI2);
#endif

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {      
  while (!Serial && (millis() < 2000)) ;          
  Serial.begin(9600);
  
  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  // init done
  
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();

  // draw a single pixel
  display.drawPixel(10, 10, WHITE);
  // Show the display buffer on the hardware.
  // NOTE: You _must_ call display after making any drawing commands
  // to make them visible on the display hardware!
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw many lines
  testdrawline();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw rectangles
  testdrawrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw multiple rectangles
  testfillrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw mulitple circles
  testdrawcircle();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw a white circle, 10 pixel radius
  display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawroundrect();
  delay(2000);
  display.clearDisplay();

  testfillroundrect();
  delay(2000);
  display.clearDisplay();

  testdrawtriangle();
  delay(2000);
  display.clearDisplay();
   
  testfilltriangle();
  delay(2000);
  display.clearDisplay();

  // draw the first ~12 characters in the font
  testdrawchar();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw scrolling text
  testscrolltext();
  delay(2000);
  display.clearDisplay();

  // text display tests
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Hello, world!");
  display.setTextColor(BLACK, WHITE); // 'inverted' text
  display.println(3.141592);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print("0x"); display.println(0xDEADBEEF, HEX);
  display.display();
  delay(2000);
  display.clearDisplay();

  // miniature bitmap display
  display.drawBitmap(30, 16,  logo16_glcd_bmp, 16, 16, 1);
  display.display();

  // invert the display
  display.invertDisplay(true);
  delay(1000); 
  display.invertDisplay(false);
  delay(1000); 
  display.clearDisplay();

  // draw a bitmap icon and 'animate' movement
  testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
}


void loop() {
  
}


void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  uint8_t icons[NUMFLAKES][3];
 
  // initialize
  for (uint8_t f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS] = random(display.width());
    icons[f][YPOS] = 0;
    icons[f][DELTAY] = random(5) + 1;
    
    Serial.print("x: ");
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(" y: ");
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(" dy: ");
    Serial.println(icons[f][DELTAY], DEC);
  }

  while (1) {
    // draw each icon
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
    }
    display.display();
    delay(200);
    
    // then erase it + move it
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
      // move it
      icons[f][YPOS] += icons[f][DELTAY];
      // if its gone, reinit
      if (icons[f][YPOS] > display.height()) {
        icons[f][XPOS] = random(display.width());
        icons[f][YPOS] = 0;
        icons[f][DELTAY] = random(5) + 1;
      }
    }
   }
}


void testdrawchar(void) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

  for (uint8_t i=0; i < 168; i++) {
    if (i == '\n') continue;
    display.write(i);
    if ((i > 0) && (i % 21 == 0))
      display.println();
  }    
  display.display();
}

void testdrawcircle(void) {
  for (int16_t i=0; i<display.height(); i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
    display.display();
  }
}

void testfillrect(void) {
  uint8_t color = 1;
  for (int16_t i=0; i<display.height()/2; i+=3) {
    // alternate colors
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
    display.display();
    color++;
  }
}

void testdrawtriangle(void) {
  for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, WHITE);
    display.display();
  }
}

void testfilltriangle(void) {
  uint8_t color = WHITE;
  for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
    display.fillTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, WHITE);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}

void testdrawroundrect(void) {
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE);
    display.display();
  }
}

void testfillroundrect(void) {
  uint8_t color = WHITE;
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}
   
void testdrawrect(void) {
  for (int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
    display.display();
  }
}

void testdrawline() {  
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, WHITE);
    display.display();
  }
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, WHITE);
    display.display();
  }
  delay(250);
  
  display.clearDisplay();
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, WHITE);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
    display.display();
  }
  delay(250);
  
  display.clearDisplay();
  for (int16_t i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
    display.display();
  }
  delay(250);

  display.clearDisplay();
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, WHITE);
    display.display();
  }
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE); 
    display.display();
  }
  delay(250);
}

void testscrolltext(void) {
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  display.println("scroll");
  display.display();
 
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);    
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
}
 
Arduino finally released 1.8.3. I'm updating Teensyduino now.

Should have 1.37-beta2 available within a couple hours.
 
IDE 1.8.3 release notes don't look real significant WRT to Teensy? Any surprises? I just finished downloads of 1.8.3 and TD_1.37b2 to install later.

ARDUINO 1.8.3 2017.05.31

(bugfix service release)

[ide]
* Fixed RESOURCE_NAME in install.sh script
* Serial Monitor: added "Clear output" button. Thanks @MichaelSy
* added options in preferences.txt for: custom title, comment/uncomment shortcut, always show file extensions. Thanks @MichaelSy
* added options in preferences.txt to enable/disable typing assistance (auto close brace, auto indent)
* Enabling "Use external editor" option now requires to save all sketches.

[core]
* AVR: added availableForWrite() method in generic Stream class. Thanks @eric-wieser
* AVR: moved flush() method up in the class hierarchy from Stream to Print class. Thanks @matthijskooijman

[other]
* Update Wifi101 Firmware Updater plugin
 
I have installed on Windows and have done a few compiles.

The one thing I notice is there is a new button in the TeensyMonitor <Clear Output>
Which currently does not look like it does anything with Teensy.
 
The ZIP version of V1.8.3 works OK but Teensyduino and TyTools won't install. The former won't enable the Next button after the folder is selected. The later says the folder is not valid. What seems to be the problem, perhaps something missing that's expected?

PS
Both programs install correctly in V1.8.2.
 
Last edited:
Status
Not open for further replies.
Back
Top