Teensyduino 1.46 Released

Status
Not open for further replies.

Paul

Administrator
Staff member
Teensyduino 1.46 has been released.

https://www.pjrc.com/teensy/td_download.html

The main new feature are supports for Arduino 1.8.9 and improved startup on Teensy 3.6 when used with a "soft start" external power supply.


The changes since 1.46-beta10 are:

  • Update library Adafruit_GFX
  • Remove outdated libs: Adafruit_ILI9340, Adafruit_ILI9341, Adafruit_SSD1306, Adafruit_ST7735
  • Audio: Workaround for WM8731's poor I2C communication
  • Encoder: add atomic readAndReset() function (humanoid2050)
  • Use "-fpermissive" to treat some C++ errors as only warnings, as Arduino Uno does
 
Win 10 downloaded TD_1.46 for IDE 1.8.9.

Installed and ran properly to upload Blink to T_3.5 and see millis() on SerMon!
 
The changes since 1.46-beta10 are:

Update library Adafruit_GFX
Remove outdated libs: Adafruit_ILI9340, Adafruit_ILI9341, Adafruit_SSD1306, Adafruit_ST7735

Trouble from these changes … this post pjrc.com/threads/54711-Teensy-4-0-First-Beta-Test

What is the replacement for SSD1306?

Trying to compile on t4-2 prior working examples were using that, and the changes to Adafruit_GFX break that

{Builds and runs pulling old copies of those libs to sketchbook}
 
Last edited:
Hello!
Is this the correct branch? If this is not the case, transfer it to the desired branch.
Sorry for my English. I use the translator.
I installed Arduino 1.89 and Teensyduino 1.46 on another Arduino laptop
After that, the example stopped compiling, I found it on this site, I do not remember where, but earlier this example seemed to work. Here is the compiler message:

TestADC4CanalDMA:26: error: 'DMAMUX_SOURCE_FTM3_CH3' was not declared in this scope
constexpr std::array<int, 4> dma_triggers = { DMAMUX_SOURCE_FTM3_CH0, DMAMUX_SOURCE_FTM3_CH1, DMAMUX_SOURCE_FTM3_CH2, DMAMUX_SOURCE_FTM3_CH3 };
'DMAMUX_SOURCE_FTM3_CH0' was not declared in this scope

I use Tennsy3.2, if Tennsy3.6- no error
I'm desperate. I start a big project where I need to collect data from 4 ADCs, then I need to process, and in the main cycle I need to change the coefficient in order for one of the ADCs to be translated into a DAC by multiplying it by a coefficient.
I need to learn how to do it, but the example is not compiled.

Code:
#include <ADC.h>
#include <array>
#include <DMAChannel.h>

// connect out_pins to adc pins, PWM output on out pins will be measured.

const uint8_t adc0_pin0 = A4;  //  ADC0
const uint8_t adc0_pin1 = A5;  //  ADC0
const uint8_t adc1_pin0 = A2;  //  ADC1
const uint8_t adc1_pin1 = A3;  //  ADC1

constexpr std::array<uint8_t, 4> adc_pins = { adc0_pin0, adc0_pin1, adc1_pin0, adc1_pin1 };
//constexpr std::array<uint8_t, 4> out_pins = { 5, 6, 9, 10 };

ADC adc;
std::array<ADC_Module*, 2> adc_modules;
static_assert(ADC_NUM_ADCS == 2, "Two ADCs expected.");

auto& serial = Serial;

const size_t buffer_size = 1000;
std::array<std::array<volatile uint16_t, buffer_size>,  4> buffers;

std::array<volatile uint32_t*, 4> adc_result_registers = { &ADC0_RA, &ADC0_RB, &ADC1_RA, &ADC1_RB };
std::array<DMAChannel, 4> dma_channels;
constexpr std::array<int, 4> dma_triggers = { DMAMUX_SOURCE_FTM3_CH0, DMAMUX_SOURCE_FTM3_CH1, DMAMUX_SOURCE_FTM3_CH2, DMAMUX_SOURCE_FTM3_CH3 };

// CMSIS PDB
#define PDB_C1_EN_MASK                           0xFFu
#define PDB_C1_EN_SHIFT                          0
#define PDB_C1_EN(x)                             (((uint32_t)(((uint32_t)(x))<<PDB_C1_EN_SHIFT))&PDB_C1_EN_MASK)
#define PDB_C1_TOS_MASK                          0xFF00u
#define PDB_C1_TOS_SHIFT                         8
#define PDB_C1_TOS(x)                            (((uint32_t)(((uint32_t)(x))<<PDB_C1_TOS_SHIFT))&PDB_C1_TOS_MASK)
#define PDB_C1_BB_MASK                           0xFF0000u
#define PDB_C1_BB_SHIFT                          16
#define PDB_C1_BB(x)                             (((uint32_t)(((uint32_t)(x))<<PDB_C1_BB_SHIFT))&PDB_C1_BB_MASK)

size_t bufferWriteIndex(size_t channel) {
    uintptr_t buffer_start = uintptr_t(buffers[channel].data());
    uintptr_t dma_pos = uintptr_t(dma_channels[channel].destinationAddress());
    return (dma_pos - buffer_start) / sizeof(uint16_t);
}

void setup() 
{
    for(size_t i = 0; i < adc_modules.size(); i++) adc_modules[i] = adc.adc[i];
    for(auto pin : adc_pins) pinMode(pin, INPUT);

    serial.begin(9600);
    delay(1000);
    serial.println("Starting");

    for(auto adc_module : adc_modules) 
    {
        adc_module->setAveraging(1);
        adc_module->setResolution(12);
        adc_module->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED);
        adc_module->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED);
    }
    
    // perform ADC input mux setup; the ADC library doesn't handle the B-set of registers
    // so we copy the config over
    adc.adc0->analogRead(adc0_pin1);
    ADC0_SC1B = ADC0_SC1A;
    adc.adc0->analogRead(adc0_pin0);

    adc.adc1->analogRead(adc1_pin1);
    ADC1_SC1B = ADC1_SC1A;
    adc.adc1->analogRead(adc1_pin0);

 //   if(adc.adc0->fail_flag || adc.adc1->fail_flag) 
 //   {
 //       serial.printf("ADC error, ADC0: %x ADC1: %x\n", adc.adc0->fail_flag, adc.adc1->fail_flag);
//    }

    for(auto adc_module : adc_modules) adc_module->stopPDB();
    // conversion will be triggered by PDB
    for(auto adc_module : adc_modules) adc_module->setHardwareTrigger();

    // enable PDB clock
    SIM_SCGC6 |= SIM_SCGC6_PDB;

    // Sample at 100'000 Hz
    constexpr uint32_t trigger_frequency = 100000;
    constexpr uint32_t mod = (F_BUS / trigger_frequency);
    static_assert(mod <= 0x10000, "Prescaler required.");

    // The K66 ADC conversion complete DMA triggering is completely broken for multi-channel conversions.
    // PDB DMA triggering doesn't work correctly, DMA channel linking for FTM-triggered DMA transfers
    // is also broken and doesn't correctly deassert COCO.
    // Thus, 4 timer channels are used to trigger DMA. The FTM counter at half point triggers DMA
    // for ADC A channel, the counter at MOD triggers DMA for ADC channel B.

    FTM3_SC = 0;
    FTM3_CNT = 0;
    FTM3_MOD = uint16_t(mod - 1);

    // output compare mode, trigger DMA when counter reaches FTM3_CxV
    uint32_t ftm_channel_config = FTM_CSC_CHIE | FTM_CSC_DMA | FTM_CSC_MSA | FTM_CSC_ELSA;
    FTM3_C0SC = ftm_channel_config;
    FTM3_C1SC = ftm_channel_config;
    FTM3_C2SC = ftm_channel_config;
    FTM3_C3SC = ftm_channel_config;

    FTM3_C0V = uint16_t(mod / 2 - 1);      // DMA trigger for ADC0 A
    FTM3_C1V = FTM3_MOD;                   // DMA trigger for ADC0 B
    FTM3_C2V = uint16_t(mod / 2 - 1);      // DMA trigger for ADC1 A
    FTM3_C3V = FTM3_MOD;                   // DMA trigger for ADC1 B
    FTM3_EXTTRIG = FTM_EXTTRIG_INITTRIGEN; // external trigger at counter overflow --> trigger PDB

    PDB0_MOD = (uint16_t)(mod-1);

    uint32_t pdb_ch_config = PDB_C1_EN (0b11) | // enable ADC A and B channel
                             PDB_C1_TOS(0b11) | // enables the channel delay
                             PDB_C1_BB (0b00);  // back-to-back trigger disabled
    PDB0_CH0C1 = pdb_ch_config; // ADC 0
    PDB0_CH1C1 = pdb_ch_config; // ADC 1

    // ADC0 A and ADC1 A conversions are triggered immediately, ADC0 B and ADC1 B at the half point
    PDB0_CH0DLY0 = 0;
    PDB0_CH0DLY1 = uint16_t(mod / 2 - 1);
    PDB0_CH1DLY0 = 0;
    PDB0_CH1DLY1 = uint16_t(mod / 2 - 1);

    const uint32_t pdb_base_conf = PDB_SC_TRGSEL(0b1011) |               // triggered by FTM3
                                   PDB_SC_PDBEN |                        // enable
                                   PDB_SC_PRESCALER(0) | PDB_SC_MULT(0); // count at F_BUS
                                   
    // sync buffered registers
    PDB0_SC = pdb_base_conf | PDB_SC_LDOK;
    
    for(size_t i = 0; i < 4; i++) {
        DMAChannel& dma = dma_channels[i];
        dma.source(*(uint16_t*) adc_result_registers[i]);
        dma.destinationBuffer(buffers[i].data(), sizeof(buffers[i]));
        dma.triggerAtHardwareEvent(dma_triggers[i]);
        dma.enable();
    }

    FTM3_SC = (FTM_SC_CLKS(1) | FTM_SC_PS(0));  // start FTM, run at F_BUS 

    // PWM output on out pins for testing purposes.
 //   for(auto out_pin : out_pins) analogWriteFrequency(out_pin, 5000);
 //   for(size_t i = 0; i < out_pins.size(); i++) analogWrite(out_pins[i], (i + 1) * 50);

    delay(500);
}

void loop() {
    // print buffer right after the first 100 elements have been updated
    while(bufferWriteIndex(1) >= 100) ;
    while(bufferWriteIndex(1) < 100) ;

    // Print first measurements in buffer.
    for(size_t i = 0; i < 100; i++) 
    {
        serial.print( buffers[0][i]);serial.print( " ");
        serial.print( buffers[1][i]*2);serial.print( " ");
        serial.print( buffers[2][i]*3);serial.print( " ");
        serial.print( buffers[3][i]*4);serial.print( " ");
        serial.println();
    }
    

    delay(500);
}
 
Last edited:
I installed Arduino 1.89 and Teensyduino 1.46 on another Arduino laptop
After that, the example stopped compiling

Maybe you have the wrong board selected in the Tools > Boards menu?

This code appears to be designed for Teensy 3.5 or 3.6. I copied it into Arduino. I get exactly the same error if I compile for Teensy 3.2. It does compile without error if I select Teensy 3.6.
 
I also noticed, for t3.6, if I uncomment lines 72-75, I get an error:
TestADC4CanalDMA:72: error: no match for 'operator||' (operand types are 'volatile ADC_Error::ADC_ERROR' and 'volatile ADC_Error::ADC_ERROR')
if(adc.adc0->fail_flag || adc.adc1->fail_flag)


C:\Users\LukashukVL\Documents\Arduino7\TestADC4CanalDMA\TestADC4CanalDMA.ino:72:28: note: candidate: operator||(bool, bool) <built-in>

C:\Users\LukashukVL\Documents\Arduino7\TestADC4CanalDMA\TestADC4CanalDMA.ino:72:28: note: no known conversion for argument 2 from 'volatile ADC_Error::ADC_ERROR' to 'bool'

no match for 'operator||' (operand types are 'volatile ADC_Error::ADC_ERROR' and 'volatile ADC_Error::ADC_ERROR')
 
But what should I do if I need for t3/2?

If you did not write this code, and if you are not very familiar with how it works, buying Teensy 3.6 is the only realistic solution.

This code is very advanced. It directly accesses hardware features which do not exist in Teensy 3.2. Only an expert programmer who is very familiar with the low-level hardware features and who understands very advanced topics like timers to trigger DMA transfers could successfully modify this code for different hardware. The techniques this code uses are beyond the reach of almost all normal programmers.

The code is too advanced for most people to edit. Simply buying the intended hardware is the only viable solution if you do not have very advanced programming skills.
 
I have t3.2 and t3.6, my task is to do it on 3.2, but for 3.6 if you remove comments from lines 72-75, the compiler reports an error
 
I have t3.2 and t3.6, my task is to do it on 3.2

You will need to study the reference manuals closely.

https://www.pjrc.com/teensy/datasheets.html

Teensy 3.2 does not have a FTM3 timer, but the FTM0 is similar. As a very first step, you will need to convert all FTM3 to FTM0.

I'm sorry, I can not help any further. But I will say again, this is a very difficult task which requires deep knowledge to edit source code which is so advanced. You really might consider whether that effort is really worthwhile, only to save a small amount of money on the cheaper hardware.
 
Thank! forgive my persistence. I try 3.6,
if (adc.adc0-> fail_flag || adc.adc1-> fail_flag)
** this is line 72-75 - gives an error
 
Paul! Now it is compiled for p3.6 and p3.2 but does not work. works for 3.6 when FTM3. Thank! I will smoke the documentation.
 
I was able to get this to successfully install on a Beaglebone Black Wireless running Debian Stretch, and eventually managed to flash a board with it.
The Arduino IDE shows all the familiar sane Teensy options in the menus.

It looks like an attempt to upload to the board hangs on something. The Teensy loader window pops up but remains empty, and if you wait long enough the Arduino IDE eventually gives up on the process.
If you press the button on the Teensy board it seems to go ahead and complete the process with the Teensy loader window filling in with the expected graphic and the board accepting the firmware.

On subsequent upload attempts when you push the button on the board the Arduino environment returns:

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'send': was expecting ('true', 'false' or 'null')
at [Source: (ProcessPipeInputStream); line: 361, column: 6]

along with a bit more stuff. I can provide a verbose dump file of the compile and upload process if that would be useful for fault finding.
 
The helptext for the ILI9341_t3 library in the installer still directs people to use the Adafruit_ILI9341 library for other boards, which was removed in this release. Should perhaps be suggesting Adafruit_GFX here now?
 
Teensyduino 1.46 installed is preventing Arduino 1.89 to start.
I am running the latest/next Mac OS 10.15 Catalina. I can Arduino , but when i try to install the teensy it loads, installs but then arduino starts, then closes. I have tried installing teensyduino without any libraries same issue.
This latest os requires more permissions, i have given arduino full file access?
any idea please?
 
Teensyduino 1.46 installed is preventing Arduino 1.89 to start.
I am running the latest/next Mac OS 10.15 Catalina. I can Arduino , but when i try to install the teensy it loads, installs but then arduino starts, then closes. I have tried installing teensyduino without any libraries same issue.
This latest os requires more permissions, i have given arduino full file access?
any idea please?

fixed in latest osx update!
 
Status
Not open for further replies.
Back
Top