Cubecell Software Serial

Hello i am trying to use pins 0 and 4 as RX and TX in software serial. Is there any library that i can use for SoftwareSerial.
Thanks

There is no software serial library right now.
The next generation of nodes will use a asr6502 which has a second serial port.

I’m hacking on a SoftwareSerial implementation now. Lack of an oscilloscope makes it a bit harder, but I’m basically taking the standard SoftwareSerial impl and mixing in the ASR6501 hardware pin stuff from the Wire library.

It…compiles :slight_smile: It will take a bit more work to test it and get it working, but I’m not seeing any hard blockers (if someone wants to point some out, save me some pain!). Maybe there’s some timing stuff, but I’m only looking for 9600 (for gps connectivity), and even then only RX.

ASR6502 with a hardware UART will be better, but this should fill a gap.

@bwooce that are great news.
never found time to do it.

You say “only for RX”, in my experience, RX is the harder part!

@wasn @canalhas FYI

Yes the timing for RX is complicated for sure. Luckily a lot of the hard work of timing calculations had already been done in the code I shamelessly ripped off.

The hardest was trying to test with my own implementation and no external reference. I hooked up an ESP32 to send and reflect traffic using a real UART and that helped a lot. Working for 9600 N81 TX and RX.

So here is a ASR6501 SoftwareSerial implementation. I’m not confident of it enough yet to do a Pull request to Heltec but I’ll give it some time to marinate and try out some TTNMapper code on a CubeCell and see how it goes.

Feedback welcome, if this works for y’all then I’d appreciate hearing about it. If it doesn’t…more so.

great !!!

i will give it a try

Used alongside LoRaWAN and with TinyGPS++ I’m getting 20 good sentence reads out of 1000 (aka 2% success)…so there is a timing/interrupts issue I need to work on.

Today 0%. I’ve no idea how I got any good results now, although I changed my testing to be more GPS-like.

  • It looks like TX works (9600bps, ~most of the time) when not doing anything else.
  • RX. Not working at all, even with no other tasks running.

So a lot more work required, sorry for raising any hopes.

I can’t see how your code would work if there were any interrupts happening for.other stuff.
If I get a moment, I may try it out. I do have a couple of oscilloscopes, but I may use the budget logic analyser.

I’d be interested in the wave form, it should be 104ms square waves per bit. Yes it looks like this isn’t good code for this usecase, and receiving an entire byte with interrupts (in theory) off blocks for ~100us x 21 = 2.1ms which is a very long time for this processor…I will try porting AltSoftSerial that uses timers and blocks per bit instead. Thing that work on 8Mhz 8bit processors don’t directly translate to 32bit 48Mhz ones.

I’m not convinced that noInterrupts() turns off all interrupts either as TX works most of the time but has repeated identical pulses of corrupt data over time.

It’s an odd thing that a higher bps would block for less time individually too, but then timing requires more precision.

Unless Heltec have microsecond timers available for interrupt purposes, I think you are stuck with blocking code.

I spent a few minutes looking at this today. I just wrote an endless loop, setting a pin high, calling a 104uS delay, then setting the pin low, another 104uS delay.
The good news is that the waveform is rock solid, so I think the “noInterrupts()” does work.
The bad news is that the time between transitions is 107.3uS, and that’s without all the other overheads, such as the function for reading the rx pin, the bit count and byte shift etc.
So I reckon the timing is out by too much to work reliably.

It’s one of those times when I would revert to assembler, as It’s hard to count cycles in C.

Thanks @johnarnoldbrown for the feedback.Yes this is much harder and more hacky than I expected, there are so many good reasons this is properly done in hardware.

I have successfully harnessed the PWM1 interrupt but so far failed to stop is firing every ~2uS when it’s active. It’s more precise and possibly enough to use for timing but getting the timing right is hard, and I’ve tried so many times to get more than on/off control of it e.g set it to 104uS. Other SoftSerial implementations pulse a debug pin when they’re reading the input so the timing can be tweaked until they line up correctly, and that sounds like what’s required.

What it really needs is a PSoC creator built timing object just for this but I don’t know if @Aaron can do that. He did comment on the Github issue that he was looking into a SoftwareSerial implementation and I’d be so happy for him to do that :slight_smile: