Interesting project. Makes me wonder how hard would it be to create a serial tester that can simulate different serial protocols, including customizable timing settings, signal polarity, framing options, CRC, etc. Maybe even able to simulate noisy signals, missing bits, misaligned clock, etc. As you discovered using digitalWrite is extremely slow. There's faster, more direct ways of controlling the I/O pins. There's also more options to represent your numbers and store them efficiently so maybe you could have used a cheaper micro. BUT most of the time squeezing the most out of a microcontroller requires writing "lower" level code, which will make your code less readable and less portable.
Thanks for the reply! You are right in that there are many things that could be improved, especially in the code :-) On the one hand, I’d love to make such improvements. On the other, the time I have for this hobby is restricted (actually travelling somewhere close to the equator now :-) With better code, I’m sure I’d be able to employ a slower and cheaper MCU. If I needed to build many copies, it would make perfect sense (higher margins). However, since I only need one unit, the €25 price tag of a Teensy 4.0 is not a main concern. The device currently generates codes up to 1MHz clock. If I had been able to reach a 100kHz clock speed only, I’d be happy too (100kHz is actually my default speed). But everyone will have different design requirements. Also, optimized code often means less portability, as you noted. Now this unit does what I wanted it to do, I now plan to invest my time in an existing complementary device. Stay tuned :-)
Sorry, but. As I'd understand, the only thing that this device does is nothing more than playing table of 5 parallel 1-bit sequence 511 bits long again and again, which is something, that, in my opinion, does not require a microcontroler. 5 bits to output through some latches (just to achieve correct timing), 6-th bit then should be used to reset the counter driving lower 9 bits of address counter, because that table is 511 samples long and this is the easiest way how to reset it. Then you have 17 scenarios, so additional 5 address bits used to switch scenario should be enough, right? This leads me to a 16kB EPROM. Using 70ns version gives you one sample every 100ns (just to be on the safe side), but you need to read twice per sample because of resetting of the address counter, which leads me to at least 200ns per sample, which is equal to 5Mbit/s. EPROMs are typically slow as a hell, but even though that thing would be capable of delivering 5Mbit/s (and maybe little bit more). Switching the scenario could be easily achieved using rotary switches. The second thing - how the outputs are made. TTL logic is not intended to be fast or precise when it comes to timing. You definitely need something differential (like ECL or LVDS) to achieve at least reasonably precise timing. TTL could be also utilized in a kind of differential way, but it's not easy to do and introduces another issues, using ECL, MECL, PECL or LVDS is just easier than running into rabbit hole of TTL logic. In fact, it would be relatively easy to put out a differential data output, you can just store that bitstream in straight and inverted form and use unused part of latch IC to put them out, but doing the same with the clock signal is definitely not that easy, so, ok, it's not differential, it's bare TTL. Maybe it would be useful to have also inverted data output, I would add this into that design just because it's easy to do. Using that BNCs leads me to conclusion, that 50Ω or 75Ω relatively long coaxial cables would be used (your BNCs are 50Ω types) to connect to DUT, which is a kind of unfortunate because of its relatively low characteristic impedance and also low attenuation on relatively high frequencies, which, if they are wired as you did, introduce huge ringing into whole system or overloads the outputs of TTL logic (if they are properly terminated to reduce ringing). I know that 100kHz is not too much, but as you touch the 1Mbit/s, this starts to become an issue. So in my opinion, as it is, it's probably ok up to 200kbit/s, maybe 300, but I would use different sort of wiring, just to be on safe side (and also to save some costs). Just look at the digital probes of your oscilloscope(s). These simple connectors and flat wires are used for a reason, not (only) to reduce costs. In fact, it's much better option for TTL logic than using coaxial cables and BNCs. The last thing - software. I accept that using some kind of microcontroller opens the possibility to develop more sophisticated software introducing at least some versatility to that device, co using MCU is not that bad idea, but the software is awful. That "bool np9[ rows ][ columns ]" is something horrible, because (you are running at 32bit system) it occupies 4 bytes for one boolean value. You are using 17 different bitstreams. In fact, if you declare that thing to be "uint32_t np9[columns]" you can easily store 32 bitstreams occupying much less memory. And selecting the right bitstream is also easy, you can easily use macros like bit_is_set() to obtain selected bitstream from that uint32 (also & _BV(bstream_num) etc, there are a lot of possibilities). That's the first thing. The second thing is that CLK should trigger an INT and the data out should be done on the background. This is the easiest way how to eliminate at least some jitter. Putting the data out routine to the background also opens the possibility to add some functionality like the dynamic generation/modifying the bitstream pattern, this just opens a lot of possibilities. This is so typical for arduino programmers. They don't use interrupts, they use the hardware very inefficient way, it's just pain to look at it. That device is not bad, but there is a huge area for many improvements. It's decent beginning and I don't thing that development of this device should end at this point. In fact, it's great idea to build device like this.
Interesting project. Useful informations. Nice video to follow. Thanks.
Very nice, the video kept me glued to the screen ;-)
Happy to hear so!
Interesting project. Makes me wonder how hard would it be to create a serial tester that can simulate different serial protocols, including customizable timing settings, signal polarity, framing options, CRC, etc. Maybe even able to simulate noisy signals, missing bits, misaligned clock, etc.
As you discovered using digitalWrite is extremely slow. There's faster, more direct ways of controlling the I/O pins. There's also more options to represent your numbers and store them efficiently so maybe you could have used a cheaper micro.
BUT most of the time squeezing the most out of a microcontroller requires writing "lower" level code, which will make your code less readable and less portable.
Thanks for the reply!
You are right in that there are many things that could be improved, especially in the code :-) On the one hand, I’d love to make such improvements. On the other, the time I have for this hobby is restricted (actually travelling somewhere close to the equator now :-) With better code, I’m sure I’d be able to employ a slower and cheaper MCU. If I needed to build many copies, it would make perfect sense (higher margins). However, since I only need one unit, the €25 price tag of a Teensy 4.0 is not a main concern. The device currently generates codes up to 1MHz clock. If I had been able to reach a 100kHz clock speed only, I’d be happy too (100kHz is actually my default speed). But everyone will have different design requirements. Also, optimized code often means less portability, as you noted.
Now this unit does what I wanted it to do, I now plan to invest my time in an existing complementary device. Stay tuned :-)
@@rudiselectronicslab861 That sounds intriguing. Can't wait to see what it is!
Sorry, but. As I'd understand, the only thing that this device does is nothing more than playing table of 5 parallel 1-bit sequence 511 bits long again and again, which is something, that, in my opinion, does not require a microcontroler. 5 bits to output through some latches (just to achieve correct timing), 6-th bit then should be used to reset the counter driving lower 9 bits of address counter, because that table is 511 samples long and this is the easiest way how to reset it. Then you have 17 scenarios, so additional 5 address bits used to switch scenario should be enough, right? This leads me to a 16kB EPROM. Using 70ns version gives you one sample every 100ns (just to be on the safe side), but you need to read twice per sample because of resetting of the address counter, which leads me to at least 200ns per sample, which is equal to 5Mbit/s. EPROMs are typically slow as a hell, but even though that thing would be capable of delivering 5Mbit/s (and maybe little bit more). Switching the scenario could be easily achieved using rotary switches.
The second thing - how the outputs are made. TTL logic is not intended to be fast or precise when it comes to timing. You definitely need something differential (like ECL or LVDS) to achieve at least reasonably precise timing. TTL could be also utilized in a kind of differential way, but it's not easy to do and introduces another issues, using ECL, MECL, PECL or LVDS is just easier than running into rabbit hole of TTL logic. In fact, it would be relatively easy to put out a differential data output, you can just store that bitstream in straight and inverted form and use unused part of latch IC to put them out, but doing the same with the clock signal is definitely not that easy, so, ok, it's not differential, it's bare TTL. Maybe it would be useful to have also inverted data output, I would add this into that design just because it's easy to do.
Using that BNCs leads me to conclusion, that 50Ω or 75Ω relatively long coaxial cables would be used (your BNCs are 50Ω types) to connect to DUT, which is a kind of unfortunate because of its relatively low characteristic impedance and also low attenuation on relatively high frequencies, which, if they are wired as you did, introduce huge ringing into whole system or overloads the outputs of TTL logic (if they are properly terminated to reduce ringing). I know that 100kHz is not too much, but as you touch the 1Mbit/s, this starts to become an issue. So in my opinion, as it is, it's probably ok up to 200kbit/s, maybe 300, but I would use different sort of wiring, just to be on safe side (and also to save some costs). Just look at the digital probes of your oscilloscope(s). These simple connectors and flat wires are used for a reason, not (only) to reduce costs. In fact, it's much better option for TTL logic than using coaxial cables and BNCs.
The last thing - software. I accept that using some kind of microcontroller opens the possibility to develop more sophisticated software introducing at least some versatility to that device, co using MCU is not that bad idea, but the software is awful. That "bool np9[ rows ][ columns ]" is something horrible, because (you are running at 32bit system) it occupies 4 bytes for one boolean value. You are using 17 different bitstreams. In fact, if you declare that thing to be "uint32_t np9[columns]" you can easily store 32 bitstreams occupying much less memory. And selecting the right bitstream is also easy, you can easily use macros like bit_is_set() to obtain selected bitstream from that uint32 (also & _BV(bstream_num) etc, there are a lot of possibilities). That's the first thing. The second thing is that CLK should trigger an INT and the data out should be done on the background. This is the easiest way how to eliminate at least some jitter. Putting the data out routine to the background also opens the possibility to add some functionality like the dynamic generation/modifying the bitstream pattern, this just opens a lot of possibilities. This is so typical for arduino programmers. They don't use interrupts, they use the hardware very inefficient way, it's just pain to look at it.
That device is not bad, but there is a huge area for many improvements. It's decent beginning and I don't thing that development of this device should end at this point. In fact, it's great idea to build device like this.