Xilinx Portable Calendar Viewer
Design of a Portable Calendar ViewerFinal Project Report Pmod Device Drivers on a Zynq?-7000 All-Programmable SoC on a ZedBoard MicrocontrollerBailey Hulsey , Shalin Shah, Sarat Bhargava, Gaurav Bansal, Rakshita Nagalla, Walter OjiXilinx Inc.: Chandra Sekar Balakrishnan (chandra.sekar.balakrishnan@) AbstractThis paper delineates the design and the importance of a Portable Calendar Viewer (PCV) implemented using an All-Programmable System on a Chip (SoC) called the Zynq 7000. This viewer was created to access a calendar either online through a Wi-Fi connection or from a calendar on a Bluetooth device directly then display the latest few calendar events on an OLED (Organic Light Emitting Diode) screen. A hardware description language (HDL) was used in a programming environment called Vivado to design the optimum connections from the Zynq processor to the peripherals on a developmental microcontroller known as the ZedBoard. Next, the drivers for the OLED, the Bluetooth interface, and the Wi-Fi interface, which are all connected to the ZedBoard using PMOD ports, will all be written in C programming language. At the time of the completion of this second project report, only an initial draft of the code for only the OLED driver has been written, but without certain Xilinx licenses, we are unable to test, debug, or configure the code to our certain specifications. Finally, the system will be designed in a Linux environment known as PetaLinux SDK and dumped to the board after the PetaLinux Kernel will be booted from the hard drive flashed from a USB connected PC. By learning these languages and the schematics of our hardware, we were able to generate drivers for PMOD devices that will most certainly be implemented in the future Xilinx projects.IntroductionThe most central component, the ZedBoard, is a microcontroller powered by Zynq?-7000 All-Programmable SoC XC7Z020-CLG484-1 microprocessor. It has a 512 Mb DDR3, 256 Mb Quad-SPI Flash and a 4GB SD card. The ZedBoard can communicate using many connections including Ethernet, JTAG USB, USB OTG 2.0, USB-UART and FMC-LPC connectors, 5 Pmod compatible headers and AMS heads among others. Out of all these, we will be using 3 Pmod headers, with the ZedBoard pins JA1, JB1 and JD1, for Pmod BT2 Bluetooth interface, PmodWifi-802.11b Wi-Fi Interface and Pmod OLED respectively. The ZedBoard clock source ticks at 33.3333 MHz for PS (Processor Subsystem) and a default of 100 MHz, although configurable, for PL (Programmable Logic). Being multifunctional, ZedBoard also provides an option of HDMI output supporting 1080p60 16-bit, VGA output of 12-bit resolution color and an on-board 128*32 OLED display, among many others. The Xilinx Platform Cable JTAG connector and the onboard USB-JTAG interface is connected to external devices like PC’s for debugging and configuration. This function will also be used in our system to initially install the application image on the ZedBoard’s hard drive.When configuring our hardware, we have included connections from the Zynq chip to our peripherals – the three external Pmod devices (OLED, Wi-Fi, and Bluetooth), two on-board navigational buttons, one on-board select button, and seven-on board LED’s. The basic top level layout of our device and the above listed peripherals is as follows. When we switch ON the power, the Pmod OLED shows a welcome screen. Next, it gives the user 2 options i.e. Bluetooth and Wi-Fi. Using the on-board navigation buttons – Up (ZedBoard port T18) and Down (R16) – a graphical representation of selection like an underline will cycle through the choices for the user to select using the Select Button (P16). Then the user selects Bluetooth to choose to get the calendar entries from a Bluetooth device or Wi-Fi from an internet database. If the user selects Bluetooth, the on-board LED LD0 (T22) will turn on. Now the OLED will show the available devices for the user to select, and as the user selects one, the Pmod BT2 will try to make the connection with that device. To access the connection, the user will use the on-board enabled buttons to enter the password and the Select Button to pair with the device. On successful connection, the LD1 (T21) will glow. Now the data transmission will take place between the two devices, and whenever data is successfully received, LD2 (U22) will glow. The payload will then be transferred from the Pmod BT2 peripheral through the SPI interface, and after being processed by the Zynq chip, the contained calendar event will be displayed on the OLED.If the user instead selects Wi-Fi, LD4 (V22) will turn on. After this option is selected, the OLED will show the available networks. When the user selects a network, he will be prompted to enter the password in the way as entering the Bluetooth password. Upon successful connection, LD5 (W22) will glow. In our driver, we would have already hardcoded the specific website containing the calendar entries, and the system will use a direct command to fetch them. Now as the data transmission takes place, LD6 (U19) will be turned on. The data here will be received by Pmod Wi-Fi 802.11b module according to the Wi-Fi protocol, then transferred to the Zynq chip through the SPI interface, and after being processed, it will be displayed on the OLED. Finally, the user will be able to navigate to the next and previous calendar events using the aforementioned on-board directional buttons.Background and TerminologyThe tools we are using to develop the PCV are the Vivado Design Suite software, which programmers can use to reconfigure the internal connectivity of the Zynq All-Programmable SoC, and PetaLinux SDK (Software Development Kit), where the final application will be written and whose kernel our project will run on. Both of these development applications are owned and commercially distributed by Xilinx, but the majority of the source code for our drivers will be written in C from a simple text editor or C programming IDE.The Zynq 7000 is utilizing fully programmable hardware. Its creator imagined a customizable piece of hardware that would allow programmers to configure the board in a unique way to suit their specific needs. The PL of this chip is similar to an FPGA while the performance is more similar to a non-programmable ASIC SoC; thus, the Zynq chip affords a hardware-writable system which can be programmed using a Hardware Description Language (HDL) like VHDL or Verilog. The hardware of the Zynq chip was programmed in a graphical programming environment called the Vivado Design Suite where we created a block design, which is used to set the board’s configuration. It’s a graphical representation of the connectivity inside the Zynq chip with IP’s (Intellectual Properties) existing as blocks to represent the components of the board and its ports to peripheral access. One of these IP’s, the AXI interconnect, links the Zynq 7000 chip to the other IP’s. It takes care of all of the interactions between the Zynq chip and the rest of the components on the board. For our particular project, we required the use of certain peripheral ports on the ZedBoard in order to attach the Wi-Fi Pmod, OLED Pmod, and the Bluetooth Pmod. Part of the activation process for the ports involves enabling specific pins using an XDC (Xilinx Design Constraint) file. The XDC file simply allow us to interact with the hardware at the pin level, and give us precise control over where exactly our hardware will connect. We used the Verilog HDL to create this constraint file.Pmod interface is a specific peripheral hardware standard, congruent with USB or VGA, that is used primarily with FPGA’s. The Wi-Fi Pmod reads the RF (Radio Frequency) transmission from a connected network. The Bluetooth Pmod also sends and receives RF data but from another Bluetooth device over a paired point-to-point network. The OLED (Organic Light Emitting Diode) Pmod is used as a display interface. After we successfully connected and enabled all of the necessary components, we began to work on creating the device drivers that will enable our BT Pmod and our Wi-Fi Pmod to function properly with other Bluetooth devices and web resources respectively.Here is a brief description about the Pmod peripherals, starting with a description about the Pmod port on the ZedBoard. The ZedBoard has a total of 5 Pmod connectors of which four Pmod connectors interface to the PL-side of the EPP (Enhanced Parallel Port) of the Zynq microprocessor, and one is connected to the PS -side through the MIO interface. We are going to use 3 of the 4 Pmods connected to the PL-side. Each Pmod connector has 12 pins of which 4 are for power (2 are +3.3 V and 2 are for ground) and the rest of them are for transferring the data. In total there are 8 pins for a Pmod connector that are used for the data transfer. Figure SEQ Figure \* ARABIC 1 - ZedBoard's Pmod ConnectorPmod OLED (organic LED) has a SPI controlled monochrome display of 128*32 pixel screen. It can be operated at a maximum clock speed of 10MHz which has internal buffer to store the data. The following image describes which pin on the external Pmod OLED device corresponds to which function once connected to the microcontroller. Table SEQ Table \* ARABIC 1 - Pmod OLED Pin SpecificationsThe D/C signal determines whether the Pmod OLED is in display mode or command (if the d/c pin signal is high then OLED is given access to the display mode or if zero command mode) Res pin is the reset pin it is active low type. The Chip Select (CS) pin should be low to receive data over SPI interface. The following is the Power on and off sequence of Pmod OLED: 1) Apply power to VDD. 2) Send Display OFF command. 3) Initialize display to desired operating mode. 4) Clear screen. 5) Apply power to VBAT. 6) Delay 100ms. 7) Send Display ON command. And the power-off sequence continues as follows. 1) Send Display OFF command. 2) Power off VBAT. 3) Delay 100ms. 4) Power off VDD.The next image includes the specifications for the Pmod Wi-Fi device.Table SEQ Table \* ARABIC 2 - Pmod Wi-Fi Pin SpecificationsThe Pmod Wi-Fi device uses IEEE 802.11-compliant RF transceiver for receiving the data. It can support a data rate b/w 1 and 2Mbps and works in a range of up to 400m. The primary communications interface with the Pmod Wi-Fi is an SPI bus. It works up to a clock frequency of 25MHz. The Pmod Wi-Fi supports a voltage b/w 2.7V and 3.3V. So this is also 12pin device as the other Pmods with 4 pins for the power. In order to get the data from the internet the slave select should be high (SS = high) and active low reset (RST = low).The Pmod Bluetooth employs the Roving Networks RN-42 to create a fully integrated Bluetooth interface. The Pmod Bluetooth uses a standard 12-pin connection and communicates via a simple UART interface. There is also a secondary SPI header on the board for updating the RN-42 firmware if needed. The Pmod BT2 has several modes available to the user via the jumper settings. JP1 through JP4 provide various modes of operation as indicated in the table below. Table SEQ Table \* ARABIC 3 - Pmod Bluetooth Jumper SpecificationsEach jumper is active when shorted. JP1 restores the device to factory default settings after three transitions of the jumper setting .After the 3rd transition, the device returns to factory default except for the Bluetooth name. The other 3 jumpers, JP2-JP4, only sample in the first 500 ms of operation to allow the pins that they tie to on the RN-42 module to serve a separate purpose. JP2 enables pairing with a special device class defined by the user in software. JP3 enables auto connect to a stored address defined by the user. JP4 chooses whether to operate at the stored baud rate (115.2 Kbps default) or a baud rate of 9600 regardless of the software selected rate when shorted. By default, the UART uses a baud rate of 115.2 Kbps, 8 data bits, no parity and a single stop bit. The pin descriptions are given in the table as below:Table SEQ Table \* ARABIC 4 - Pmod Bluetooth Pin SpecificationsIn order to enter the command mode, the PmodBT2 must receive “$$$” to which it will respond “CMD”. When in command mode, the module will respond to a large number of commands allowing the user to customizing the module for specific applications. In order to exit command mode, send “---<cr>” (three minus signs in a row and where <cr> stands for the carriage return character) to which the device will respond “END”.2 for updating the RN-42 firmware if needed . and communicates via a simple UART interface . orresponding pins of theWe will next be creating the device drivers within the C programming language and the top-level system in PetaLinux user-space I/O environment.Problem StatementOur Portable calendar viewer accesses the calendar information either from the calendar on a Bluetooth device or from the online calendar via a Wi-Fi connection as per the user’s choice and displays the information on the OLED display connected externally to the ZedBoard. The calendar information for the next two hours can be accessed by using the navigation push buttons. The hardware of the project includes the ZedBoard with an embedded Zynq SoC and external PMODs, OLED, BT, and Wi-Fi, and the software includes the device drivers developed in C language and the overall system design in PetaLinux Userspace environment. The application can be used to design portable gadgets that allow the user to access information about the events through Wi-Fi or Bluetooth as per the user’s requirement.Solution – Design and ImplementationThe solution can be divided into three parts: Hardware block design, writing and testing of the drivers (Software part) and the final top-level application development. First, the Hardware Block Design was first created as a rough draft in SnagIt Editor where we only included the important blocks/IP’s. Then, we figured out the one-to-one connections of the 3 ZedBoard Pmod Ports with the corresponding Zynq EPP pins from the ZedBoard schematic. Using the pin data collected, we created a more detailed block diagram in the Vivado Design Suite 2013.3. In the block diagram, initially we used 1 AXI interconnect for connecting the Zynq (master) with its two slave IPs (AXI_UARTLite and QUAD_SPI). These two IP’s were in turn connected to the 3 Pmods and two GPIO ports (which acted as slaves). The Bluetooth Pmod was connected to the AXIUARTLite IP and the Wi-Fi and OLED Pmods were connected to the QUAD_SPI IP because the two connections use two different interfaces and thus need two different IP’s in the Vivado block diagram implementation. Also, we encountered a problem with the processor speeds of these two connection interfaces. To solve this problem, we included a second AXI interconnect IP to our block diagram whose clock rate we were able to modify before using it to connect the alternative connection port to the Zynq processor.The XDC file was then created. The pins are configured as either input or output using the I/O Planner. In case of the reset pin, either a pull-up or pull-down resistor has to be activated. Once the XDC file is saved and the design is synthesized, a bit file can be instantly generated as an output product from Vivado. This file can later be imported to the Zynq chip by PetaLinux where it will reconfigure the connections in Zynq chip’s PS block and program the IP’s in the PL block.Finally, after the hardware is initialized correctly, the software must be developed. First, each device driver needs to be developed so that the application can access information that the Pmod BT and the Pmod Wi-Fi receive as well as deliver the results of the calendar events to the Pmod OLED. These drivers are really a list of the functions that the application will call to interact with the hardware peripherals, specifically the Pmod IO devices. This is perhaps the most externally impactful implementation of our design. Sekar mentioned that the very purpose of our project is for us to develop drivers for these devices that can then be utilized in many other applications in further projects with global significance. The creation of this portion of the project will require run-time debugging on the ZedBoard from a PetaLinux shell on a PC along with much research into the fields of networking, embedded systems, debugging, and device driver format.As of the point in time when this second project report was written, we have written code for the Wi-Fi driver since we have received the Wi-Fi interface device. However, since we don’t have the licenses for PetaLinux, we are unsure how well this code will work. The code is included below:left230505/**in this file i am going to mmap all the pins that are going to be used in my oled project ** as i am using a linux based embedded system *///headers need to run the mmap fn.#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/mman.h>#include <fcntl.h>#include "SPI.h"#include <stdlib.h> //as c99 is used.//preprocessor directives#define GPIO_MAP_SIZE 0x10000int main(){ //in this fn i am going to mmap the first extra_Oled so that i can access the data register to write. int32_t ptr1;int32_t ptr2;//fd1 for extra oled device file.//fd2 for oled device file. int fd1 , fd2; fd1 = open(uio1,O_RDWR); fd2 = open(uio2,O_RDWR);ptr1 = (int32_t)mmap(NULL, GPIO_MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0); ptr2 = (int32_t)mmap(NULL,GPIO_MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd2,0);}….00/**in this file i am going to mmap all the pins that are going to be used in my oled project ** as i am using a linux based embedded system *///headers need to run the mmap fn.#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/mman.h>#include <fcntl.h>#include "SPI.h"#include <stdlib.h> //as c99 is used.//preprocessor directives#define GPIO_MAP_SIZE 0x10000int main(){ //in this fn i am going to mmap the first extra_Oled so that i can access the data register to write. int32_t ptr1;int32_t ptr2;//fd1 for extra oled device file.//fd2 for oled device file. int fd1 , fd2; fd1 = open(uio1,O_RDWR); fd2 = open(uio2,O_RDWR);ptr1 = (int32_t)mmap(NULL, GPIO_MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0); ptr2 = (int32_t)mmap(NULL,GPIO_MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd2,0);}….SPI.c:-247650180975…..void DCClearBit(void){ PMODOLED_CMD_DATA = PMODOLED_CMD_DATA & ~(0x01); //in this register bit 0 is to be made 0 to indicate CMD mode.}void VDDSetBit(void){ PMODOLED_CMD_DATA = PMODOLED_CMD_DATA | 0x02; //in this register bit 1 is to be made 1 1st step in power sequence.}void SSClearBit(void){ // i have to set the 0th bit of the slave select register to 0. PMODOLED_SS = PMODOLED_SS & ~(0x01);}void PORTClearBits(unsigned int32_t* pointer , int8_t bitno) //THE 2 PARAMETERS THAT R GIVEN R POINTER FOR THE REGISTER AND which bit in it.{ *pointer = (*pointer) & ~(1<<bitno);}void PORTSetBits(unsigned int32_t* pointer , int8_t bitno) //THE 2 PARAMETERS THAT R GIVEN R POINTER FOR THE REGISTER AND which bit in it.{ *pointer = (*pointer) | (1<<bitno);}00…..void DCClearBit(void){ PMODOLED_CMD_DATA = PMODOLED_CMD_DATA & ~(0x01); //in this register bit 0 is to be made 0 to indicate CMD mode.}void VDDSetBit(void){ PMODOLED_CMD_DATA = PMODOLED_CMD_DATA | 0x02; //in this register bit 1 is to be made 1 1st step in power sequence.}void SSClearBit(void){ // i have to set the 0th bit of the slave select register to 0. PMODOLED_SS = PMODOLED_SS & ~(0x01);}void PORTClearBits(unsigned int32_t* pointer , int8_t bitno) //THE 2 PARAMETERS THAT R GIVEN R POINTER FOR THE REGISTER AND which bit in it.{ *pointer = (*pointer) & ~(1<<bitno);}void PORTSetBits(unsigned int32_t* pointer , int8_t bitno) //THE 2 PARAMETERS THAT R GIVEN R POINTER FOR THE REGISTER AND which bit in it.{ *pointer = (*pointer) | (1<<bitno);}-171450285750/* ---------------------------------------------------------------------------------------- *//*Include File Definitions *//* ---------------------------------------------------------------------------------------- */#include "PmodOLED.h"#include "OledChar.h"#include "OledGrph.h"#include "SPI.h"#include "delay.h"/* ---------------------------------------------------------------------------------------- *//*Local Type Definitions *//* ---------------------------------------------------------------------------------------- */#definecmdOledDisplayOn0xAF#definecmdOledDisplayOff0xAE#definecmdOledSegRemap0xA1//map column 127 to SEG0#definecmdOledComDir0xC8//scan from COM[N-1] to COM0#definecmdOledComConfig0xDA//set COM hardware configuration/* ---------------------------------------------------------------------------------------- *//*Global Variables *//* ---------------------------------------------------------------------------------------- */extern charrgbOledFont0[];extern charrgbOledFontUser[];extern charrgbFillPat[];extern intxchOledMax;extern intychOledMax;/* Coordinates of current pixel location on the display. The origin** is at the upper left of the display. X increases to the right** and y increases going down.*/intxcoOledCur;intycoOledCur;char *pbOledCur;//address of byte corresponding to current locationintbnOledCur;//bit number of bit corresponding to current locationcharclrOledCur;//drawing color to usechar *pbOledPatCur;//current fill pattern…00/* ---------------------------------------------------------------------------------------- *//*Include File Definitions *//* ---------------------------------------------------------------------------------------- */#include "PmodOLED.h"#include "OledChar.h"#include "OledGrph.h"#include "SPI.h"#include "delay.h"/* ---------------------------------------------------------------------------------------- *//*Local Type Definitions *//* ---------------------------------------------------------------------------------------- */#definecmdOledDisplayOn0xAF#definecmdOledDisplayOff0xAE#definecmdOledSegRemap0xA1//map column 127 to SEG0#definecmdOledComDir0xC8//scan from COM[N-1] to COM0#definecmdOledComConfig0xDA//set COM hardware configuration/* ---------------------------------------------------------------------------------------- *//*Global Variables *//* ---------------------------------------------------------------------------------------- */extern charrgbOledFont0[];extern charrgbOledFontUser[];extern charrgbFillPat[];extern intxchOledMax;extern intychOledMax;/* Coordinates of current pixel location on the display. The origin** is at the upper left of the display. X increases to the right** and y increases going down.*/intxcoOledCur;intycoOledCur;char *pbOledCur;//address of byte corresponding to current locationintbnOledCur;//bit number of bit corresponding to current locationcharclrOledCur;//drawing color to usechar *pbOledPatCur;//current fill pattern…PmodOLED.c-1047750…/* ---------------------------------------------------------------------------------------- *//* Local Variables *//* ---------------------------------------------------------------------------------------- *//* This array is the offscreen frame buffer used for rendering.** It isn't possible to read back frome the OLED display device,** so display data is rendered into this offscreen buffer and then** copied to the display.*/charrgbOledBmp[cbOledDispMax]; //what ever i am going to write is // going to be done in buffer first and later update the screen/* ---------------------------------------------------------------------------------------- *//*Forward Declarations *//* ---------------------------------------------------------------------------------------- */voidOledHostInit();voidOledDevInit();voidOledDvrInit();charSpi2PutByte(char bVal);voidOledPutBuffer(int cb, char * rgbTx);/* ---------------------------------------------------------------------------------------- *//*Procedure Definitions *//* ---------------------------------------------------------------------------------------- *//***OledInit**Parameters:**none**Return Value:**none**Errors:**none**Description:**Initialize the OLED display subsystem.*/void OledInit(){// Init the PIC32 peripherals used to talk to the display.OledHostInit(); // i have to change this completely//Init the memory variables used to control access to the display.OledDvrInit(); //I THINK THERE IS NOTHING TO CHANGE HERE FOR ME.// Init the OLED display hardware.OledDevInit();// Clear the display.OledClear();}…00…/* ---------------------------------------------------------------------------------------- *//* Local Variables *//* ---------------------------------------------------------------------------------------- *//* This array is the offscreen frame buffer used for rendering.** It isn't possible to read back frome the OLED display device,** so display data is rendered into this offscreen buffer and then** copied to the display.*/charrgbOledBmp[cbOledDispMax]; //what ever i am going to write is // going to be done in buffer first and later update the screen/* ---------------------------------------------------------------------------------------- *//*Forward Declarations *//* ---------------------------------------------------------------------------------------- */voidOledHostInit();voidOledDevInit();voidOledDvrInit();charSpi2PutByte(char bVal);voidOledPutBuffer(int cb, char * rgbTx);/* ---------------------------------------------------------------------------------------- *//*Procedure Definitions *//* ---------------------------------------------------------------------------------------- *//***OledInit**Parameters:**none**Return Value:**none**Errors:**none**Description:**Initialize the OLED display subsystem.*/void OledInit(){// Init the PIC32 peripherals used to talk to the display.OledHostInit(); // i have to change this completely//Init the memory variables used to control access to the display.OledDvrInit(); //I THINK THERE IS NOTHING TO CHANGE HERE FOR ME.// Init the OLED display hardware.OledDevInit();// Clear the display.OledClear();}…-933450…/* ------------------------------------------------------------ *//***OledHostInit**Parameters:**none**Return Value:**none**Errors:**none**Description:**Perform PIC32 device initialization to prepare for use**of the OLED display.**This is currently hard coded for the Cerebot 32MX4 and**SPI2. This needs to be generalized.*/void OledHostInit(){ volatile int delay; //In this subroutine i am going to initialise the I.P PMODOLED_SRR_R = PMODOLED_SRR_R | 0x0a; delay = 100; //wait for the 4 clk cycles //now as we have done reset all the registers //ctl and status registers take the default values. PMODOLED_CTRL = PMODOLED_CTRL & ~0x100; //makes master transactions enabled PMODOLED_CTRL = PMODOLED_CTRL | 0x60; //reset teceive and transmit fifo delay = 150; //wait for 1 clk cycle. //loop back can be used the 0th bit when set the //transmition is connected to receiver. PMODOLED_CTRL = PMODOLED_CTRL | 0x01;}/***OledDisplayOn**Parameters:**none**Return Value:**none**Errors:**none**Description:**Turn the display on. This assumes that the display has**already been powered on and initialized. All it does**is send the display on command.*/void OledDisplayOn(){ PORTClearBit(prtDataCmd,bitDataCmd);Spi2PutByte(cmdOledDisplayOn);}…00…/* ------------------------------------------------------------ *//***OledHostInit**Parameters:**none**Return Value:**none**Errors:**none**Description:**Perform PIC32 device initialization to prepare for use**of the OLED display.**This is currently hard coded for the Cerebot 32MX4 and**SPI2. This needs to be generalized.*/void OledHostInit(){ volatile int delay; //In this subroutine i am going to initialise the I.P PMODOLED_SRR_R = PMODOLED_SRR_R | 0x0a; delay = 100; //wait for the 4 clk cycles //now as we have done reset all the registers //ctl and status registers take the default values. PMODOLED_CTRL = PMODOLED_CTRL & ~0x100; //makes master transactions enabled PMODOLED_CTRL = PMODOLED_CTRL | 0x60; //reset teceive and transmit fifo delay = 150; //wait for 1 clk cycle. //loop back can be used the 0th bit when set the //transmition is connected to receiver. PMODOLED_CTRL = PMODOLED_CTRL | 0x01;}/***OledDisplayOn**Parameters:**none**Return Value:**none**Errors:**none**Description:**Turn the display on. This assumes that the display has**already been powered on and initialized. All it does**is send the display on command.*/void OledDisplayOn(){ PORTClearBit(prtDataCmd,bitDataCmd);Spi2PutByte(cmdOledDisplayOn);}…left186055…/* ------------------------------------------------------------ *//***OledDvrInit**Parameters:**none**Return Value:**none**Errors:**none**Description:**Initialize the OLED software system*/void OledDvrInit(){ int ib;// Init the parameters for the default fontdxcoOledFontCur = cbOledChar;dycoOledFontCur = 8;pbOledFontCur = rgbOledFont0;pbOledFontUser = rgbOledFontUser;for (ib = 0; ib < cbOledFontUser; ib++) {rgbOledFontUser[ib] = 0;}xchOledMax = ccolOledMax / dxcoOledFontCur;ychOledMax = crowOledMax / dycoOledFontCur;// Set the default character cursor position.OledSetCursor(0, 0);// Set the default foreground draw color and fill patternclrOledCur = 0x01;pbOledPatCur = rgbFillPat;OledSetDrawMode(modOledSet);// Default the character routines to automatically update the display.fOledCharUpdate = 1;}…020000…/* ------------------------------------------------------------ *//***OledDvrInit**Parameters:**none**Return Value:**none**Errors:**none**Description:**Initialize the OLED software system*/void OledDvrInit(){ int ib;// Init the parameters for the default fontdxcoOledFontCur = cbOledChar;dycoOledFontCur = 8;pbOledFontCur = rgbOledFont0;pbOledFontUser = rgbOledFontUser;for (ib = 0; ib < cbOledFontUser; ib++) {rgbOledFontUser[ib] = 0;}xchOledMax = ccolOledMax / dxcoOledFontCur;ychOledMax = crowOledMax / dycoOledFontCur;// Set the default character cursor position.OledSetCursor(0, 0);// Set the default foreground draw color and fill patternclrOledCur = 0x01;pbOledPatCur = rgbFillPat;OledSetDrawMode(modOledSet);// Default the character routines to automatically update the display.fOledCharUpdate = 1;}…927100…/* ------------------------------------------------------------ *//***OledDevInit**Parameters: none**Return Value: none**Errors: none**Description:**Initialize the OLED display controller and turn the display on.*/void OledDevInit(){// We're going to be sending commands, so clear the Data/Cmd bitDCClearBit(); //prtDataCmd IS THE ADDRESS OF THE PIN DATA/CMD //WE Have to write a 0 to this bit to say that it is 0 cmd.// Start by turning VDD on and wait a while for the power to come up.VDDSetBit(); //in this subroutine i will make the VDD bit i.e 1st bit(not 0th bit)to 1.DelayMs(5); //i need clk speed to implement this routine.// Display off commandSpi2PutByte(0xAE);// Bring Reset low and then highPORTClearBits(prtReset, bitReset);DelayMs(1);PORTSetBits(prtReset, bitReset);// Send the Set Charge Pump and Set Pre-Charge Period commandsSpi2PutByte(0x8D);Spi2PutByte(0x14);Spi2PutByte(0xD9);Spi2PutByte(0xF1);// Turn on VCC and wait 100msPORTSetBits(prtVbatCtrl, bitVbatCtrl);DelayMs(100);// Send the commands to invert the display.Spi2PutByte(0xA1);//remap columnsSpi2PutByte(0xC8);//remap the rows// Send the commands to select sequential COM configurationSpi2PutByte(0xDA);//set COM configuration commandSpi2PutByte(0x20);//sequential COM, left/right remap enabled// Send Display On commandSpi2PutByte(0xAF);}…00…/* ------------------------------------------------------------ *//***OledDevInit**Parameters: none**Return Value: none**Errors: none**Description:**Initialize the OLED display controller and turn the display on.*/void OledDevInit(){// We're going to be sending commands, so clear the Data/Cmd bitDCClearBit(); //prtDataCmd IS THE ADDRESS OF THE PIN DATA/CMD //WE Have to write a 0 to this bit to say that it is 0 cmd.// Start by turning VDD on and wait a while for the power to come up.VDDSetBit(); //in this subroutine i will make the VDD bit i.e 1st bit(not 0th bit)to 1.DelayMs(5); //i need clk speed to implement this routine.// Display off commandSpi2PutByte(0xAE);// Bring Reset low and then highPORTClearBits(prtReset, bitReset);DelayMs(1);PORTSetBits(prtReset, bitReset);// Send the Set Charge Pump and Set Pre-Charge Period commandsSpi2PutByte(0x8D);Spi2PutByte(0x14);Spi2PutByte(0xD9);Spi2PutByte(0xF1);// Turn on VCC and wait 100msPORTSetBits(prtVbatCtrl, bitVbatCtrl);DelayMs(100);// Send the commands to invert the display.Spi2PutByte(0xA1);//remap columnsSpi2PutByte(0xC8);//remap the rows// Send the commands to select sequential COM configurationSpi2PutByte(0xDA);//set COM configuration commandSpi2PutByte(0x20);//sequential COM, left/right remap enabled// Send Display On commandSpi2PutByte(0xAF);}…left0…/** Power off function*/void OledDevTerm(){// Send the Display Off command.Spi2PutByte(cmdOledDisplayOff);// Turn off VCCPORTClearBits(prtVbatCtrl, bitVbatCtrl);delay(100);// Turn off VDDPORTClearBits(prtVddCtrl, bitVddCtrl);}/* ------------------------------------------------------------ *//***OledDisplayOff**Parameters: none**Return Value: none**Errors: none**Description:**Turn the display off. This does not power the display**down. All it does is send the display off command.*/void OledDisplayOff(){PORTClearBits(prtDataCmd, bitDataCmd);Spi2PutByte(cmdOledDisplayOff);}/* ------------------------------------------------------------ *//***OledClear**Parameters: none**Return Value: none**Errors: none**Description:**Clear the display. This clears the memory buffer and then**updates the display.*/void OledClear(){OledClearBuffer();OledUpdate();}…00…/** Power off function*/void OledDevTerm(){// Send the Display Off command.Spi2PutByte(cmdOledDisplayOff);// Turn off VCCPORTClearBits(prtVbatCtrl, bitVbatCtrl);delay(100);// Turn off VDDPORTClearBits(prtVddCtrl, bitVddCtrl);}/* ------------------------------------------------------------ *//***OledDisplayOff**Parameters: none**Return Value: none**Errors: none**Description:**Turn the display off. This does not power the display**down. All it does is send the display off command.*/void OledDisplayOff(){PORTClearBits(prtDataCmd, bitDataCmd);Spi2PutByte(cmdOledDisplayOff);}/* ------------------------------------------------------------ *//***OledClear**Parameters: none**Return Value: none**Errors: none**Description:**Clear the display. This clears the memory buffer and then**updates the display.*/void OledClear(){OledClearBuffer();OledUpdate();}…left13/* ------------------------------------------------------------ *//***OledClearBuffer**Parameters:none**Return Value:none**Errors:none**Description:**Clear the display memory buffer.*/void OledClearBuffer(){int ib;char *pb = rgbOledBmp;// Fill the memory buffer with 0.for (ib = 0; ib < cbOledDispMax; ib++) *pb++ = 0x00;}/* ------------------------------------------------------------ *//***OledUpdate**Parameters:none**Return Value:none**Errors:none**Description:**Update the OLED display with the contents of the memory buffer*/void OledUpdate(){intipag;inticol;char *pb = rgbOledBmp;for (ipag = 0; ipag < cpagOledMax; ipag++) {PORTClearBits(prtDataCmd, bitDataCmd);// Set the page addressSpi2PutByte(0x22);//Set page commandSpi2PutByte(ipag);//page number// Start at the left columnSpi2PutByte(0x00);//set low nybble of columnSpi2PutByte(0x10);//set high nybble of columnPORTSetBits(prtDataCmd, bitDataCmd);// Copy this memory page of display data.OledPutBuffer(ccolOledMax, pb);pb += ccolOledMax;} }…00/* ------------------------------------------------------------ *//***OledClearBuffer**Parameters:none**Return Value:none**Errors:none**Description:**Clear the display memory buffer.*/void OledClearBuffer(){int ib;char *pb = rgbOledBmp;// Fill the memory buffer with 0.for (ib = 0; ib < cbOledDispMax; ib++) *pb++ = 0x00;}/* ------------------------------------------------------------ *//***OledUpdate**Parameters:none**Return Value:none**Errors:none**Description:**Update the OLED display with the contents of the memory buffer*/void OledUpdate(){intipag;inticol;char *pb = rgbOledBmp;for (ipag = 0; ipag < cpagOledMax; ipag++) {PORTClearBits(prtDataCmd, bitDataCmd);// Set the page addressSpi2PutByte(0x22);//Set page commandSpi2PutByte(ipag);//page number// Start at the left columnSpi2PutByte(0x00);//set low nybble of columnSpi2PutByte(0x10);//set high nybble of columnPORTSetBits(prtDataCmd, bitDataCmd);// Copy this memory page of display data.OledPutBuffer(ccolOledMax, pb);pb += ccolOledMax;} }……left211804…/* ------------------------------------------------------------ *//***OledPutBuffer**Parameters: cb- number of bytes to send/receive**rgbTx- pointer to the buffer to send**Return Value: none**Errors: none**Description:**Send the bytes specified in rgbTx to the slave and return**the bytes read from the slave in rgbRx*/void OledPutBuffer(int cb, char * rgbTx){int ib; charbTmp;// Bring the slave select line lowPORTClearBits(PMODOLED_SS, bitSelect);// Write/Read the datafor (ib = 0; ib < cb; ib++) {// Wait for transmitter to be ready i.e check if the FIFO IS FULLwhile(PMODOLED_STATUS_R & (0x08) == 0x08) //wait for the transmit fifo complete.// Write the next transmit byte.PMODOLED_DTR = *rgbTx++; //first assignment and next moving the pointer. while(PMODOLED_STATUS_R & (0x04) == 0x04) //wait untill the transmition occurs. }// Bring the slave select line highPORTSetBits(prtSelect, bitSelect);}…00…/* ------------------------------------------------------------ *//***OledPutBuffer**Parameters: cb- number of bytes to send/receive**rgbTx- pointer to the buffer to send**Return Value: none**Errors: none**Description:**Send the bytes specified in rgbTx to the slave and return**the bytes read from the slave in rgbRx*/void OledPutBuffer(int cb, char * rgbTx){int ib; charbTmp;// Bring the slave select line lowPORTClearBits(PMODOLED_SS, bitSelect);// Write/Read the datafor (ib = 0; ib < cb; ib++) {// Wait for transmitter to be ready i.e check if the FIFO IS FULLwhile(PMODOLED_STATUS_R & (0x08) == 0x08) //wait for the transmit fifo complete.// Write the next transmit byte.PMODOLED_DTR = *rgbTx++; //first assignment and next moving the pointer. while(PMODOLED_STATUS_R & (0x04) == 0x04) //wait untill the transmition occurs. }// Bring the slave select line highPORTSetBits(prtSelect, bitSelect);}…left391795…/* ------------------------------------------------------------ *//***Spi2PutByte**Parameters: bVal- byte value to write**Return Value: Returns byte read**Errors: none**Description:**Write/Read a byte on SPI port 2*/char Spi2PutByte(char bVal) //LATEST ONE.{ SSClearBit(); //this fn makes the slave select low to select the device u want as slave PMODOLED_CTRL = PMODOLED_CTRL & ~0x100; //ENABLING THE MASTER TRANSACTIONS. PMODOLED_CTRL = PMODOLED_CTRL | 0x20; //TRANSMIT FIFO POINTER RESET. PMODOLED_CTRL = PMODOLED_CTRL & ~0x04; //BIT 2 AS 0 THEN SPI DEVICE SLAVE while(PMODOLED_STATUS_R & (0x08) == 0x08) //wait for the transmit fifo complete. PMODOLED_DTR = bVal; //Written the bval to the transfer register while(PMODOLED_STATUS_R & (0x04) == 0x04) //wait untill the transmition occurs. PMODOLED_CTRL = PMODOLED_CTRL | 0x02; //making SPE bit of ctrl to 1.}00…/* ------------------------------------------------------------ *//***Spi2PutByte**Parameters: bVal- byte value to write**Return Value: Returns byte read**Errors: none**Description:**Write/Read a byte on SPI port 2*/char Spi2PutByte(char bVal) //LATEST ONE.{ SSClearBit(); //this fn makes the slave select low to select the device u want as slave PMODOLED_CTRL = PMODOLED_CTRL & ~0x100; //ENABLING THE MASTER TRANSACTIONS. PMODOLED_CTRL = PMODOLED_CTRL | 0x20; //TRANSMIT FIFO POINTER RESET. PMODOLED_CTRL = PMODOLED_CTRL & ~0x04; //BIT 2 AS 0 THEN SPI DEVICE SLAVE while(PMODOLED_STATUS_R & (0x08) == 0x08) //wait for the transmit fifo complete. PMODOLED_DTR = bVal; //Written the bval to the transfer register while(PMODOLED_STATUS_R & (0x04) == 0x04) //wait untill the transmition occurs. PMODOLED_CTRL = PMODOLED_CTRL | 0x02; //making SPE bit of ctrl to 1.}Finally, we will need to design our coherent top-level application. We first must design the PLL and the timer description files in PetaLinux saving them to our directory. Then, we will begin writing a Linux program in a PetaLinux text editor like Nano. We will have to make sure that we enable all the hardware that we have programmed using Vivado while we define constants and registers in a manner relevant to the rest of the software development world. Finally, we will design more functions to compartmentalize the processes of our system. For instance, we will need to write a function that enables the user to choose their intended connection type along with another function that allows the user to enter the username and password for said connection. Many more functions and the main function that connects all of their processes will also need to be written and debugged concurrently through the development.Expected Schedule/TimelineSince the implementation of our project necessitates the learning of three new programming environments, it seems logical to divide up our work into three phases, each involving much research and familiarization with utilizing the given software. DateDeliverables4th July, 14First Report11th July , 14Hardware Block Design in Vivado Design Suite , XDC file , bit file generation18th July , 14Plan for software Driver development25th July , 14Final Hardware Block Design in Vivado Design Suite , XDC file , bit file generation1st August, 14First Draft of untested OLED Driver Code because of unavailability of license8th August, 14PetaLinux License Access from Xilinx12th August 14Tested Driver code14th August, 14Final ReportTable SEQ Table \* ARABIC 5 - Project Deliverable ScheduleThe first phase is to design the user interface and decide which of the ZedBoard components and peripheral ports are necessary then use the hardware description language in the Vivado Design Suite software package to reconfigure the interconnections between the Zynq? processor and the ZedBoard, thus enabling those. This stage has been completed as of 7 July, 2014. This is not to say that Vivado will not be used in the future implementation of our project as we debug the hardware and troubleshoot future deficiencies in our design, but we know which hardware to enable and connect and how to do realize this.The second phase is designing the device drivers used to access the PMOD OLED display, the PMOD Bluetooth interface and the PMOD Wi-Fi interface in our overall system. We will create these in the C programming language using a Xilinx Tools IDE. We now hope to have the shell of these drivers completed by 12th August, 2014. With a first draft of these drivers, we can then move on to our system software design.The third phase is using PetaLinux Tools to connect the hardware with the drivers, convert the received information from the network, display the necessary calendar events, and integrate the user interface, thus rendering the project both operable and portable. We hope to continue working of the project after submission of the final report . Evaluation/Results/DemoUsing Vivado Design Suite to program the hardware implementation of our project required diligence and understanding of many intricate machinations of the peripherals we connected to the ZedBoard to make up what will be the finished product.Figure 2 - Block diagram version - 1The below explains about the block diagram version-1 . The IP’s we have chosen to use are as follows. First, the Zynq7 Processing System is the non-programmable part of the Zynq chip. It contains the Dual core ARM cortex A9 processing system and some peripherals that can be directly connected to the PS block through the MIO (Multiplexed Input/Output) interface. The following are the peripherals that are enabled in the PS-block: Uart1, Usb0, 2 PL fabric clocks at frequencies of 100 MHz and 10 MHz, 2 GPIO master AXI interfaces, and SD 0.Uart1(Universal asynchronous receiver / transmitter) is included to connect the computer to the ZedBoard while using the PetaLinux SDK when Linux has booted on the device from the SD card and for programming the PL portion of Zynq delivering the bit file generated from Vivado. We are using an USB0 to connect an external keyboard. As we are including different devices working at respective frequencies, we have enabled 2 PL-fabric clocks, of the possible We have also enabled two GPIO master AXI interfaces to support the 2 AXI Interconnect's working at two different frequencies. An SD card is to be used to boot the Linux kernel onto the board and the bit file which programs the Zynq chip’s PL portion.The PL components of our block diagram need further description. First, AXI Interconnect serves as a point-to-point connection, a far faster link than a data bus, between the PS block and the PL block and provides high speed transfer of the data between the two. Next, AXIQuad SPI converts the data brought by Pmod Bluetooth which uses the SPI protocol and converts to AXI AMBA (Advanced Microcontroller Bus Architecture) protocol and it is connected to the AXI Interconnect. AXIUARTLite is equivalent to the AXIQuad SPI, but accesses data with the UART interface rather than the SPI interface.Next we created the 2 GPIO I.P's to connect the 8 user LED's and 3 push buttons. The FCLK_Clk0 is connected to the AXI Interconnect to determine its processor speed. GPIO’s S_AXI slave port is connected to the M03_AXI master port. In other words, the GPIO block is the slave to the AXI interconnect master. This is done for both the GPIO block used for the 8 LED’s and the GPIO block used for the three push buttons. Finally, the pin numbers that we have discovered from the board and device are included in figures.Since the first project report submission, we have made the following changes to the block diagram. First, we realized that the Pmod interface included pins that were not included in the SPI Interface, so we removed them from the AXI Quad SPI IP’s and consequently connected them to an additional IP called the AXI GPIO. Also, we had to include a connection of the clock to those GPIO IP’s. Finally, one Data/Command Signal in the OLED Pmod was connected to the wrong IP – the AXI Quad SPI. We connected this signal to the GPIO IP as well.Figure 3 - Block diagram version - 2Conclusions and Future WorkIt is clear that designing any electronic system requires the reconfiguring of its hardware alongside the programming of its software. Before the implementation of either of these is possible, a holistic design of the project must be created to satisfy its specification requirements in a clear and efficient way while a plan and timeline must also be created to ensure the project’s completion and modifications.For our portable calendar viewer, we first decided which components of the ZedBoard were necessary. We needed to enable three PMOD ports using hardware description language for our Bluetooth interface, our Wi-Fi interface, and our external OLED display. This way, we could access the calendar from the web and display the events thus completing the purpose of the project. We knew that the project needed a simple user interface, so we concluded on using only three on-board buttons to scroll through options on our display. The user would need to select which type of connection and then be able to scroll through their calendar events, so we enabled a left button, a right button and a central selector button. Finally, we needed to enable the UART port for access to an external PC to download the system initially, but also to enter the login requirements for both the network connection and the calendar account.Although this task seems to be very easily implemented, we had to first get familiar with the Vivado Design Suite software and then troubleshoot the many problems we encountered. For instance, we had to learn the names of all the IP’s we needed and how to access them and embed them into our block design. Then we had to understand the connections of the pins hardwired onto the board and those in the Zynq? chip, as well as the components of the Zynq? chip and our peripheral devices and how they interact with each other and how to realize their interactions in our program. We have successfully completed the first major phase of our implementation – hardware.Next, we will spend much time learning the details of PetaLinux and the C IDE in Xilinx Tools to prepare for the final two phases – device driver programming and system configuration. After deciding and specifying how our devices will receive and convert and compute and display the data, we will have to program the entire project to work in a cohesive and independent manner by importing our drivers, reading the inputs and continuously obeying the user in the convenient manner that we specified.Our portable calendar viewer will truly be able to simply the work necessary for the user to know what is going on in his or her life with speed and simplification. Furthermore, with our project as an example many Xilinx workers and ZedBoard programmers around the world will be able to design and implement projects that will further simplify the world. Truly we have a lot of work to do before our holistic project is completed, but without the work we have completed thus far, we would have no guidelines or starting point. We’ve mapped out the race and finished the first lap. References IO : QUAD SPI : WiFi : ................
................
In order to avoid copyright disputes, this page is only a partial summary.
To fulfill the demand for quickly locating and searching documents.
It is intelligent file search solution for home and business.