UART keep alive signal for SFP fiber - Page 1
Forum section: electronics / general

author: Amper
author_rank: Frequent Contributor
timestamp: January 25, 2023, 04:01:30 pm
content: Hi,im working on sending data between two STM32L via fiber over SFP modules, the link sort of works, one disadvantage is that the SFP trancievers seem to need a very symmetrical signal and have quite a long startup time. Even though i dont want to transmit a lot of data (high voltage insulation is the goal) i need a quite high baud and manchester encoding for the link to be reliable. After a transmission i have to wait several ms for the new packet to be unscrambled. That on the other hand is too slow for the transmission i want to do.The solution that should work is to keep the link busy at all times. Is there some established way of doing this without using too much cpu time in the controller? The only way i could come up with rn is to put everything into something like 100 byte packages and as soon as the buffer of actual data is empty interrupt the program and send empty buffers filled with zeros or some preamble. It doesnt seem very elegant to me. also 100 bytes at 1MBaud would be an interrupt every 0.8ms which would be very inconvenient...Maybe you guys have an idea

author: Siwastaja
author_rank: Super Contributor
timestamp: January 25, 2023, 04:43:44 pm
content: There seems to be a lot of mixups or weird questions.What is this "SFP module"? What do you mean by "symmetrical", and seeing you mention manchester encoding later on, by symmetrical, do you mean free from DC bias? If so, MCU UART peripheral is probably unable to create manchester encoding, but you can try the SPI peripheral fed from DMA acting like an endless shift register. But, are you sure you need DC bias free signal? Because later on you talk about like you just have to sendsomething. Specification to that "SFP module" would help sort this out. Even if you need DC bias removal, there are more efficient bit stuffing algorithms than manchester encoding.What do you mean by "link busy"? All STM32 devices have DMA. You can keep the DMA feeding whatever data to UART with no CPU intervention. You can setup it in circular mode with, say, 1-byte long buffer, and just reconfigure it whenever you want to send something of value. Or, you can configure DMA into double buffered mode, and process (generate or parse) one of the buffers while other is being used by the peripheral.What is this "unscrambling" which takes several ms?

author: Amper
author_rank: Frequent Contributor
timestamp: January 25, 2023, 05:35:42 pm
content: A bit of context was missing, you are right but you still got my questionhttps://de.wikipedia.org/wiki/Small_Form-factor_PluggableThey are driven by lvds drivers, differential in, differential out, each line has its own dc block and as it seems also some internal auto gain or similar on the optical side that requires the signal to have not only no DC in absolute but also no dc over just a few bits. Just having two stopbits instead of one will cause glitches.Manchester can be done in software before sending the modified bit order via the uart peripherals of the stm.By "something" im taking about not having breaks in the transmission longer than two bits no not cause the auto gain of the reciever to missadjust and cause wrong bits upon the transmission resuming.Your idea using just one byte via DMA sounds like what i wanted to do, my issue so far was mostly, how do i refill the TX buffer at a speed so it never overflows or runs empty, thats why i talked about the interrupt after sending.The unscrambling (lack of a better word) means, the differential output with DC Block goes into a steady state with the lines close to each other after not seeing any signal for a while. Them being in undefined states makes the output just generate noise at a few GHz and the recovery from this state takes a few milliseconds after restarting transmission.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 25, 2023, 06:46:27 pm
content: Thanks for clarifications, so you really do need Manchester or 8b/10b or similar.What is the actual bitrate you need?I mean, UARTs are pretty limited in speed (because of the internal x8 oversampling thing that runs at peripheral clock) anyway, so if it is working with UART, then, unless your algorithms are bloated, you can almost always do simple bit operations at maximum possible UART clock, with CPU to spare. Memory access being fast on MCUs, you could just even use large lookup tables to unscramble, so then it's just a dozen of CPU cycles per byte. Chances are, you could maybe do it even without DMA, on per-byte basis, in an ISR, but ISR entry and exit is some overhead (~ 20 cycles). If the UART has a FIFO, even just 4 bytes, then you are already much better off with reduced interrupt rate.But double-buffered DMA where finishing one buffer triggers processing the other will have best performance. Alternative to the double buffering is one large buffer in circular mode, and usage of Half Transfer interrupt.But getting the actual numbers, i.e. desired bitrate, MCU part number or even family (you just said STM32L; but between STM32L0 or STM32L4, big difference), and CPU clock speed would be helpful handwaving it more closely.

author: Amper
author_rank: Frequent Contributor
timestamp: January 25, 2023, 07:34:50 pm
content: ThanksYes, about the manchester im sure and i dont consider it an issue, thats something i already got going as long as i dedicate all cpu time to sending stuff.Im sure i could do it with very little resources but wasting interrupts on something that happens so very regularly seems like a bad idea. Id like to not worry about it when doing other stuff.For even more context: the original idea was just to have a way of making sensors and simple control stuff work over long distance and EMI resistant, remote sensing on hydroelectric powerstations, nothing critical infrastructure like but stuff like "filter two kilometers up hill behind a Forrest is clogged" or just temperatures and Waterlevels. So i took an open source board (https://gitea.osmocom.org/electronics/osmo-small-hardware/src/branch/master/sfp-breakout), quickly added space for the STM32L412C8T, some IO and an oled and got boards made. The next revision will have a sub-D as well and max232 because i realized it would be nice to connect the HP34970A isolated as well, so the goal changed to long range interface and RS232 tranciever via fiber.The choice to use single mode fiber is because they are sort of cheap and very robust, also i have a splicer at home so i can make my own lines.-> The datarate i need is very low, having 100kbaud would be plenty but since its the lowest limit the sfp hardware works ata and the controller doesnt seem to mind 1MBd im open to having more.enough rambling around, put in fewer words, there are not really hard requirements i have to hit besides reliability and robustness, speed is not important, ease of use and keeping the controllers "mind" free of interrupts would be nice so i can use display and periphery without worrying about the communication failing.EDIT: I guess ill try getting the DMA transmit working, that seems to be a good point to continue from no matter what the next step will be.

author: dobsonr741
author_rank: Frequent Contributor
timestamp: January 25, 2023, 07:47:11 pm
content: This article suggests sending constant streaming UART traffic with compensation for zero DC balance:https://www.electro-tech-online.com/attachments/manchester_encoding_using_rs232-pdf.30816/

author: Amper
author_rank: Frequent Contributor
timestamp: January 25, 2023, 07:53:00 pm
content: huh, the TX routine is actually exactly what im doing in my code

author: uer166
author_rank: Super Contributor
timestamp: January 25, 2023, 09:52:17 pm
content: Neat! Don't you need to do gap-less transmission here though? I've always had trouble doing that with e.g. SPI peripheral, where it always puts some gaps, even when using DMA or busy-wait.

author: Amper
author_rank: Frequent Contributor
timestamp: January 25, 2023, 10:13:21 pm
content: No gaps would be ideal, i have no idea how close ill get to thatOne thing i just realized is tht my keep alive idea sending empty bytes will be an issue on the receiving side... id need to drop all the placeholders, if possible in hardware. Still unsure how this will turn out...

author: dobsonr741
author_rank: Frequent Contributor
timestamp: January 25, 2023, 10:22:28 pm
content: When doing it in hardware my choice would be a small FPGA. Or, if you are not married to STM32, the PIO engine in Raspberry Pi Pico.

author: Amper
author_rank: Frequent Contributor
timestamp: January 25, 2023, 10:46:14 pm
content: That would be "slightly" overkill for the application i have in mindIt has to be possible in a simpler way, worst case i could just use a very high frequency signal from some external generator and do fsk modulation or something like that.

author: berke
author_rank: Frequent Contributor
timestamp: January 25, 2023, 11:06:47 pm
content: You could generate a square wave at half the baud rate using a PWM at no CPU cost and XOR it with the output using an 74HC86 or similar.- When you're not transmitting, the receiver should see $AA's (assuming 8N1).- When you're about to transmit using the UART, turn the PWM off, transmit, then turn the PWM back on. Transform bytes so that you don't generate $AA and so that there are enough transitions. For example, to keep your code simple you could transmit two bits per byte. A byte ABCDEFGH becomes 0101 A !A B !B, 0101 C !C D !D, 0101 E !E F !F, 0101 G !G H !H- You may get some garbled bytes/glitches when you engage/disengage the PWM that some leading/trailing sync bytes should take care of easily

author: Siwastaja
author_rank: Super Contributor
timestamp: January 26, 2023, 06:34:53 am
content: Quote from: Amper on January 25, 2023, 07:34:50 pmNo need to worry, microcontrollers are specifically designed for small interrupt latency, to run interrupt-based code. (Compared to more complex application processors.) You can easily calculate or approximate this stuff, and if it fits, then it fits.Quote1 megabaud per second is just 100 kbytes per second. If the CPU runs at 80MHz, that's 800 CPU cycles per byte. Handwaving it, maybe you can easily do interrupt based in 100 cycles per byte (including ISR entry/exit overhead), in which case you have a tad over 10% CPU usage. Plenty of time to run other things in interrupts, or main thread. With DMA solution, maybe you can process in 50 cycles per byte, and use lower priority level for the processing ISR (or even do it in main thread), which could be advantageous if you have some other important ISRs that take many hundreds of cycles AND cannot wait.FPGA is total and utter overkill by many order of magnitudes, but always gets suggested in threads where people ask something completely normal for MCUs because some people think in terms of 1980-1990's MCUs, when 115200 baud/s UART was considered "fast". In 1990's, a companion CPLD would have been likely used.For reference, I have successfully implemented 500kbaud/s SDLC implementation on 400MHz Cortex-M7 so that eachbittriggered an ISR! This included bit stuffing/destuffing, flag byte detection, CRC calculation, and ISR entry/exit latency; no peripheral available. Even with fifo-less UART peripheral, you already reduce the interrupt rate by 10x.SPI peripheral is better: it has 16-bit word size, and 32-bit FIFO. With SPI, you could process 32-bit words with one bus transfer.DMA is obviously the best.

author: peter-h
author_rank: Super Contributor
timestamp: January 26, 2023, 02:32:36 pm
content: Remember that LEDs don't have an infinite life. I've designed numerous fibre products and if you drive the LED hard (which usually you are, to get decent range) its life isn't that great. So continuous data may not be a good thing. I solved it by encoding a rising edge with two pulses and a falling edge with one pulse, and then a simple state machine (22V10 clocked at 1MHz did the decoding. The baud rate was up to 115200.

author: dobsonr741
author_rank: Frequent Contributor
timestamp: January 26, 2023, 02:42:36 pm
content: SFPs cost as much a cup of latte these days. I’m interested to see more on the 22v10 state machine. If I understand right the link would be dark most of the time?

author: peter-h
author_rank: Super Contributor
timestamp: January 26, 2023, 02:58:26 pm
content: Yes. On average with NRZ data it is off 50% of the time.22V10 state machine (done in 1999, compiled with CUPL):Code:Name GAL;Partno V1.7;Date 10/05/99;Revision 1.7;Designer P;Company X Ltd;Assembly ;Location ICXX;Device P22V10LCC;/*GAL FOR FIBRE LINE DRIVER.Implements both encoder and decoder.NOTE: the Partno field above is used for the UES. However, to getthe UES you need to use G22V10LCC and this needs CUPL4 because CUPL3has a bug on that device.MOD RECORD1.01/11/98Created.1.13/11/98TEST_ENA & TMD inverted.1.26/11/98DEC_OUT forced to 0 if Test switch pressed.1.428/12/98In TMD, ENC_OUT *not* taken from DEC_IN if switchis pressed. Comments changed re external sync.1.521/4/99Decoder redesigned.1.622/4/99Decoder changed, TMD now sets Dout=1 and triggersthe invalid decode data watchdog.1.710/5/99Encoder & decoder redesigned, to properly terminateTMD mode.*//* Inputs */pin 2=CLK;/* Clock */pin 3=RESET;/* Global Reset */pin 4=PRESET;/* Global Preset */pin 5=SPARE2;/* Unused input */pin 6=SPARE3;/* Unused input */pin 7=SPARE4;/* Unused input */pin 9=SPARE5;/* Unused input */pin 10=SPARE6;/* Unused input */pin 11=SPARE7;/* Unused input */pin 12=!ENC_IN;/* Encoder input, inverted due to MAX232 */pin 13=!TEST_ENA;/* Test Mode (loopback) switch, active-low */pin 16=DEC_IN;/* Decoder input *//* Outputs */pin 27=EQ0;/* Encoder state machine */pin 26=EQ1;/* Encoder state machine */pin 25=EQ2;/* Encoder state machine */pin 24=DQ0;/* Decoder state machine */pin 23=DQ1;/* Decoder state machine */pin 21=DQ2;/* Decoder state machine */pin 20=DQ3;/* Decoder state machine */pin 19=!TMD;/* Test Mode detect LED, active-low */pin 18=ENC_OUT;/* Encoder output */pin 17=!DEC_OUT;/* Decoder output, inverted due to MAX232 *//* Definitions *//* One does need to give the encoder & decoder states different names */$DEFINE est_0'b'000/* All possible encoder states */$DEFINE est_1'b'001/* See NOTES for explanation of bits */$DEFINE est_2'b'010$DEFINE est_3'b'011$DEFINE est_4'b'111$DEFINE est_5'b'101$DEFINE est_6'b'110$DEFINE est_7'b'100$DEFINE dst_0'b'0000/* All possible decoder states */$DEFINE dst_1'b'0001/* See NOTES for explanation of bits */$DEFINE dst_2'b'0011$DEFINE dst_3'b'0111$DEFINE dst_4'b'0110$DEFINE dst_5'b'1111$DEFINE dst_6'b'1110$DEFINE dst_7'b'1001$DEFINE dst_8'b'0101$DEFINE dst_9'b'0010$DEFINE dst_10'b'1011$DEFINE dst_11'b'1010$DEFINE dst_12'b'1101$DEFINE dst_13'b'1000$DEFINE dst_14'b'0100$DEFINE dst_15'b'1100/* D-types forming the two state machines. These must both be ZERO-based, dueto a "feature" of CUPL */FIELD encoder = [EQ2..0];FIELD decoder = [DQ3..0];/* Equations */EQ0.AR= RESET;/* All D-types are reset with RESET */EQ1.AR= RESET;EQ2.AR= RESET;DQ0.AR= RESET;DQ1.AR= RESET;DQ2.AR= RESET;DQ3.AR= RESET;EQ0.SP= PRESET;/* All D-types are preset with PRESET */EQ1.SP= PRESET;EQ2.SP= PRESET;DQ0.SP= PRESET;DQ1.SP= PRESET;DQ2.SP= PRESET;DQ3.SP= PRESET;/* ********************** ENCODER *************************** */SEQUENCE encoder{/* wait for Din=1, SW=0 */PRESENT est_0IF TEST_ENANEXT est_7;/* test mode */IF ENC_INNEXT est_1;/* Din=1 */DEFAULTNEXT est_0;/* nothing happens here */PRESENT est_1NEXT est_2;/* nothing happens here */PRESENT est_2IF TEST_ENANEXT est_6;/* test mode */IF !ENC_INNEXT est_3;/* Din=0 */DEFAULTNEXT est_2;/* nothing happens here */PRESENT est_3NEXT est_4;/* nothing happens here */PRESENT est_4NEXT est_5;/* nothing happens here */PRESENT est_5NEXT est_0;/* return to S0 *//* switch pressed - generate a 101010101.... output while switch pressed *//* exit only if switch released and incoming (decoder i/p) data has stopped */PRESENT est_6NEXT est_7;PRESENT est_7IF TEST_ENANEXT est_6;/* stay in test mode */IF !TEST_ENA & !DEC_IN & !TMDNEXT est_0;/* exit test mode */DEFAULTNEXT est_7;}/* Decode Encoder state machine Q2..0 D-types into ENC_OUT output */TABLEencoder => enc/* enc = internal encoder o/p, before mux */{est_0=>0;est_1=>1;est_2=>0;est_3=>1;est_4=>0;est_5=>1;est_6=>1;est_7=>0;}/*Switch ENC_OUT output according to whether test mode detected by decoder.The final encoder output is taken from the decoder output if the followingcondition is true:tmd=1 and sw=0 and !s7(encoder)The following statement could have been done as encoder:[enc_0..enc_6] butthat might not work if the states had funny binary codings. All depends onhow CUPL implements the enc_0..enc_6 range stuff.*/enc_not_s7 =encoder:est_0 #encoder:est_1 #encoder:est_2 #encoder:est_3 #encoder:est_4 #encoder:est_5 #encoder:est_6;enc_out_mux = TMD & !TEST_ENA & enc_not_s7;ENC_OUT = ( enc & !enc_out_mux ) # ( DEC_IN & enc_out_mux );/* ********************** DECODER *************************** */SEQUENCE decoder{/* wait for Din=1, then S1 */PRESENT dst_0IF DEC_INNEXT dst_1;DEFAULTNEXT dst_0;/* wait for Din=0, then S2 */PRESENT dst_1IF !DEC_INNEXT dst_2;DEFAULTNEXT dst_8;/* To S3, unless Din=1 so we have 101... & we have to test for TMD */PRESENT dst_2IF DEC_INNEXT dst_9;DEFAULTNEXT dst_3;/* wait for Din=1, then S4 */PRESENT dst_3IF DEC_INNEXT dst_4;DEFAULTNEXT dst_3;/* To S5 */PRESENT dst_4NEXT dst_5;/* if Din=1 now then it is a normal end (S6) & we go back to start (via S7) */PRESENT dst_5IF DEC_INNEXT dst_6;DEFAULTNEXT dst_10;/* back to start */PRESENT dst_6NEXT dst_7;PRESENT dst_7NEXT dst_0;/* Get here from S1 if we got 11 */PRESENT dst_8IF !DEC_INNEXT dst_3;/* 110, OK */DEFAULTNEXT dst_11;/* 111 i.e. crap *//* 101 detected, check for a 0, to make 1010 */PRESENT dst_9IF !DEC_INNEXT dst_12;DEFAULTNEXT dst_0;/* Get here from S5 if S5 just missed Din=1 so we recheck */PRESENT dst_10IF !DEC_INNEXT dst_3;DEFAULTNEXT dst_6;/* Get here from S8 if we see 111... - wait here until Din=0; thisprevents a persisting Dout=1 condition when a long Din=1 inputhas ended */PRESENT dst_11IF !DEC_INNEXT dst_0;DEFAULTNEXT dst_11;/* Get here from S9, having detected 1010, check for a 1 to make 10101 */PRESENT dst_12IF DEC_INNEXT dst_13;DEFAULTNEXT dst_0;/* TMD mode is 1 all the time we are in S13-S15. Any pattern is OK butwe exit to S0 on two consecutive 0 samples */PRESENT dst_13IF DEC_INNEXT dst_15;DEFAULTNEXT dst_14;PRESENT dst_14IF DEC_INNEXT dst_15;DEFAULTNEXT dst_0;/* exit */PRESENT dst_15IF DEC_INNEXT dst_13;DEFAULTNEXT dst_14;}/* Decode Decoder state machine Q3..0 D-types into DEC_OUT output */TABLEdecoder => dec/* dec = internal decoder o/p, before switch */{dst_0=>0;dst_1=>0;dst_2=>0;dst_3=>1;dst_4=>1;dst_5=>1;dst_6=>0;dst_7=>0;dst_8=>0;dst_9=>0;dst_10 =>0;dst_11 =>0;dst_12 =>0;dst_13 =>0;dst_14 =>0;dst_15 =>0;}/* Decode Decoder state machine Q3..0 D-types into TMD (Test Mode) output */TABLEdecoder => TMD{dst_0=>0;dst_1=>0;dst_2=>0;dst_3=>0;dst_4=>0;dst_5=>0;dst_6=>0;dst_7=>0;dst_8=>0;dst_9=>0;dst_10 =>0;dst_11 =>0;dst_12 =>0;dst_13 =>1;dst_14 =>1;dst_15 =>1;}/*Switch DEC_OUT output according to whether test mode detected by decoder.We force it to 0 if the Test switch is ON; this stops muck comingout of the DEC_OUT output if we are doing a *local* loopback, and it stopsmuck coming out of the local unit with remote loopback.Should not be necessary.*/DEC_OUT = dec & !TEST_ENA;/*NOTESThe RESET input is not really necessary, since the P3Z22V10 has apower-on reset (which works provided Vcc rise is monotonic). RESETmust be grounded on the package, or driven from a reset circuit.21/4/99: RESET is driven for a circuit which detects a break-leveldecoder output exceeding about 100ms; normally this would indicate adecoding fault.The PRESET input is also not necessary, but CUPL warns that the .SPsignals are undefined, and we have lots of spare inputs anyway.PRESET must be grounded on the package.To avoid logic hazard problems, the state bit patterns are arrangedso that whenever there is an asynchronous input (e.g. ENC_IN) only*one* D-type in the state machine changes state, i.e. Gray code.HOWEVER this scheme is not sufficient to avoid problems because whenCUPL compiles the state expressions it still generates equationswhere we have both "input" and "!input" affecting the same D-type,and there is an uncontrolled skew inside some 22V10 devices in theirinternal true/complement input generation. So externalsynchronisation is still required, is done with an HC74, so we maynot have bothered with the Gray code encoding. But its use doesimprove reliability, in fact the Philips P3Z22V10 was highly reliablewithout the HC74. The gray-code was abandoned in some places becausethere aren't enough states. Only some states actually need thegray-coded patterns anyway.Test Mode (TMD) is detected by initially looking for a 10101 patternand then hanging in there regardless of the data until a 00 issampled. The need to initially detect a 1010.. assumes a certainmismatch between the crystals of the two converters; otherwise aconstant 1111.. sampling is possible but this mismatch will alwaysoccur within a fraction of a second. It is no good looking for a 111..because this can occur at power-up.There are big problems exiting TMD, because of the way the signal islooped back in each of the two units. The things just keep loopingback to each other for ever. It is not enough to just stop theencoder encoding the 01010101... pattern when the button is notpressed any more, because of the pattern which is already in transitthrough the remote unit and which will continue to return to us for afew us longer, thus causing our local unit to remain in TMD mode.It was solved by the encoder waiting for button release, and by thedecoder testing for 101010... (not just a long high level) to detectTMD, and by bringing encoder state S7 into the encoder output mux.It is not necessary to use "SEQUENCED" (with "D" on the end) becauseCUPL knows the flip-flop type from the device name.*/It even has a LINE TEST feature which sends a special pattern which is looped back.

author: Doctorandus_P
author_rank: Super Contributor
timestamp: February 03, 2023, 07:02:14 pm
content: A simple way would be to just set the transmitter to ouput a square wave from a timer, and then every now and then have the other check if it still sees the sqare wave.But why use SFP in the first place? If you don't need the bandwidth then just use some cheap S/PDIF optical transmitter and receiver.Or you can DIY them by using a simple LED and foto diode spaced a few cm from each other (possibly wrapped in some dark shrink tube)Or use other "standard" parts. For example an optocoupler like CNY65 has a 3mm isolation distance which gives it a 0.3pF coupling capacitance and it can withstand 11kV.

author: Amper
author_rank: Frequent Contributor
timestamp: February 07, 2023, 09:27:07 am
content: Hi!The issue is "every now and then" which will still make it very busy if i dont want much latency. Goal is transmitting analog sensor data (and other data, serial port for the HP34970a and such).SFP are very nice because they are modular, standardized, there is fiber available, i own a splicer, they transmit >10km and so on. Of cause plastic would work, actually have a plastic rs232 adapter already but thats not what im looking for.Its supposed to be used not just for one specific task, thats also why the controller shouldnt be busy if possible. Two applications i have rn is lightning resistant transmisson of 4-20mA sensor data on a hydroelectric plant (water source to power house) and 180kV DC insulation on a small beam on target linear accelerator. In the second case id actually just use some esp32 over wifi but in case 1 burrying normal quarz fiber is more reliable.EDIT: Btw, rn im on the path to doing FSK, seems to be the most sensible path to go after asking a bunch of people and not having better ideas myself

author: dobsonr741
author_rank: Frequent Contributor
timestamp: February 07, 2023, 02:37:29 pm
content: How about implementing a Manchester encoder/decoder on a CPLD? The modern version of Peter-h’s 22V10. For example, 10MHz out when idle. A positive edge from the UART causes 2x wide high state, negative edge 2x wide low state on the outgoing train.If CPLD is a high learning curve, then a few D FF, XOR gate, non-retriggerable monostable would do.The 10MHz impulse train/sampling rate would not upset the UART up to 100kbaud, you can always go higher than 10MHz (with CPLD). I’d pick XC2C32 and verilog to implement it.

author: asmi
author_rank: Super Contributor
timestamp: February 07, 2023, 07:54:46 pm
content: Have you considered SPDIF optics instead of SFP? It seems to me that they are more suitable for the bitrate you are looking for, and still provide for a galvanic isolation.

author: dobsonr741
author_rank: Frequent Contributor
timestamp: February 07, 2023, 08:04:18 pm
content: SPDIF/TosLink parts are hard to find and expensive. They are phased out with HDMI taking over. There’s virtually no support to make custom cables - I’m skipping here buying off stuff from AliExpress.SFPs on the other hand are plenty, $10 will get you a BIDI transceiver, lots of sources for ready made patch cables and tools/field connectors to make a new cable.I’m running SPDIF signal though SFPs in my living room to feed surround speakers. It was such a surprise to find out a 1Gig SFP just runs fine at 6MHz.

author: Nominal Animal
author_rank: Super Contributor
timestamp: February 08, 2023, 02:35:20 am
content: TME does have Cliff OTJ-5 FCR684205T and OTJ-1 FCR6842031T Toslink transmitters in stock for an acceptable price (1.5€ + VAT), but the ORJ-3 FCR6842032R and ORJ-5 FCR684205R do cost almost double that (3€ + VAT). They can do 16 Mbit/s using NRZ, with roughly 50% on time.TME also has Cliff FC6842135TR in stock for ~ 6€+VAT apiece, which is basically a similar transmitter and a receiver in a single body that can be screwed to a panel.Some MCUs support sending BREAK characters continuously, which is one way one could use UART over Toslink without signal inversion. Each BREAK takes longer than a normal character, and keeps the line low except for the stop bit, so it can be used to reduce the overall on time (as the line idles high). It isn't NRZ, and the on/off ratio isn't near half, but I think keeping the transmitter average on time below 67% or so should work for Toslink just fine: essentially, it's just a very wide optocoupler, really.For example, on NXP i.MX RT1062 (Teensy 4.x), one can just set the SBK bit of the LPUART control register, and the UART will continuously send BREAK characters. On the receiving side, they read as all zeroes with a framing error, as usual.STM32L0 supports the same, SBKRQ bit of the USART_RQR or LPUART_RQR register.So, personally, I would use TOSLINK for this, because you'd only need two transmitters and two receivers (or two FC6842135TR) and two 100nF bypass capacitors, total; with standard Toslink cables up to 20m or so. TME even sells AVK-216-1000 (Goobay 50938), 10m Toslink cables, for 10€+VAT apiece; shorter ones much cheaper, of course. Each STM32L would send BREAK characters whenever it has no data to send.Then again, I'm just a hobbyist, and know nothing. I do have experimented with this before, years ago for a fusor project, but the others decided to go with a commercial optical RS-232 instead.

author: Amper
author_rank: Frequent Contributor
timestamp: February 08, 2023, 08:58:54 am
content: Can you buy kevlar armored toslink lines at >1km length?I think i already got into the why sfp.@dobsonr741fpga were suggested before but i dont see the point in that, it would make adapting the project to other applications very difficult. Im not trying so solve one specific problem and get a product out of it, i want a simple way of using sfp to transmit anything i want to from a microcontroller that can at the same time do other tasks. If i get a cpld im sure i can learn to implement the manchester encoding (most likely there is already some stuff out there i could copy) but im not planning on writing my own display drivers on cpld if i want to connect an oled.

author: Nominal Animal
author_rank: Super Contributor
timestamp: February 08, 2023, 03:43:58 pm
content: Quote from: Amper on February 08, 2023, 08:58:54 amYep, you did. (I kinda forgot, and focused on the isolation aspects you mentioned, because I've looked at Toslink for exactly that a few years ago.)Quote from: Amper on February 08, 2023, 08:58:54 amAs a non-EE hobbyist who likes to interface SBCs to various devices, I'd say it would be most useful if the SFP link could be treated as an UART or SPI link. That means that the FPGAs, CPLDs, or small microcontrollers at the link ends would only do conversion from the original UART/SPI datastream to Manchester encoding over the SFP link with idle/keepalive, to UART/SPI datastream. Link idle/keepalive would be transparent to the endpoints, and only the UART baud rate and format or SPI clock frequency would be fixed.In other words, the FPGA/CPLD/whatever would just be the interface between any microcontroller and the SFP link, hiding the complexity of using the SFP link effectively. You might even use a separate GPIO pin for power down.

author: Amper
author_rank: Frequent Contributor
timestamp: February 08, 2023, 05:51:50 pm
content: Which means id waste an entire controller to replace the fsk hardwareYes, possible but i wouldnt really call it elegant. Also doing 100kBaud tx AND RX to some external device while at the same time keeping the spf allive and doing bitwise machester will not be easy at the same time, they will bite each other. that would require buffering everything on both ends and then transmitting it which also sucks for just forwarding since tx to rx time may be critical. I guess ill try both methods, hardware wise i already got what i need for your version.

author: Siwastaja
author_rank: Super Contributor
timestamp: February 08, 2023, 06:03:02 pm
content: Quote from: Amper on February 08, 2023, 08:58:54 amThis simple way is indeed to use UART or SPI peripheral to send/receive manchester encoded bits, and let an ISR handle encode/decode for every 32 bits or so (using UART in FIFO mode, SPI with any bit length in FIFO mode, or SPI in 32-bit mode, if available, without FIFO mode). This way you offload the CPU quite a bit, and processing a single 32-bit word at once is more efficient than working with 8-bit interrupts, or even worse, bit-by-bit interrupts. Yet processing every 32 bits does not incur that much latency (compared to batch processing large DMA buffers).Rest of the application can run as usual, including interrupts. Wrap the whole thing in its own .c file and you can reuse it for many projects. If your application needs very low-latency interrupt processing for some certain things, which cannot wait for maybe 50 clock cycles of your encode/decode ISR, then just use higher interrupt priority for those things.

author: dobsonr741
author_rank: Frequent Contributor
timestamp: February 08, 2023, 07:16:41 pm
content: Amper, what FSK hardware are you thinking of?

author: nctnico
author_rank: Super Contributor
timestamp: February 08, 2023, 09:23:40 pm
content: @Amper: what other peripherals do you have in that microcontroller?