Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 15 of 15

Thread: High-speed digital I/O

  1. #1
    Junior Member
    Join Date
    Mar 2020
    Posts
    6

    High-speed digital I/O

    I would like to use the Teensy 4.0 as a simple signal generator to produce digital signals. The intent is to use three I/O pins and configure them as outputs. The 1st signal has a frequency of around 30 HZ, the 2nd signal has a frequency of around 8 KHz, and the 3rd signal has a frequency of around 10 MHz.

    The code for generating the signals does not involve any math or computation. So, the code will be just a few lines long with no math or computation in between.
    Can I achieve producing a 10 MHz signal?

    Thanks,
    Mo

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,498
    The PWM pins can do it, without any software overhead.

    Code:
    void setup() {
      analogWriteFrequency(2, 10000000);
      analogWrite(2, 128);
    }
    
    void loop() {
    }
    Click image for larger version. 

Name:	file.png 
Views:	8 
Size:	26.7 KB 
ID:	19493

  3. #3
    Junior Member
    Join Date
    Mar 2020
    Posts
    6

    High-speed digital I/O

    Thank you for your prompt response.

    The three signals need to have a certain timing relationship. So, there are not three individual "free-running" signals; they are timed w.r.t. each other. This implies that I have to generate them using code to preseve the timing relashion ship. For the sake of the discussion, I call these signals "30Hz", "8KHz" and "10MHz". The sequence will assert the "30Hz" signal, then some tiime later, the "8KHz" signal will be asserted, and some time later the "10MHz" signal will start. After say 1280 cycles of the "10MHz" signal, the "8KHz" signal will be deasserted (deactivated), ... and this cycle continues for 240 times at which point the "30Hz" signal will be deactivated, and then the entire process repeats.

    Given that the Teensy 4.0 is running at 600 MHz, the question is "can it toggle a GPIO line in less than 60 clock cycles?" to provide a 10 MHz signal

    Thanks again,

    Mo

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,578
    Quote Originally Posted by MoA View Post
    The three signals need to have a certain timing relationship. So, there are not three individual "free-running" signals;
    So next time it would be good to mention such things in the 1st post. Nobody knows what you want without that.
    We don't want to spend time to answer things to hear "I want something different" later. We're not your support-hotline.

    If the code is just a few line - why don't you write it, and test it?
    Yes it can toggle with 10MHz. Depends on how much more you're doing in your code.
    If you use "digitalWriteFast() with a const pin number, the compiler optimizes this to a single instruction (plus load adresses -depends on your code how good/fast it will be).
    However, the BUS to the GPIO is 150MHz.
    Last edited by Frank B; 03-26-2020 at 07:14 PM.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,498
    Quote Originally Posted by MoA View Post
    the question is "can it toggle a GPIO line in less than 60 clock cycles?" to provide a 10 MHz signal
    Yes, digitalWriteFast() can easily toggle pins that fast.

    But you will probably need to disable interrupts and maybe write some tricky code to get the timing right.

  6. #6
    Junior Member
    Join Date
    Mar 2020
    Posts
    6

    Writing an 8-bit value to 8 individual output lines

    Quote Originally Posted by PaulStoffregen View Post
    Yes, digitalWriteFast() can easily toggle pins that fast.

    But you will probably need to disable interrupts and maybe write some tricky code to get the timing right.
    Thanks to all contributors for their valuable input.

    I would like to extend the scope of my project to include writing an 8-bit value (which can be a constant to compile time) to 8 individual digitial output lines. I can arrange the outputs lines in any order including next to each other or whatever arrangement that may be necessary. I am looking for the fastest way to set those 8 output lines. Ideally, I would like an API that sets all 8 lines at the same time.

    Any suggestions?

    Thanks again,
    Mo

  7. #7
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    You can write directly to the GPIO register to change multiple bits in parallel. You must write 32 bits at a time, but only a subset are available as real external pins due to the T4.0 board design.

    Check out this thread for some working code:
    https://forum.pjrc.com/threads/57698...is-it-possible

    Also make sure to read Paul's post here:
    https://forum.pjrc.com/threads/57717...l=1#post216620

  8. #8
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    811
    If you want to find out which pin belongs to which bit in the GPIO registers you can have a look at the code here: https://github.com/TeensyUser/doc/wi...w-level-access

  9. #9
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,363
    A potential other option in much of this would be to see if you could do some of this using the FlexIO subsystem.

    So far I have played with some of their examples like SPI and Serial and tried to more generalize them...
    Some of that stuff is up in my github project: https://github.com/KurtE/FlexIO_t4

    Depending on which clocking options you choose in the clocking registers like: CCM_CDCDR you can run this probably as high as 480mhz or maybe 508.24mhz then divided by
    a few different other values: (either 1, 2, 3 or 8)*(1 or 8) The 1*1 is not recommended for fast inputs. So you could have it at something like 240mhz maybe.

    You can in theory try to use the basic blocks of Timers, shifters and build things and the also have the ability to try to setup your own state machine.

    They also have the ability to do things like parallel outputs. But again there is not 8 contiguous pins on any of the three FlexIO objects. Although I believe the T4.1 will have that on FLEXIO3. But only FliexIO1 and FlexIO2 have DMA support...

    And like a lot of the stuff in the manual, some of the stuff may take a few readings and experiments to make any sense... (Chapter 49)

  10. #10
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    Yeah, FlexIO can do this with zero processor overhead... Although it may be tricky to set up. I posted some example code doing 4bit parallel output from a buffer at 40MHz with FlexIO:
    https://forum.pjrc.com/threads/59504...l=1#post230008
    (Ignore the comment about a missing ampersand in the library, Kurt fixed that)

    Doing 8 pins will be more of a hassle, but you can do it if you increase the shift width to either 16 or 32 and include padding bits in your buffer as necessary. I would expect it to run more slowly however.

    (I am currently working on a project using FlexIO to drive 6 pins in parallel on an LED panel which I hope to post soon...)

  11. #11
    Senior Member
    Join Date
    Feb 2017
    Posts
    369
    Quote Originally Posted by MoA View Post
    I would like to extend the scope of my project .....
    Feature Creep or poorly defined requirements from the start?

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,498
    Or still learning how to ask strangers on the internet for tech help.

    Seriously though, you can get much better help if you give us context to understand what you're trying to accomplish. A series of narrowly focused questions without any way to understand your needs really limits what we can do. We're humans and we generally want to help. Please, do yourself a favor and write a better message that gives us some insight to what you're really trying to accomplish.

  13. #13
    Junior Member
    Join Date
    Mar 2020
    Posts
    6

    Writing an 8-bit value to 8 digital output lines

    Quote Originally Posted by easone View Post
    Yeah, FlexIO can do this with zero processor overhead... Although it may be tricky to set up. I posted some example code doing 4bit parallel output from a buffer at 40MHz with FlexIO:
    https://forum.pjrc.com/threads/59504...l=1#post230008
    (Ignore the comment about a missing ampersand in the library, Kurt fixed that)

    Doing 8 pins will be more of a hassle, but you can do it if you increase the shift width to either 16 or 32 and include padding bits in your buffer as necessary. I would expect it to run more slowly however.

    (I am currently working on a project using FlexIO to drive 6 pins in parallel on an LED panel which I hope to post soon...)
    Given that with my application I need 8 digital lines, is there any guidance on the selection of the pins/outputs. In other words, which 8 outputs provide the easiest proramming experience?

    Thanks,

    Mo

  14. #14
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    For posterity on this forum, here is a detailed answer...

    If you are using GPIO:
    Pins 0-1 and 14-27 are on GPIO1 (16 pins)
    Pins 6-13 and 32 are on GPIO2 (9 pins)
    Pins 28, 30, and 31 are on GPIO3 (3 pins)
    Pins 2-5, 29, and 33 are on GPIO4 (6 pins)

    If you are using FlexIO:
    Pins 2-5 and 33 are on FlexIO1 (5 pins)
    Pins 6-13 and 32 are on FlexIO2 (9 pins)
    Pins 7-8, 14-23, 26-27 are on FlexIO3 (14 pins)

    Of course pins 24-33 are on the bottom side of the board.

    For FlexIO unless you use 32-bit shift mode, you can't choose arbitrary pins, they have to be consecutive (in terms of the FlexIO pin numbers, not the Teensy pin numbers). The details are listed in Kurt's Teensy4 spreadsheet here:
    https://github.com/KurtE/TeensyDocuments

    Because of that, 8-bit shift mode is limited to 5 pins for FlexIO2 and 6 pins for FlexIO3. 16-bit mode is limited to 7 pins for FlexIO2 and 12 pins for FlexIO3.

    So you can output to 8 pins using GPIO1 or GPIO2 (with 32 bit writes), FlexIO2 (with 32-bit mode), or FlexIO3 (with 16 or 32-bit mode). FlexIO3 16-bit mode will be the most efficient way, but GPIO is much easier. In each case you can write directly to the registers to output data on demand, but they can also be set up with a DMA transfer to run in the background (except FlexIO3 which doesn't work at all with DMA).
    Last edited by easone; 03-28-2020 at 05:34 AM.

  15. #15
    Junior Member
    Join Date
    Jan 2020
    Posts
    15
    Another thing is that FlexIO generates timer and clock signals which can also be configured to output to external pins. In that case the timer pins can be arbitrary. So you could for example use FlexIO2 in 8 bit mode with 5 parallel output pins and 4 additional clock or timer pins.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •