Pinout diagrams with port labels

Status
Not open for further replies.

FFMan

Active member
New to Teensy but liking the speed :)

I want to drive a AD7302 ADC in the most efficient way possible. It has a parallel 8 bit input and for efficiency i want to address the 8 lines as one port in 1 line of code

Portb = 255

I couldn't find on the Teensy pin out, the actual port designations (e.g. A0 - A7) to ascertain on what model this is possible. For speed i was thinking of a 3.2 or 3.6

Can someone point me in the right direction please ?
 
They're shown in the schematics.

On Teensy 3.2, you'll probably want to use port D (pins 2, A0, 7, 8, 6, A6, A7, 5) or port C (pins A1, A8, A9, 9, 10, 13/LED, 12, 28, 27, 29, 30).
 
They're shown in the schematics.

On Teensy 3.2, you'll probably want to use port D (pins 2, A0, 7, 8, 6, A6, A7, 5) or port C (pins A1, A8, A9, 9, 10, 13/LED, 12, 28, 27, 29, 30).

I'm doing this on an LC as my first Teensy. I'm try to use port C and I think from the schematics it's:-

C0 = 15
C1 = 22
C2 = 23
C3 = 9
C4 = 10
C5 = 13
C6 = 11
C7 = 12

but i'm not getting the results i expect. Have i got this wrong ?
 
Have i got this wrong ?
No, the pins are correct. After you have configured them as outputs on the LC, assign a value to GPIOC_PDOR to set them. If you have configured them as inputs, read them using GPIOC_PDIR. If you want to know more, look at pages 843 and 845 of the MKL26Z64 Manual (on the datasheets page).

That said, you might wish to define
Code:
#define  GPIOC_PDOR_8BIT  (*(volatile uint8_t *)0x400FF080)
#define  GPIOC_PDIR_8BIT  (*(volatile uint8_t *)0x400FF090)
so you can set (GPIOC_PDOR_8BIT) or get (GPIOC_PDIR_8BIT) just those low 8 bits of port C. It does not matter on the LC, because only these eight pins are available from port C, but on 3.0/3.1/3.2 you have four additional bits (27, 28, 29,30), and on 3.5/3.6 also four (35/A16, 36/A17, 37/A18, 38/A19) that GPIOC_PDOR will set and GPIOC_PDIR will read (if set to outputs/inputs, correspondingly).
 
No, the pins are correct. After you have configured them as outputs on the LC, assign a value to GPIOC_PDOR to set them. If you have configured them as inputs, read them using GPIOC_PDIR. If you want to know more, look at pages 843 and 845 of the MKL26Z64 Manual (on the datasheets page).

That said, you might wish to define
Code:
#define  GPIOC_PDOR_8BIT  (*(volatile uint8_t *)0x400FF080)
#define  GPIOC_PDIR_8BIT  (*(volatile uint8_t *)0x400FF090)
so you can set (GPIOC_PDOR_8BIT) or get (GPIOC_PDIR_8BIT) just those low 8 bits of port C. It does not matter on the LC, because only these eight pins are available from port C, but on 3.0/3.1/3.2 you have four additional bits (27, 28, 29,30), and on 3.5/3.6 also four (35/A16, 36/A17, 37/A18, 38/A19) that GPIOC_PDOR will set and GPIOC_PDIR will read (if set to outputs/inputs, correspondingly).

I was setting the ddr with DDRC=255; to set outputs and setting the pins with for example PORTC=255;

Is that approach not going to work ?
 
Is that approach not going to work ?

It will work, but slowly, because Teensy 3.x provides software emulation of those old AVR registers. When you write the DDRC and PORTC, you're not actually writing to hardware registers. Those are special C++ objects with operator overloading. They allow ancient AVR code for Arduino Uno to (usually) run correctly, but internally the C++ compiler is calling functions which do same as if you had put several digitalWriteFast() lines in your code.

To write to 8 pins as fast as possible, you need to use the native registers. Of course, you need to pay attention to the schematic to connect to 8 pins which are accessed by the same native register.

On the plus side, Teensy 3.6 runs at 180 MHz, so even if you don't do things very efficiently, it often works out much faster than if you had used an old 8 bit 16 MHz part as efficiently as possible.
 
thanks Paul I understand. As a workaround i coded it using an array of pin designations and it's plenty fast enough, and I guess doing that I get portable code so I'll not worry about the direct approach for now. If i need more speed I'll go to a 3.6

I'm coming from 8 bit zbasic so C on Teensy is already out-performing by some margin and should meet my needs for driving an oscilloscope CRT.

appreciate the help
 
Fully agreed with Paul.

That said, the direct port interface is sometimes useful with displays and ADCs and such, that have parallel interfaces.

The way I handle portability issues, is using helper functions, and the preprocessor to choose the appropriate one. In particular:
Code:
#if defined(__MKL26Z64__) || defined(__MK20DX128__) || defined(__MK20DX256__)
// Teensy LC/3.0/3.1/3.2: Data pins are 15, 22, 23, 9, 10, 13, 11, 12.

static inline void init_data_pins(void)
{
    // Data pins are fixed.  Do not attempt to change any of the pins.
    pinMode(15, OUTPUT); 
    pinMode(22, OUTPUT);
    pinMode(23, OUTPUT);
    pinMode(9,  OUTPUT);
    pinMode(10, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(11, OUTPUT);
    pinMode(12, OUTPUT);
}

static inline void set_data_pins(uint8_t byte)
{
    // Use a direct byte access to the GPIOC_PDOR register:
    (*(volatile uint8_t *)0x400FF080) = byte;
}

#else
// All other microcontrollers: Fall back to generic equivalent code.

#define  DATA_PIN0  15
#define  DATA_PIN1  22
#define  DATA_PIN2  23
#define  DATA_PIN3  9
#define  DATA_PIN4  10
#define  DATA_PIN5  13
#define  DATA_PIN6  11
#define  DATA_PIN7  12

static inline void init_data_pins(void)
{
    pinMode(DATA_PIN0, OUTPUT); 
    pinMode(DATA_PIN1, OUTPUT);
    pinMode(DATA_PIN2, OUTPUT);
    pinMode(DATA_PIN3, OUTPUT);
    pinMode(DATA_PIN4, OUTPUT);
    pinMode(DATA_PIN5, OUTPUT);
    pinMode(DATA_PIN6, OUTPUT);
    pinMode(DATA_PIN7, OUTPUT);
}

static inline void set_data_pins(uint8_t byte)
{
    digitalWrite(DATA_PIN0, (byte & 1) ? HIGH : LOW);
    digitalWrite(DATA_PIN1, (byte & 2) ? HIGH : LOW);
    digitalWrite(DATA_PIN2, (byte & 4) ? HIGH : LOW);
    digitalWrite(DATA_PIN3, (byte & 8) ? HIGH : LOW);
    digitalWrite(DATA_PIN4, (byte & 16) ? HIGH : LOW);
    digitalWrite(DATA_PIN5, (byte & 32) ? HIGH : LOW);
    digitalWrite(DATA_PIN6, (byte & 64) ? HIGH : LOW);
    digitalWrite(DATA_PIN7, (byte & 128) ? HIGH : LOW);
}

#endif
and then init_data_pins(); in setup(), and set_data_pins(byte) everywhere to set the outputs.

It is obviously important to verify the two implement the same operations. To test, just replace the #if defined... with #if 0 and recompile. (The unused code within the preprocessor directives is not compiled at all, and therefore won't affect the size of the generated code at all.)
It is even more important to comment the assumptions and reasons for having special code for a specific microcontroller type, so I would really expand the comments a bit.

Of course, if the generic code is fast enough, there is no reason to use the hardware-specific one, and Teensyduinos digitalWriteFast() is plenty fast. Plus, generic code allows you to use consecutive pins, rather than pins dictated the hardware. That is easier to maintain and develop, and thus better.
I am only trying to say that if you do need the extra speed, the above is how I do it.
 
Last edited:
thanks for the replies.

Curious about this statement:-
Teensyduinos[tt] digitalWriteFast()

what is digitalWriteFast - i can't find this in the arduino reference, are there some Teensy functions I'm not aware of ?

I'm new to Arduino though have been programming and building projects for years using zbasic. I'm cross-training to C but the zbasic environment is generally more closed and incorporates much of the functionality provided through external libraries as standard, so there are fewer options on how to do things which is both agood and bad thing. However this projects needs speed, and the fastest zbasic cpu is 29mhz and 8 bit.
 
ok - just googled digital writefast and i see what you mean.

this would result in longer (a loop replaced by 8 if statements) but faster code for writing the parallel value to the adc - i'll bear it in mind.

but i see digitalwritefast library does not support non-AVR platforms so no good for Teensy LC ?
 
Last edited:
(I keep forgetting that this forum does not have [tt] ... [/tt], and I must use [FONT=Courier New]...[/FONT] instead.)

Teensyduino supports digitalWriteFast() for all Teensies, including LC.

The reason my example code uses digitalWrite() instead, is because that code is intended for other, non-Teensy microcontrollers. But, since I use either Teensies or AVRs (ATTiny or ATmega32u4), I really should use digitalWriteFast() there instead. Simply put, it does what digitalWrite() does, but faster.
 
ok - forgive this if it's too newbie, but i have arduino IDE and Teensyduino installed. The board type set to LC and :-

#include <digitalWriteFast.h>

and i get error:-

#error Non-AVR device, unsupported.
 
You do not need the #include, because Teensyduino provides the digitalWriteFast(). Whenever you select one of the Teensy boards in Arduino, Teensyduino gets automagically included. Essentially, Teensyduino provides an implementation for Teensies, whereas the digitalwritefast library provides it for AVRs.
 
crikey bob - what a difference fast mode makes

In normal mode can write 4 zeros on the crt 125 times a second, in fast mode it's 478 !
 
Status
Not open for further replies.
Back
Top