HW4 - ndm736/ME433_2020 GitHub Wiki

The SSD1306 is a driver for OLED displays. You have a 128x32 pixel I2C breakout board version in your kit. An OLED display uses individually controllable LEDs as pixels, so it does not need a backlight like a TFT LCD (like on most computer and cellphone screens).

The pixels can either be on or off, so there is no control over color or brightness. That means the amount of memory it takes to know every pixels value is 128 x 32 = 4096 bits = 512 bytes. That is a very reasonable amount of memory (compared to a color display, which would need 3 color bytes, RGB, per pixel, or 128 x 32 x 3 = 12288 bytes, and that's not a very high resolution display!). So what we'll be able to do is store the value of every pixel inside of an array in the PIC, and update all of the pixels simultaneously to update the display.

This display has 3 downsides: low resolution, I2C communication, and no reset pin. The SSD1306 can communicate with SPI, and it has a reset pin, but this particular breakout board did not make those available, so we'll have to use I2C and a heartbeat to know if the communication is stuck.

Take a look at the SSD1306 sample code which uses the functions from the I2C sample code. I referenced code written for various Arduino boards to figure out how to initialize the registers to make the display turn on, those are set using ssd1306_setup(). The setup function contains a short delay at the beginning, the display seems to need a little time to settle after getting power before you start talking to it.

The ssd1306.c file contains an array of 512 unsigned chars. The bits in this array represent what the display will show when you call the ssd1306_update() function. Update takes about 1/80th of a second, which is fine for out purposes, but considering the low resolution of the screen it isn't really too impressive.

ssd1306.c contains two other functions, ssd1306_clear() and ssd1306_drawPixel(). clear() set the value of every pixel to off. drawPixel() takes the x and y location of a pixel and turns it on (1) or off(0).

That's all you get! No method for drawing lines, circles, or text, just draw individual pixels and update the display. It is your job to make this more useful by adding a function to draw text so that we can see the values of variables.

First, connect SDA and SCL to your I2C bus, and Vdd to 3.3V and GND to GND. Start a new project and put it in a folder in your repo called HW4. Use the I2C and ssd1306 sample code to initialize I2C, initialize the ssd1306, and blink both a LED and a pixel at 1Hz to verify that your system works. Keep the LED blink in your code, it is useful as a heartbeat to know that the PIC is not frozen, which can happen if the PIC is communicating with the ssd1306 when you happen to reprogram with the Snap and then the ssd1306 never communicates with the PIC again without a power reset.

Second, write a function that uses the font sample code to draw a letter at a position. The function should take in the position of the letter in x and y, and the character. font.h contains a bitmap of every drawable character in ASCII. Each letter is 8 pixels tall and 5 pixels wide. Loop through ASCII[the letter][column 1 to 5], turning pixels on when the bit is a 1 and off when the bit is a 0. Test it out.

Third, write a function that prints a character array generated by sprintf() at a position. The function should take in the position of the first letter in x and y, and a pointer to the character array. In the function, while the character is not the null character ('\0' or the value 0) send the character to your draw letter function with the right x and y position. Now you can make a message and write to the screen:

char message[50]; sprintf(message, "my var = %d", i); drawMessage(10,10,message);

Every letter is 5x8 pixels, and the screen is 128x32, so you can fit 25x4 letters on the screen! Test your function by filling up the screen.

Finally, write a program that prints the value of a variable to the screen. Set the core timer to 0 at the top of the loop, and read the value of the core timer after calling ssd1306_update(). Use the time from the core timer to print to the bottom of the screen the frames per second (fps) that the display can achieve.

Submit a link to the HW4 folder in your repo in Canvas and make a demonstration video of the display and upload that to Canvas.