I'm currently evaluating if it would be possible to directly feed an ethernet PHY chip with RMII interface with the P2. For my CNC controller project I don't need a TCP/IP stack but access to raw ethernet packets. It would be possible to use a Wiznet W5500 or W6100 chip but, first, I don't want to be dependant on a particular supplier and, second, it's totally overkill in terms of money, board space and register/driver complexity. And third, bit banging the protocol may enable the implementation of EtherCAT, one day...
The RMII interface mainly uses a clock of 50MHz and two data lines to transfer a 100Mb/s data stream. Well, actally it's four data lines for full duplex RX/TX. The PHY chips have an "elastic" FIFO buffer to compensate frequency drifts from transmitter to receiver so that the data is always phase locked to the same local 50 MHz reference clock. This refernece clock could also be used as input to the PLL for the system clock of the P2 so we can use a fixed NCO divider and don't have to care about phase drift.
I think it should be possible to use either two cogs with streamers, one for transmitting and one for receiving, or one cog and four smart pins in synchronous serial mode. The two bits per clock could be split and merged with the SPLITW and MERGEW assembly commands. Or we could use a mix of the two methods, for example, using the streamer for transmitting and two smart pins for receiving.
i do think so. We are talking 100 MBIT/s, the CRC alone (4 bits every 2 clocks at best) demands it's share. copying the data all about the P2 doesn't help either. since normally you would want to buffer the data in HUBram, it's best to stream it directly from a register to HUBram once the CRC is done
i arrived at the conclusion that using a synchronous serial smartpin (no streamer) and a FIFO on the other end is the way to go
since you can delay the sending routine whenever you need, in between packets, you rather pack your high level stuff in the sending cog
Ah, interesting. A friend who has implemented the ethernet interface for an Amiga clone also send me a quote of a parallax forum thread although he didn't know anything obout the propeller at that time. Here are the specs: _rev12.pdf
So the LAN8720 seems to be a good choice.
So as the first thing I have to make some sort of evaluation/prototyping board. To keep all options available I have to be careful with the pin assignments. The propeller has unique flexibility and allows any single feature on any arbitrary pin but it still has some restrictions about pin grouping.
base is a pin number divisible by 8 to allow easy connection to an EVAL or KISS board. Every signal except RXER is within the +/-3 range from the clock pin. The management interface (register access) MDIO and MDC can be on any other pin pair.
If the 50MHz reference clock is used as PLL clock input and the system clock is a multiple of that I theoretically won't need another clock input pin at all. All data and status signals are synchronous so I could center the sampling time between the rising and falling edges. But that would mean I had to use the streamer for both sending and receiving. And cogs=streamers cost more than pins.
Receiving takes much more attention. AFAICS it is not possible to tell the length of the packet until it actually ends (DV is de-asserted). The other problem is that CRS is asserted asynchronously to the reference clock. So it is possible to get the synchronization wrong because the setup time for sampling is violated. In this case the first bit pair is shifted which can't be detected because all preamble bit pairs look the same ("555...") until the "D" nibble of the SFD is reached. Synchronization then needs to be corrected immediately to not miss the important destination address field which follows next.
All signals are sampled on the clock edge. some PHYs mux carrier detect & rx-valid on one line on alternating bits with respect to the nibble.
the packet error could be dealt with in an interrupt while packet reception itself needs to be done with 3 smartpins that are started on the same clock, synced to the start of your frame and read out at a constant rate. since you have to do that anyways you can do the crc in between and so stream the packet to HUB ram in quasi realtime. sending is easier and there is no need for precalculating the crc. forget about the streamer. there is so much you have to do to get the data ready for transmission which is calling for a dedicated cog
From the RMII spec:
CRS_DV is a combined signal of CRS (carrier sense) and DV (data valid). It becomes active immediately and asynchronously to the local clock as soon as carrier is sensed, i.e. a J/K code group is recognized. CRS becomes inactive earlier than DV because of the elastic FIFO buffer. In this case CRS_DV toggles at 25MHz at the end of a frame.
The streamer (technically the FIFO) steals hubRAM cycles only as needed on a per clock cycle basis. Cog can still run as normal in parallel, including block copies to and from hubRAM. Combined hubRAM bandwidth of the pair is 32-bits per clock cycle. There is no lose of available bandwidth when shared.
I changed the 50MHz oscillator for a plain 25MHz crystal and it immediately works. I don't know how this was supposed to be, originally. I know I could have bought a cheap clone board but the 50MHz oscillator is even in the original Waveshare schematic. This would never work. You could use the 50MHz oscillator as external reference clock in the case that the REF_CLK pin is instead used as nINT output. There's actually a jumper (optional 33 ohm resistor) for this signal path. But the LAN8720A will never work without 25MHz at CLKIN/XTAL1. XTAKL2 is not even connected to anything.
EDIT2: Well, it's really good news that the Prop2 can supply the reference clock. This makes the bit timings much easier to manage. If the reference clock was derived from the incoming Ethernet clocking then you'd be in trouble.
The LAN8720 only has a REF_CLK output, no input. The P2 could supply the 25MHz crystal clock but that wouldn't save anything. You'd still need the 50MHz reference because you don't know the phase relationship and the TX/TX data is synchronous to the 50MHz clock. So it's better to connect the crystal to the LAN8720A and use the 50MHz clock to feed the XIN input of the P2. So both run synchronously, say, the P2 at a multiple of 50MHz like 200 or 250MHz.
The receiver has a PLL to retrieve the original frequency of the transmitter (remote clock) but that signal is not brought out. Instead, an "elastic" FIFO is used with the remote frequency clocking the input and the local 50MHz clocking the output. CRS_DV is not signaled before the FIFO is half full. This is relatively clever and ensures that the RMII interface is always synchronous to the local clock.
Well, the attribute "wiser" depends on the requirements. Yes, if 10Mbit/s half duplex with no automatic cross over (pair swap) detection is enough for you then the ENC28J60 is a good solution. I've used it for the P1 with great success (>5k units build) for almost 10 years, now. But I think the P2 deserves something newer with a little bit more power. And my personal challange is to write a driver for a 100M ethernet device that consists of less "lines of code" than the ENC28J60 errata sheet.
Ok, the next step is trying to capture packets on the receiver side. What makes me wonder is that CRS_DV is high almost all the time after the link is up and auto-negotiation is complete. There are only very narrow low-pulses of two or four clock periods. The LAN8720 is connected to a Netgear switch which is connected to a PC but without any data traffic. The LED at the switch flashes from time to time I think because of windows scanning for new devices, ARP activity and so on.
3.7.4.1 REF_CLK In Mode
In REF_CLK In Mode, the 50MHz REF_CLK is driven on the XTAL1/CLKIN pin. A 50MHz source for REF_CLK must
be available external to the device when using this mode. The clock is driven to both the MAC and PHY as shown in
Figure 3-7.
Like many I find something extremely satisfying about watching light displays in awe. From bonfire night fireworks to pretty in game graphics and even an 8x8x8 RGB LED cube I built back in 2013.
I have had many attempts at a reliable RGB propeller clock over the years and though I have had many prototypes up and running they never seemed to stay working for long or be good enough for me to shout about. This is my attempt at a stable design that should last for a long time.
The display features 24 x RGB LEDs, provides a flicker free image to the human eye and is powerful enough to display and manipulate simple 3D meshes in real time. Also included are timing mechanisms to drive a clock and synchronization mechanisms to keep the image stable independent of the motor speed.
A propeller display is made up of a single row of LEDs that are spun by a motor. As the motor spins the LEDs the LEDs switch on and off at high speed allowing a stable image to be displayed within the arc of the LEDs.
A micocontroller brain is used to switch the LEDs on and off at the right moment to draw the image. As the circuitry spins around an onboard sensor such as a hall effect or IR beam breaker is used to synchronize the microcontroller and keep the displayed image static.
In my experience as an embedded engineer the tricky part is not the circuitry but the mechanics. Mainly picking the right motor for the job and creating a way of passing power to the circuity as it spins.
The LEDs are driven using a simple buffering system using cheap and cheerful 74 series octal buffer chips. There are some nice LED driver chips available now but if you know what your doing and have plenty of processing power in your microcontroller then these are not a necessity.
The LEDs I used are very small SMD type common anode LEDs I bought from Farnell. They were expensive but come complete with a lense and look very good lit up. They are also very small, I originally tried a display of 32 LEDs using a much bigger LED and though this worked very well it was a bit too large to be spinning at high speed without any safety cage.
To drive the LEDs I use 8 data pins from the microcontroller and a clock pin. The 8 data pins are connected to the input of the first octal buffer IC and the cathodes of the first 8 LEDs. The 8 outputs from the first buffer IC are then fed to the 8 inputs of the second buffer IC and the cathodes of the second 8 LEDs. The clock signal is fed to all of the buffer ICs so that they all clock together at the same time. Using this technique you get (8 + 1) * 8 = 72 bits of control or 72 / 3 = 24 RGB LEDs. If 11 buffer ICs were used then the number of RGB LEDs goes up to 32.
The LED anode pins are all connected together and then fed to the drain pin of a logic level P channel FET. This allows all the LEDs to be switched off as we clock out the data. Without the FET you tend to get some light smeared over the inner display when the outer display is lit which is best avoided. This smearing effect is shown in the image.
The red LEDs have a lower driver voltage than the green and blue channels so the resistors are there to allow the colour intensity to remain uniform for all three colours.
Of course you don't have to use RGB LEDs, normal LEDs will work just as well and give you 3 x the resolution for the same number of control signals. I'm just a sucker for the pretty colours.