Week Four! How time flies, it’s been nearly a month since I first stepped into the office of Aeste. Continuing from our previous work of setting up a basic SPI bus between a Raspberry Pi (RPi) master and a PIC18 slave, we go on to write a function for the A/D converter and emulate an SPI Flash with the program memory of the PIC18. Since I finished these tasks slightly earlier than expected, we then tackle a third (bonus level!) task: emulating an Ethernet controller.
Click here to skip to the conclusion.
A crucial point for these functions is that they must all be accessible from the master, the RPi, using only the SPI connection. This will be similar to the final product, when the Spartan-6 (master) needs to go through the PIC18 to use its ADC, flash memory and Ethernet capabilities.
As such, it was decided that they ought to be three individual functions which can be called from the Main file. The PIC18 would read the data coming in from the SPI bus and run each function accordingly. The protocols for these processes need not be unique, and in fact it would be better if they resembled those used in common components in industry. In other words, each function should emulate established SPI devices.
Analogue-to-Digital Converter (ADC)
The pins of PORTA have the ability of acting as inputs to the ADC module on the PIC18. The module reads the voltage level at the pin (relative to VDD =3.3V) and converts it to a 10-bit value (stored in two addresses). The Microchip C18 library comes with an existing set of functions to control the ADC module, so creating a new function for the SPI master to access these ports was relatively straightforward.
This was tested using the 10k potentiometer on the PICDEM.Net2 development board, which simulates an analogue input to the RA9/AN2 pin on the PIC18. Although the ADC was successful in obtaining a reading between 1023 and 0, it was noted that the change in input voltage did not correspond to a linear change in reading (see Fig. 1). An attempt was made to use the in-built calibration function, but the PIC18 implemented by measuring and storing an offset value, subtracting it from future readings. This would also only deal with positive errors at “zero” input, not negative.
Fig. 1: Readings from the ADC module
The PIC18F67J60 has up to 128 kilobytes of on-chip program memory. Most of it will be required to contain its programming, but a portion can be reserved to emulate a Flash memory chip. Once again, there are existing functions in the C18 library that enable read, write and erase during normal operation of the PIC18. Since the erase function only works on blocks of 1024 bytes at a time, it was decided that the size of the memory should only be as much, from address 1F800h to 1FBFFh.
There are various popular SPI Flash Memory peripherals on the market, but they all share a standard list of instructions/SPI opcodes. For this project, the device that was selected to be modelled in particular would be the Serial Quad I/O (SQI) Flash Memory SST26VF016 from Microchip.
As can be seen in Code 2, the emulated Flash has merely four functions in reality. If the user sends any opcodes for unsupported functions, the flashSPI() program will return an arbitrary error code (defined elsewhere). Fig. 2 demonstrates a normal read operation
Fig. 2: (a) Reading the emulated Flash memory, and (b) the data in the memory registers as shown in MPLAB.
The ENC28J60 is a very popular discrete Ethernet controller module with SPI function from Microchip. It is very similar to the one in the PIC18, in that they share roughly the same features, PHY & control registers and bits. Hence, it was naturally the target for emulation in this project.
The data sheet gives a clear outline of the SPI command set for the ENC. However, a significant initial challenge is mapping the addresses of the device registers to the PIC18’s; the ENC has registers in 4 banks which are accessed using a 5-bit addresses but the PIC18 has one bank with 12-bit addresses. Moreover, some registers and bits are reserved/unimplemented in the PIC18. The Ethernet emulation function must thus be able to respond with the right (or fake) data when reading from or writing to the registers.
The full Ethernet controller function has yet to be completed, but the first out of seven functions, Read Control Register (opcode 000b), is as shown in Fig. 3.
Fig. 3: Reading the register ERDPTH
At present, the PIC18 will emulate an ADC module, Flash memory and Ethernet controller, and these will be its main functions when operating as the SPI slave to the Spartan-6 FPGA for the final product. The ADC may have some accuracy issues and the Flash memory is not a full emulation, but the overall functionality is demonstrated. I expect to do a bit more work on them especially in trying to tidy up and standardise the code to be more comprehensible, but the major hurdles are hopefully completed.
Next week! We try to wrap up the emulation of the Ethernet controller. However, a new challenger looms on the horizon, with letters in bold: “P C B”.