CS428 Embedded Systems Lab

Assignment 3: Display

This assignment aims to help you understand:

(a)    How the display works and how to provide a simple driver and

(b)    How analog to digital converters work and how to provide a simple driver.

 

1.     Get a kit from the lab

For this assignment, you will need:

·       the Arduino DUE board,

·       the main shield,

·       the display shield,

·       the led module,

·       the speaker module, and

·       a USB cable.

Details on the procedure you need to follow to get access to these will be given in class.

 

2. Download the assignment repo

Refer to the assignments page for information about forking the assignment repo. Fork and clone the repo as3_display.

 

3. Connect the required components to the Arduino DUE board

·       This is your Arduino board [pinout, schematic].

·       Add the gpio expansion shield on top. Align the board sides and the pins carefully, as shown here. Be careful not to bend any of the pins. Make sure that all the pins between the shield and the Arduino are connected firmly.

·       Add the display shield on top of the gpio shield.

·       The green led is a Digital Piranha Green LED v2 module. Connect the LED module to the 2nd pin triplet on the display shield matching wire and pin colors. Connect the positive red wire to the red + pin, the negative black to the black - pin, and the signal green to the green D pin. Take a look at the Arduino due pinout pdf for more details on where each pin goes and what is does.

·       This is the speaker module [schematic]. Connect the speaker module to the 5th pin triplet on the display shield matching wire and pin colors. Connect the positive red wire to the red + pin, the negative black to the black - pin, and the signal green to the green D pin. Take a look at the Arduino due pinout pdf for more details on where each pin goes and what is does.

·       Our LCD display is an LCD12864 and uses the ST7565 controller/driver to operate the display. ST7565 accepts commands from the ARM core over SPI.

 

4. Build our basic firmware

The as3_display directory contains the skeleton of a very simple program/firmware. To build this firmware:

1.     Go to the as3_display directory.

2.     Copy the orig directory to a new directory for your solution to the assignment with “cp -r orig solution”.  

3.     Go to the solution directory and adjust the Makefile, similar to the first assignment.

4.     In the solutions directory, type “make system; make clean; make”.

5.     Create an as3_readme.txt file that will contain your answers to questions below.

 

5. Extend the firmware to setup and use the Serial Peripheral Interface (SPI)

Our display uses the SPI protocol for communication with the processor core. However, our display shield does not (cannot) connect to the SPI peripheral of SAM3X8E (atmel_SAM3X8E_datasheet.pdf). Instead, it connects to other pins of PIO controllers and we will use these pins to emulate SPI and send commands to the display. Our display connects to the following Arduino DUE pins:

Pin                              Use for                                                         PIO-pin#

Digital 13(D13)      SPI SCK                                                         PB27

Digital 11(D11)      SPI MOSI                                                      PD7

Digital 10(DO)        SPI CS                                                            PA28

Digital 9(D9)           SPI CD                                                           PC21

Digital 8(D8)           SPI RST                                                          PC22

Digital 7(D7)           LCD backlight control                             PC23

Analog0(A0)           5-degree joystick  control                     PA16

5.1 To which PIO controller does our display connect? Which PIO pin correspond to each display pin? Fill in this information in the table above.

5.2 At what SPI speeds can the display operate? What is the required clock cycle for the SPI transfers (half in the low clock pulse and half in the high clock pulse)?

5.2 Implement the following functions that allow us to send (write) information to the display over the (emulated) SPI protocol in spi.h:

void spi_init(void);                                   // init PIO pins

void spi_setcs(uint32_t cs);                 // enable/disable display

void spi_writebit(uint8_t byte);         // if byte is 0 then bit is 0, otherwise bit=1.

                                                                                          // set the clock low, high properly so that SPI speed matches display capabilities

void spi_writebyte(uint8_t data);     // write a byte, MSB first

void spi_write(uint8_t *buf, uint32_t len); // write a buf array of len bytes 

 

6. Extend the firmware to setup and use the display

Our display is an LCD12864 and uses the ST7565 controller/driver to operate the display. ST7565 accepts commands from the ARM core over SPI. Table 16 on page 41 of the ST7565 datasheet summarizes the commands available in the ST7565.

 

To update the LCD we will use a simple technique that works for both characters and graphics: We will use a program frame buffer that will hold the state of each LCD pixel, we will be updating pixels only in the frame buffer, and from time to time we will be sending the full frame buffer to the LCD (via the SPI). The frame buffer can be a 2D array uint8_t FrameBuffer[#pages][#columns]. To display a character we need to update a set of bytes in this array.  To display (or clear) a pixel, we need to modify a single bit in some array position/byte. The font for characters is provided in font.[ch]. Each character is a 6x8 array of pixels which is represented as a sequence of 6 bytes in the font array.

 

6.1 Define your frame buffer and write a function that sends the full frame buffer to the display via the SPI:

                  void display_init(void);                        //initialize the diplay; A sketch of this function is provided

                  void display_update(void);                  // send the full frame buffer to the display

Note, that these are the only two functions that manipulate the display (LCD) itself.

 

6.2 Using only the frame buffer, implement the following functions of display.h for performing basic functions with our display:

void display_clear();                                                          //set all pixels to 0 in the frame buffer

void display_char(uint8_t i, uint8_t j, char c);            //write a char at page i, column j in the frame buffer

void display_str(uint8_t i, uint8_t j, char *str);          //write a string at page i, column j in the frame buffer

void display_num(uint8_t i, uint8_t j, uint32_t num, uint8_t width);  //write num as width digits at page i, column j in the frame buffer

void display_setpixel(uint8_t i, uint8_t j, uint8_t value); // set pixel i,j to value=0,1 in the frame buffer

 

7. Setup and use the Analog-to-Digital Converter (ADC)

The analog-to-digital converter (ADC) (Section 43 in atmel_SAM3X8E_datasheet.pdf) takes an analog voltage from one of the pins of the Arduino and converts it to a digital value. The display module contains a 5-position joystick button. This button outputs a different voltage depending on its position (display board/shield schematic).

 

7.1 To which PIO and pin is the 5-position joystick connected? Which peripheral (A or B) for this PIO pin is the ADC? Based on this pin, which ADC channel does the joystick use? In this case, no initialization is required for the PIO peripheral, as the ADC itself handles this. The ADC itself needs to be configured with no hardware triggers, 64 periods startup time, 17 periods settling time, tracking time 3, transfer period 2, single-ended mode, and gain of 1.

7.2 Implement the following functions that allow us to convert analog signals to numerical values via the ADC, in adc.h:

void adc_init(void);                                    //setup ADC. A sketch of this function is provide.

void adc_enable(uint32_t channel);      //start conversion on ADC channel

void adc_disable(uint32_t channel);     //stop conversion on ADC channel

void adc_start(void);                                //trigger next coversion

uint32_t adc_status(uint32_t channel); //check if next value is available

uint32_t adc_read(uint32_t channel); //read next sample, synchronously 

7.3 What sampling rate should you use for the joystick? Use the appropriate value for the PRESCALE parameter in ADC_MR.

7.4 Modify your firmware to read and display the state of the joystick.

 

8. Implement an Analog Clock

You will now draw simple graphics on the screen to display an analog clock. You will need to use simple math functions form math.h and to include the math library -lm in your Makefile and in the proper order with the rest of the libraries).

 

8.1 Implement the following functions in the aclock.h module:

//draw the frame at cx,cy with radius r

void aclock_frame(uint8_t cx, uint8_t cy, uint8_t r);

//draw a hand with origin cx,cy, length r, and tick t in [0,59]

void aclock_hand(uint8_t cx, uint8_t cy, uint8_t r, uint16_t t);

//draw a symbol, e.g. a fat dot, on the frame (x,y,r) at angle a

void aclock_framesymbol(uint8_t cx, uint8_t cy, uint8_t r, uint16_t d);

//draw the full thing at x,r with radius r for hh:mm:ss

void aclock_display(uint8_t x, uint8_t y, uint8_t r, uint8_t hh, uint8_t mm, uint8_t ss);

8.2 Modify your firmware to display an analog clock on the display and update the hand motion every second.

 

9. Submit

Please refer to the policies for information about the submission process.

9.1   Submit all files required to run the assignment, including your documentation file as3_readme.txt with all your answers and remarks.

9.2   Follow the procedure outlined in class for returning the components you used in this assignment.

 

(c) Copyright University of Crete, Greece, Last Modified: 18-July-2023.