Scripting the Bus Pirate to talk to a Nokia 3310 LCD

From wiki.countercaster.com

Revision as of 09:30, 19 October 2009 by LucAdmin (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The Nokia 3310 LCD is cheap (free if you have an old phone you can cannibalize) and reasonably easy to control using any microprocessor. For this reason it has proved popular with experimenters.


Bus Pirate connected to Nokia 3310 LCD.

To try an familiarise myself with the new Bus Pirate binmode, I thought I'd write a Ruby script to control a Nokia 3310 LCD. I envisage a number of applications for this script - testing an LCD of unknown condition, learning how to control this type of LCD, and even repurposing a bus pirate + LCD as a permanent display for showing status information, etc.


Bus Pirate connected Nokia 3310 LCD displaying a bitmap.

Here is some video of the LCD display in action:

Connection details

The Bus Pirate hardware provides just about everything needed to drive a Nokia 3310 LCD. These LCDs run off +3.3V, so the Bus Pirate can provide power. All that is required in addition to the Bus Pirate are:

  • 1 x 1uF capacitor
  • 1 x 4.7uF capacitor
  • 1 x 10k resistor

The connection details are as follows:

Image:ConnectionDetails.jpg

The RES (i.e. reset) line of the LCD is driven by a simple power-on reset circuit. This ensures that the display is properly initialised. It could just as easily be driven by the Bus Pirate directly, except that in binmode SPI only four Bus Pirate connections function as outputs (CLK, MOSI, AUX and CS) and all of these are in use.

The pinout for the Nokia 3310 LCD is as follows (rear-view):

+----------------+
|    12345678    |
|                |
|   NOKIA 3310   |
|      LCD       |
+----------------+

The Ruby script

Here is my Ruby script to drive the Nokia 3310 LCD via the Bus Pirate.

It depends on my Ruby Class for Bus Pirate binmode.

It also depends on an assets file containing a bitmap to display.

Download the complete code: File:Nokia lcd v0.1.zip.

#!/usr/bin/ruby
#
# Script to drive a Nokia 3310 LCD connected to the Bus Pirate.
# Uses the Bus Pirate's binmode SPI feature.
# by blue.zener
# October 2009
#
# Use and adapt as you wish, and at your own risk.
#
require 'bus_pirate'
require 'assets'
 
Nokia3310Init = [0b00100001, 0b11000101, 0b00000110, 0b00010011, 0b00100010, 0b00001100, 0x40, 0x80]
Nokia3310Inverse = 0x0d
Nokia3310Normal = 0x0c
Nokia3310Blank = 0x08
Nokia3310AllOn = 0x09
 
@bus_pirate = BusPirate::BinModeSpi.new
 
# Create an 84x48 2D array from a 4096 element 1D array
@frame_buffer = Assets::PirateImage.to_enum.each_slice(48).to_a
 
def fb_rotate
  # rotate the frame buffer by one pixel to the left
  @frame_buffer.push(@frame_buffer.delete_at(0))
end
 
def fb_to_raw
  raw = []
  @frame_buffer.each do |column|
    column.to_enum.each_slice(8) do |byte|
      i = 0
      # byte = single byte represented as 8 discrete bits:
      #   e.g.  [0, 1, 0, 1, 0, 1, 0, 1] = 0x55 
      # result =  the byte represented as a single byte:
      #   e.g. 0b01010101 = 0x55
      raw << (byte.inject { |result, bit| i+=1; result + (bit << i) })
    end
  end
  raw # should be exactly 84x48/8 = 504 bytes
end
 
def nokia_write_command(command)
  # Nokia LCD D/C line = low for command, so AUX low
  @bus_pirate.set_peripherals(:power => 1, :aux => 0)
  @bus_pirate.write(command)
end
 
def nokia_write_data(data)
  # Nokia LCD D/C line = high for data, so AUX high
  @bus_pirate.set_peripherals(:power => 1, :aux => 1)
  @bus_pirate.write(data)
end
 
@bus_pirate.open('/dev/bus_pirate', 115200, :speed=>8000000, :output_type => 1)
@bus_pirate.set_peripherals(:power => 1)
sleep(0.1)
nokia_write_command(Nokia3310Init)
nokia_write_data(fb_to_raw)
sleep(2)
nokia_write_command(Nokia3310Inverse)
sleep(2)
nokia_write_command(Nokia3310Normal)
sleep(2)
nokia_write_command(Nokia3310AllOn)
sleep(2)
nokia_write_command(Nokia3310Normal)
sleep(2)
nokia_write_command(Nokia3310Blank)
sleep(2)
nokia_write_command(Nokia3310Normal)
 
# scroll image on LCD
84.times do
  fb_rotate
  nokia_write_data(fb_to_raw)
end
 
puts "Press <enter> to quit."
STDIN.getc
 
@bus_pirate.set_peripherals(:power => 0)
@bus_pirate.close
Personal tools