UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Adam Taylor’s MicroZed(ish) Chronicles Part 84: Simple Communication Interfaces Part 4

by Xilinx Employee on ‎06-01-2015 10:54 AM (49,566 Views)

 

By Adam Taylor

 

We can now configure and turn on the OLED screen. All we need to do is drive the display with the data we want to show. However, before we do that I want to quickly recap a little of the code used to configure the OLED because I’ve realized there is an even faster way to configure the display than previously demonstrated.

 

Below is the original initialization code as presented in issue 83:

 

 

for(i =0; i<23; i++){

   wr_buff[0] = (u8) init_vector[i];

   XGpioPs_WritePin(&Gpio, dc, 0); // set DC to command

   XSpiPs_SetSlaveSelect(&SpiInstance_EMIO, 0x01); //select the slave

   XSpiPs_PolledTransfer(&SpiInstance_EMIO, wr_buff, NULL, 1); //write the word

   XGpioPs_WritePin(&Gpio, dc, 1); // set DC to data

}

 

 

While this code is functional and works fine, it does not maximize the Zynq SoC’s performance. A better way is to pass the entire 23 byte array to the SPI peripheral and tell it there are 23 bytes to send, as shown below:

 

 

   XGpioPs_WritePin(&Gpio, dc, 0);

   XSpiPs_SetSlaveSelect(&SpiInstance_EMIO, 0x01);

   XSpiPs_PolledTransfer(&SpiInstance_EMIO, init_vector, NULL, 23);

   XGpioPs_WritePin(&Gpio, dc, 1);

 

 

This is an important thing to go back and correct because we will be sending many hundreds of bytes when we want to display information on our screen. We want the best performance possible.

 

 

The OLED can operate in one of three addressing modes to write to the OLED memory: page (default), horizontal, or vertical. For this example, we will be using the default of page addressing because that is the simplest one. However, none of the addressing modes are exceptionally complicated.

 

 

The OLED fitted to the ZedBoard is a 128-by-32 array. Internally, this is divided into four pages of eight pixels (32 / 4 = 8 ) high, as shown below.

 

(NOTE: pages 4 to 7 are not used with this OLED however the controller used can support arrays as large as 128x64 pixels. Hence the four extra pages shown):

 

 

 

Image1.jpg 

 

 

These pages act like essentially like lines when displaying text on the OLED. If we wish to display images, we will have to ensure correct alignment across the pages. We may want to use one of the other addressing modes to ease this.

 

 

If you remember back to when we configured the OLED last week, we remapped the segments to run from 127 down to 0. We did not re-map the pages. Each page consists of 128 8-bit segments as shown in the diagrams below:

 

 

Image2.jpg

 

 

 

Image3.jpg

 

 

 

(Note: The segments are shown at different ends as the bottom diagram does not demonstrate remapping SEG0 = SEG127 when remapped on the bottom diagram.)

 

 

This means that to write to a page, we perform 128, 8-bit SPI writes once we have told the OLED which page we are addressing. The OLED increments the page memory address automatically on each successive write of data. The basic approach needed for writing this data is therefore:

 

  • Issue Command of the Page to be address [0-3], D/C = 0 SPI data = B0-B3 depending upon the page.

 

  • Write 128 bytes to the data memory – again we can use the trick we used above to pass a 128-byte array to the SPI controller, thus freeing up the processor.

 

Once these operations have been performed, you may see the image as you wish displayed upon the screen. However, it is not quite that simple if you wish to display text characters as you may have noticed that the data is written vertically as opposed to horizontally for traditional font patterns. What I mean by this is demonstrated below using the pixel font editor tool:

 

 

 

Image4.jpg

 

 

 

 

As you can see in the diagram above, the hex commands to display the character “B” are described horizontally as:

 

 

0x7C, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7C, 0x00

 

 

However we need to write vertically to each of the segments within a page:

 

 

0x00, 0x7f, 0x7f, 0x94, 0x94, 0x7f, 0x36, 0x00

 

 

We therefore need to convert between the horizontal and vertical within our program and correctly write to the page. This can be done pretty simply doing the following:

 

 

  1. Store the eight bytes we wish to convert in a u8 array
  2. For each bit position in the u8 array (i.e. each of the eight bits), cycle through as follows
    1. Loop through each of the eight bytes in the u8 array in step 1 above.
    2. Shift each byte logically right by the bit position being addressed.
    3. Set all of the bits in the byte apart from the LSB to 0.
    4. Store the result for each byte in the array.
    5. Logically OR the results together with the results shifted to the right by the correct number of places to reform the byte. The LSB should be in the highest position according to the byte usage in the diagram above. This prevents an “M” from being displayed upside down.
  3. Increment the loop for the next bit position.
  4. Flip the bytes MSB for LSB to ensure the characters face the correct direction e.g. a B faces the correct direction.

 

The conv_alg function performs these steps within the source code example on GitHub.

 

To ensure display flexibility, I wanted to be able to look up and output any character to the display in correct format, at least for text. To do this, I used the pixel font editor available here to write out the APEAUS font into a C header file. This file lists the horizontal font codes for all characters displayed in the diagram above. I can then use this header file to generate all of the patterns for the characters I want to display.

 

As each page is 128 characters long by 8 pixels high, I want to segment this procedure to display 16 8-bit characters on each page. This gives nice symmetry as each character would then be 8x8 pixels.

 

 

My algorithm to display the characters was thus:

 

 

  1. Define four u8 arrays, each 16 elements long. These arrays will contain the character numbers to be displayed in line with the APEAUS.h file, e.g. “B” = character 77.

 

  1. Define four u8 arrays, each 128 elements in length for the page memories. These arrays will contain the information to be output to each OLED page.

 

  1. Loop through each of the 16 element lines in step 1 above. For each of the elements, perform the following:

 

    • Look up the character to be displayed from the number (e.g. “B” = 77). As the font array consists of 2048 elements where each character is 8 elements long, we can calculate the start position of the char to display a “B”. In this case, 77*8 = 616.
    • Store the eight bytes from array element 616 into a u8 array 8 bytes long.
    • Run the horizontal to vertical conversion algorithm on the 8-byte array.
    • Store the results in the correct character position within the page array. The character position is defined by the equation:

Line-start –(char_size*loop)- byte_i

 

Where line_start = 127, char_size = 8, loop = which of the 16 words in step 1 above is being processed, and byte_i is current byte of the 8-byte character being processed.

 

 

Once we have done these steps, we issue the commands over the SPI to transmit the page to be addressed followed by the 128 bytes for the line:

 

                cmd[0] = (u8) 0xB3; // page 3

                XGpioPs_WritePin(&Gpio, dc, 0);

                XSpiPs_SetSlaveSelect(&SpiInstance_EMIO, 0x01);

                XSpiPs_PolledTransfer(&SpiInstance_EMIO, cmd, NULL, 1); // write page 3 command

                XGpioPs_WritePin(&Gpio, dc, 1);

                XSpiPs_SetSlaveSelect(&SpiInstance_EMIO, 0x01);

                XSpiPs_PolledTransfer(&SpiInstance_EMIO, page_3, NULL, 128); //send 128 page 3 bytes

 

 

When I ran this procedure, my OLED displayed the following:

 

 

 

Image5.jpg

 

 

 

You can obtain the code here. If I get the chance, I will repackage the code to work as an OLED API.

 

 

 

 

You’ll find the code for this and other MicroZed Chronicles posts in the MicroZed Chronicles’ Github repository.

 

 

 

 

 MicroZed Chronicles.jpg

 

 

 

Now, you can have convenient, low-cost Kindle access to the first year of Adam Taylor’s MicroZed Chronicles for a mere $7.50. Click here.

 

 

Please see the previous entries in this MicroZed Chronicles series by Adam Taylor:

 

Adam Taylor’s MicroZed(ish) Chronicles Part 83: Simple Communication Interfaces Part 3

 

Adam Taylor’s MicroZed(ish) Chronicles Part 82: Simple Communication Interfaces Part 2

 

Adam Taylor’s MicroZed(ish) Chronicles Part 81: Simple Communication Interfaces

 

Adam Taylor’s MicroZed Chronicles Part 80: LWIP Stack Configuration

 

Adam Taylor’s MicroZed Chronicles Chronicles Part 79: Zynq SoC Ethernet Part III

 

Adam Taylor’s MicroZed Chronicles Chronicles Part 78: Zynq SoC Ethernet Part II

 

Adam Taylor’s MicroZed Chronicles Microzed Chronicles Part 77 – Introducing the Zynq SoC’s Ethernet

 

Adam Taylor’s MicroZed Chronicles Part 76: Constraints for Relatively Placed Macros

 

Adam Taylor’s MicroZed Chronicles, Part 75: Placement Constraints – Pblocks

 

Adam Taylor’s MicroZed Chronicles, Part 73: Physical Constraints

 

Adam Taylor’s MicroZed Chronicles, Part 73: Working with other Zynq-Based Boards

 

Adam Taylor’s MicroZed Chronicles, Part 72: Multi-cycle Constraints

 

Adam Taylor’s MicroZed Chronicles, Part 70: Constraints—Clock Relationships and Avoiding Metastability

 

Adam Taylor’s MicroZed Chronicles, Part 70: Constraints—Introduction to timing and defining a clock

 

Adam Taylor’s MicroZed Chronicles Part 69: Zynq SoC Constraints Overview

 

Adam Taylor’s MicroZed Chronicles Part 68: AXI DMA Part 3, the Software

 

Adam Taylor’s MicroZed Chronicles Part 67: AXI DMA II

 

Adam Taylor’s MicroZed Chronicles Part 66: AXI DMA

 

Adam Taylor’s MicroZed Chronicles Part 65: Profiling Zynq Applications II

 

Adam Taylor’s MicroZed Chronicles Part 64: Profiling Zynq Applications

 

Adam Taylor’s MicroZed Chronicles Part 63: Debugging Zynq Applications

 

Adam Taylor’s MicroZed Chronicles Part 62: Answers to a question on the Zynq XADC

 

Adam Taylor’s MicroZed Chronicles Part 61: PicoBlaze Part Six

 

Adam Taylor’s MicroZed Chronicles Part 60: The Zynq and the PicoBlaze Part 5—controlling a CCD

 

Adam Taylor’s MicroZed Chronicles Part 59: The Zynq and the PicoBlaze Part 4

 

Adam Taylor’s MicroZed Chronicles Part 58: The Zynq and the PicoBlaze Part 3

 

Adam Taylor’s MicroZed Chronicles Part 57: The Zynq and the PicoBlaze Part Two

 

Adam Taylor’s MicroZed Chronicles Part 56: The Zynq and the PicoBlaze

 

Adam Taylor’s MicroZed Chronicles Part 55: Linux on the Zynq SoC

 

Adam Taylor’s MicroZed Chronicles Part 54: Peta Linux SDK for the Zynq SoC

 

Adam Taylor’s MicroZed Chronicles Part 53: Linux and SMP

 

Adam Taylor’s MicroZed Chronicles Part 52: One year and 151,000 views later. Big, Big Bonus PDF!

 

Adam Taylor’s MicroZed Chronicles Part 51: Interrupts and AMP

 

Adam Taylor’s MicroZed Chronicles Part 50: AMP and the Zynq SoC’s OCM (On-Chip Memory)

 

Adam Taylor’s MicroZed Chronicles Part 49: Using the Zynq SoC’s On-Chip Memory for AMP Communications

 

Adam Taylor’s MicroZed Chronicles Part 48: Bare-Metal AMP (Asymmetric Multiprocessing)

 

Adam Taylor’s MicroZed Chronicles Part 47: AMP—Asymmetric Multiprocessing on the Zynq SoC

 

Adam Taylor’s MicroZed Chronicles Part 46: Using both of the Zynq SoC’s ARM Cortex-A9 Cores

 

Adam Taylor’s MicroZed Chronicles Part 44: MicroZed Operating Systems—FreeRTOS

 

Adam Taylor’s MicroZed Chronicles Part 43: XADC Alarms and Interrupts 

 

Adam Taylor’s MicroZed Chronicles MicroZed Part 42: MicroZed Operating Systems Part 4

 

Adam Taylor’s MicroZed Chronicles MicroZed Part 41: MicroZed Operating Systems Part 3

 

Adam Taylor’s MicroZed Chronicles MicroZed Part 40: MicroZed Operating Systems Part Two

 

Adam Taylor’s MicroZed Chronicles MicroZed Part 39: MicroZed Operating Systems Part One

 

Adam Taylor’s MicroZed Chronicles MicroZed Part 38 – Answering a question on Interrupts

 

Adam Taylor’s MicroZed Chronicles Part 37: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 8

 

Adam Taylor’s MicroZed Chronicles Part 36: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 7

 

Adam Taylor’s MicroZed Chronicles Part 35: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 6

 

Adam Taylor’s MicroZed Chronicles Part 34: Driving Adafruit RGB NeoPixel LED arrays with MicroZed Part 5

 

Adam Taylor’s MicroZed Chronicles Part 33: Driving Adafruit RGB NeoPixel LED arrays with the Zynq SoC

 

Adam Taylor’s MicroZed Chronicles Part 32: Driving Adafruit RGB NeoPixel LED arrays

 

Adam Taylor’s MicroZed Chronicles Part 31: Systems of Modules, Driving RGB NeoPixel LED arrays

 

 Adam Taylor’s MicroZed Chronicles Part 30: The MicroZed I/O Carrier Card

 

Zynq DMA Part Two – Adam Taylor’s MicroZed Chronicles Part 29

 

The Zynq PS/PL, Part Eight: Zynq DMA – Adam Taylor’s MicroZed Chronicles Part 28  

 

The Zynq PS/PL, Part Seven: Adam Taylor’s MicroZed Chronicles Part 27

 

The Zynq PS/PL, Part Six: Adam Taylor’s MicroZed Chronicles Part 26

 

The Zynq PS/PL, Part Five: Adam Taylor’s MicroZed Chronicles Part 25

 

The Zynq PS/PL, Part Four: Adam Taylor’s MicroZed Chronicles Part 24

 

The Zynq PS/PL, Part Three: Adam Taylor’s MicroZed Chronicles Part 23

 

The Zynq PS/PL, Part Two: Adam Taylor’s MicroZed Chronicles Part 22

 

The Zynq PS/PL, Part One: Adam Taylor’s MicroZed Chronicles Part 21

 

Introduction to the Zynq Triple Timer Counter Part Four: Adam Taylor’s MicroZed Chronicles Part 20

 

Introduction to the Zynq Triple Timer Counter Part Three: Adam Taylor’s MicroZed Chronicles Part 19

 

Introduction to the Zynq Triple Timer Counter Part Two: Adam Taylor’s MicroZed Chronicles Part 18

 

Introduction to the Zynq Triple Timer Counter Part One: Adam Taylor’s MicroZed Chronicles Part 17

 

The Zynq SoC’s Private Watchdog: Adam Taylor’s MicroZed Chronicles Part 16

 

Implementing the Zynq SoC’s Private Timer: Adam Taylor’s MicroZed Chronicles Part 15

 

MicroZed Timers, Clocks and Watchdogs: Adam Taylor’s MicroZed Chronicles Part 14

 

More About MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 13

 

MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 12

 

Using the MicroZed Button for Input: Adam Taylor’s MicroZed Chronicles Part 11

 

Driving the Zynq SoC's GPIO: Adam Taylor’s MicroZed Chronicles Part 10

 

Meet the Zynq MIO: Adam Taylor’s MicroZed Chronicles Part 9

 

MicroZed XADC Software: Adam Taylor’s MicroZed Chronicles Part 8

 

Getting the XADC Running on the MicroZed: Adam Taylor’s MicroZed Chronicles Part 7

 

A Boot Loader for MicroZed. Adam Taylor’s MicroZed Chronicles, Part 6 

 

Figuring out the MicroZed Boot Loader – Adam Taylor’s MicroZed Chronicles, Part 5

 

Running your programs on the MicroZed – Adam Taylor’s MicroZed Chronicles, Part 4

 

Zynq and MicroZed say “Hello World”-- Adam Taylor’s MicroZed Chronicles, Part 3

 

Adam Taylor’s MicroZed Chronicles: Setting the SW Scene

 

Bringing up the Avnet MicroZed with Vivado

 

 

 

 

Comments
by Explorer
on ‎06-01-2015 04:50 PM

hi

 

Nice to add Arabic alphabet to Oled Screen, by the way, i founded a similar project, but it's on Zedboard, https://github.com/ama142/ZedboardOLED-v1.0-IP

Labels
About the Author
  • Be sure to join the Xilinx LinkedIn group to get an update for every new Xcell Daily post! ******************** Steve Leibson is the Director of Strategic Marketing and Business Planning at Xilinx. He started as a system design engineer at HP in the early days of desktop computing, then switched to EDA at Cadnetix, and subsequently became a technical editor for EDN Magazine. He's served as Editor in Chief of EDN Magazine, Embedded Developers Journal, and Microprocessor Report. He has extensive experience in computing, microprocessors, microcontrollers, embedded systems design, design IP, EDA, and programmable logic.