How these displays work is explained in a little more detail in our earlier post http://nerdclub-uk.blogspot.co.uk/2014/08/sending-bender-over-air-to-nokia-5110.html.
But we'd been using some of Steve's lovely Arduino libraries for a lot of it, which meant a lot of the low-level stuff was missing. There are loads of libraries available online to draw text and numbers onto these displays, but they almost always use fixed-width fonts.
Having left the 1980's behind, we decided to write our own "libraries" to write text onto the Nokia 5100 display, using a PIC microcontroller. The code below was written for a 16F877a (because it was the first chip we found already on a breadboard, with a programming header connected) but would work equally well on any PIC microcontroller with enough RAM for the font table.
Define CONFIG = 0x3f32
Define CLOCK_FREQUENCY = 20
AllDigital
Symbol led_pin = PORTB.7
Symbol lcd_sck = PORTD.4
Symbol lcd_data = PORTD.5
Symbol lcd_command = PORTD.6
Symbol lcd_reset = PORTD.7
definitions:
Define STRING_MAX_LENGTH = 30
Dim i As Byte
Dim j As Byte
Dim k As Byte
Dim li As Byte
Dim lj As Byte
Dim lk As Byte
Dim si As Byte
Dim sk As Byte
Dim byte_to_send As Byte
Dim x_value As Byte
Dim y_value As Byte
Dim character_to_send As Byte
Dim char(8) As Byte
Dim move_x As Byte
Dim string_to_write As String
Dim invert_display As Bit
Dim wrap_text As Bit
init:
ConfigPin PORTB = Output
ConfigPin PORTD = Output
invert_display = 0
wrap_text = 0
WaitMs 100
Gosub init_lcd
Gosub lcd_clear
x_value = 2 'columns are individual pixels
y_value = 0 'must be a row number, which is a multiple of 8
Gosub lcd_goto_xy
Gosub draw_band
x_value = 2
y_value = 1
Gosub lcd_goto_xy
invert_display = 1
wrap_text = 0
string_to_write = "{ ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Gosub lcd_write_string
invert_display = 0
x_value = 2
y_value = 3
wrap_text = 1
Gosub lcd_goto_xy
string_to_write = "abcdefghijklmnopqrstuvwxyz"
Gosub lcd_write_string
x_value = 2
y_value = 5
Gosub lcd_goto_xy
string_to_write = "123.45.67.89:0"
Gosub lcd_write_string
loop:
High led_pin
WaitMs 2000
Low led_pin
WaitMs 2000
Goto loop
End
init_lcd:
Low lcd_reset
WaitMs 10
High lcd_reset
'put into command mode
Low lcd_command
byte_to_send = 0x21 'lcd extended commands
Gosub lcd_write_byte
byte_to_send = 0xb1 'set lcd contrast
Gosub lcd_write_byte
byte_to_send = 0x04 'set temp coefficient
Gosub lcd_write_byte
byte_to_send = 0x14 'lcd bias mode 1:48
Gosub lcd_write_byte
byte_to_send = 0x0c 'put lcd into normal mode
Gosub lcd_write_byte
byte_to_send = 0x20 'dunno
Gosub lcd_write_byte
byte_to_send = 0x0c 'dunno
Gosub lcd_write_byte
WaitMs 5
'put into data mode
High lcd_command
Return
lcd_write_byte:
For li = 0 To 7
lk = 7 - li
lj = 1
lj = ShiftLeft(lj, lk)
lj = lj And byte_to_send
If lj = 0 Then
'send a zero bit
Low lcd_data
Else
'send a one bit
High lcd_data
Endif
'toggle the clock line
High lcd_sck
ASM: nop
Low lcd_sck
Next li
Return
lcd_clear:
'put the cursor at 0,0
x_value = 0
y_value = 0
Gosub lcd_goto_xy
'put the lcd into data mode
High lcd_command
'send 504 (48*84/8) blank pixels
For i = 0 To 5
For j = 0 To 83
byte_to_send = 0x00
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
Gosub lcd_write_byte
Next j
Next i
'just give everything a sec or two
WaitMs 10
Return
lcd_goto_xy:
Low lcd_command
byte_to_send = 0x80
byte_to_send = byte_to_send Or x_value
Gosub lcd_write_byte
byte_to_send = 0x40
byte_to_send = byte_to_send Or y_value
Gosub lcd_write_byte
High lcd_command
Return
lcd_get_character:
'set the default character to zero
char(0) = 0x00
char(1) = 0x00
char(2) = 0x00
char(3) = 0x00
char(4) = 0x00
char(5) = 0x00
char(6) = 0x00
move_x = 0
Select Case character_to_send
Case "A"
char(0) = 01111110b
char(1) = 00001001b
char(2) = 00001001b
char(3) = 01111110b
move_x = 5
Case "B"
char(0) = 01111111b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110110b
move_x = 5
Case "C"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01000001b
move_x = 5
Case "D"
char(0) = 01111111b
char(1) = 01000001b
char(2) = 01000001b
char(3) = 00100010b
char(4) = 00011100b
move_x = 6
Case "E"
char(0) = 01111111b
char(1) = 01001001b
char(2) = 01000001b
move_x = 4
Case "F"
char(0) = 01111111b
char(1) = 00001001b
char(2) = 00001001b
move_x = 4
Case "G"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01001001b
char(4) = 01111010b
move_x = 6
Case "H"
char(0) = 01111111b
char(1) = 00001000b
char(2) = 00001000b
char(3) = 01111111b
move_x = 5
Case "I"
char(0) = 01000001b
char(1) = 01111111b
char(2) = 01000001b
move_x = 4
Case "J"
char(0) = 00100000b
char(1) = 01000000b
char(2) = 01000001b
char(3) = 00100001b
char(4) = 00011111b
move_x = 6
Case "K"
char(0) = 01111111b
char(1) = 00001000b
char(2) = 00010100b
char(3) = 01100011b
move_x = 5
Case "L"
char(0) = 01111111b
char(1) = 01000000b
char(2) = 01000000b
move_x = 4
Case "M"
char(0) = 01111111b
char(1) = 00000001b
char(2) = 00000010b
char(3) = 00001100b
char(4) = 00000010b
char(5) = 00000001b
char(6) = 01111111b
move_x = 8
Case "N"
char(0) = 01111111b
char(1) = 00000100b
char(2) = 00001000b
char(3) = 00010000b
char(4) = 01111111b
move_x = 6
Case "O"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01000001b
char(4) = 00100010b
char(5) = 00011100b
move_x = 7
Case "P"
char(0) = 01111111b
char(1) = 00010001b
char(2) = 00010001b
char(3) = 00001110b
move_x = 5
Case "Q"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01010001b
char(4) = 00100010b
char(5) = 01011100b
move_x = 7
Case "R"
char(0) = 01111111b
char(1) = 00011001b
char(2) = 00101001b
char(3) = 01000110b
move_x = 5
Case "S"
char(0) = 00100010b
char(1) = 01000101b
char(2) = 01001001b
char(3) = 00110010b
move_x = 5
Case "T"
char(0) = 00000001b
char(1) = 00000001b
char(2) = 01111111b
char(3) = 00000001b
char(4) = 00000001b
move_x = 6
Case "U"
char(0) = 00111111b
char(1) = 01000000b
char(2) = 01000000b
char(3) = 01111111b
move_x = 5
Case "V"
char(0) = 00000011b
char(1) = 00011100b
char(2) = 01100000b
char(3) = 00011100b
char(4) = 00000011b
move_x = 6
Case "W"
char(0) = 00111111b
char(1) = 01000000b
char(2) = 00100000b
char(3) = 00011000b
char(4) = 00100000b
char(5) = 01000000b
char(6) = 00111111b
move_x = 8
Case "X"
char(0) = 01100011b
char(1) = 00010100b
char(2) = 00001000b
char(3) = 00010100b
char(4) = 01100011b
move_x = 6
Case "Y"
char(0) = 00000011b
char(1) = 00000100b
char(2) = 01111100b
char(3) = 00000111b
move_x = 5
Case "Z"
char(0) = 01111001b
char(1) = 01001001b
char(2) = 01001101b
char(3) = 01001011b
move_x = 5
Case "a"
char(0) = 00100000b
char(1) = 01010100b
char(2) = 01010100b
char(3) = 01111000b
move_x = 5
Case "b"
char(0) = 01111111b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 00111000b
move_x = 5
Case "c"
char(0) = 00111000b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 01000100b
move_x = 5
Case "d"
char(0) = 00111000b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 01111111b
move_x = 5
Case "e"
char(0) = 00111000b
char(1) = 01010100b
char(2) = 01010100b
char(3) = 01011100b
move_x = 5
Case "f"
char(0) = 01111110b
char(1) = 00001001b
char(2) = 00000001b
move_x = 4
Case "g"
char(0) = 10011000b
char(1) = 10100100b
char(2) = 10100100b
char(3) = 01111100b
move_x = 5
Case "h"
char(0) = 01111111b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 01111000b
move_x = 5
Case "i"
char(0) = 01000100b
char(1) = 01111101b
char(2) = 01000000b
move_x = 4
Case "j"
char(0) = 10000100b
char(1) = 10000101b
char(2) = 01111100b
move_x = 4
Case "k"
char(0) = 01111111b
char(1) = 00010000b
char(2) = 00010000b
char(3) = 01101100b
move_x = 5
Case "l"
char(0) = 01000001b
char(1) = 01111111b
char(2) = 01000000b
move_x = 4
Case "m"
char(0) = 01111100b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 01111000b
char(4) = 00000100b
char(5) = 00000100b
char(6) = 01111000b
move_x = 8
Case "n"
char(0) = 01111100b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 01111000b
move_x = 5
Case "o"
char(0) = 00111000b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 00111000b
move_x = 5
Case "p"
char(0) = 11111100b
char(1) = 00100100b
char(2) = 00100100b
char(3) = 00011000b
move_x = 5
Case "q"
char(0) = 00011000b
char(1) = 00100100b
char(2) = 00100100b
char(3) = 11111100b
move_x = 5
Case "r"
char(0) = 01111000b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 00000100b
move_x = 5
Case "s"
char(0) = 01001000b
char(1) = 01010100b
char(2) = 01010100b
char(3) = 01010100b
char(4) = 00100000b
move_x = 6
Case "t"
char(0) = 00111111b
char(1) = 01000100b
char(2) = 01000100b
move_x = 4
Case "u"
char(0) = 00111100b
char(1) = 01000000b
char(2) = 01000000b
char(3) = 01111100b
move_x = 5
Case "v"
char(0) = 00011100b
char(1) = 00100000b
char(2) = 01000000b
char(3) = 00100000b
char(4) = 00011100b
move_x = 6
Case "w"
char(0) = 00111100b
char(1) = 01000000b
char(2) = 00100000b
char(3) = 00010000b
char(4) = 00100000b
char(5) = 01000000b
char(6) = 00111100b
move_x = 8
Case "x"
char(0) = 01101100b
char(1) = 00010000b
char(2) = 00010000b
char(3) = 01101100b
move_x = 5
Case "y"
char(0) = 10001100b
char(1) = 10010000b
char(2) = 10010000b
char(3) = 01111100b
move_x = 5
Case "z"
char(0) = 01100100b
char(1) = 01010100b
char(2) = 01001100b
move_x = 4
Case "0"
char(0) = 00111110b
char(1) = 01000001b
char(2) = 01000001b
char(3) = 00111110b
move_x = 5
Case "1", 1
char(0) = 01000010b
char(1) = 01111111b
char(2) = 01000000b
move_x = 4
Case "2", 2
char(0) = 01100010b
char(1) = 01010001b
char(2) = 01010001b
char(3) = 01001110b
move_x = 5
Case "3", 3
char(0) = 01000010b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110110b
move_x = 5
Case "4", 4
char(0) = 00011111b
char(1) = 00010000b
char(2) = 00010000b
char(3) = 01111100b
char(4) = 00010000b
move_x = 6
Case "5", 5
char(0) = 00100111b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110001b
move_x = 5
Case "6", 6
char(0) = 00111110b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110010b
move_x = 5
Case "7", 7
char(0) = 00000001b
char(1) = 01110001b
char(2) = 00011001b
char(3) = 00000111b
move_x = 5
Case "8", 8
char(0) = 00110110b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110110b
move_x = 5
Case "9", 9
char(0) = 00100110b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00111110b
move_x = 5
Case "."
char(0) = 01100000b
char(1) = 01100000b
move_x = 3
Case ":"
char(0) = 01100110b
char(1) = 01100110b
move_x = 3
Case 32
move_x = 4
Case "{"
Gosub draw_wifi
EndSelect
Return
send_character_to_lcd:
'put the lcd into data mode
High lcd_command
For i = 0 To 6
byte_to_send = char(i)
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
Gosub lcd_write_byte
Next i
Return
lcd_write_string:
sk = Len(string_to_write) - 1
For si = 0 To sk
'convert the requested character into an array of bits to display
character_to_send = string_to_write(si)
Gosub lcd_get_character
'check the character will fit on the screen
k = x_value + move_x
If k > 82 And wrap_text = 0 Then
'don't write anything more on this line
x_value = 84
Else
If k > 82 Then
x_value = 2
y_value = y_value + 1
Gosub lcd_goto_xy
Endif
'send the character to the lcd
Gosub send_character_to_lcd
'update the "cursor x" position
x_value = x_value + move_x
Gosub lcd_goto_xy
Endif
Next si
Return
draw_band:
x_value = 0
Gosub lcd_goto_xy
'put the lcd into data mode
High lcd_command
byte_to_send = 11110000b
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
For i = 0 To 83
Gosub lcd_write_byte
Next i
byte_to_send = 0xff
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
For i = 0 To 83
Gosub lcd_write_byte
Next i
byte_to_send = 00000111b
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
For i = 0 To 83
Gosub lcd_write_byte
Next i
Return
draw_wifi:
For i = 0 To 14
Select Case i
Case 0, 14
byte_to_send = 00001000b
Case 1, 13
byte_to_send = 00000100b
Case 2, 12
byte_to_send = 00000010b
Case 3, 11
byte_to_send = 00010010b
Case 4, 10
byte_to_send = 00001001b
Case 5, 9
byte_to_send = 00100101b
Case 6, 8
byte_to_send = 10010101b
Case 7
byte_to_send = 11010101b
EndSelect
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
Gosub lcd_write_byte
Next i
x_value = x_value + 16
Gosub lcd_goto_xy
Return
Define CLOCK_FREQUENCY = 20
AllDigital
Symbol led_pin = PORTB.7
Symbol lcd_sck = PORTD.4
Symbol lcd_data = PORTD.5
Symbol lcd_command = PORTD.6
Symbol lcd_reset = PORTD.7
definitions:
Define STRING_MAX_LENGTH = 30
Dim i As Byte
Dim j As Byte
Dim k As Byte
Dim li As Byte
Dim lj As Byte
Dim lk As Byte
Dim si As Byte
Dim sk As Byte
Dim byte_to_send As Byte
Dim x_value As Byte
Dim y_value As Byte
Dim character_to_send As Byte
Dim char(8) As Byte
Dim move_x As Byte
Dim string_to_write As String
Dim invert_display As Bit
Dim wrap_text As Bit
init:
ConfigPin PORTB = Output
ConfigPin PORTD = Output
invert_display = 0
wrap_text = 0
WaitMs 100
Gosub init_lcd
Gosub lcd_clear
x_value = 2 'columns are individual pixels
y_value = 0 'must be a row number, which is a multiple of 8
Gosub lcd_goto_xy
Gosub draw_band
x_value = 2
y_value = 1
Gosub lcd_goto_xy
invert_display = 1
wrap_text = 0
string_to_write = "{ ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Gosub lcd_write_string
invert_display = 0
x_value = 2
y_value = 3
wrap_text = 1
Gosub lcd_goto_xy
string_to_write = "abcdefghijklmnopqrstuvwxyz"
Gosub lcd_write_string
x_value = 2
y_value = 5
Gosub lcd_goto_xy
string_to_write = "123.45.67.89:0"
Gosub lcd_write_string
loop:
High led_pin
WaitMs 2000
Low led_pin
WaitMs 2000
Goto loop
End
init_lcd:
Low lcd_reset
WaitMs 10
High lcd_reset
'put into command mode
Low lcd_command
byte_to_send = 0x21 'lcd extended commands
Gosub lcd_write_byte
byte_to_send = 0xb1 'set lcd contrast
Gosub lcd_write_byte
byte_to_send = 0x04 'set temp coefficient
Gosub lcd_write_byte
byte_to_send = 0x14 'lcd bias mode 1:48
Gosub lcd_write_byte
byte_to_send = 0x0c 'put lcd into normal mode
Gosub lcd_write_byte
byte_to_send = 0x20 'dunno
Gosub lcd_write_byte
byte_to_send = 0x0c 'dunno
Gosub lcd_write_byte
WaitMs 5
'put into data mode
High lcd_command
Return
lcd_write_byte:
For li = 0 To 7
lk = 7 - li
lj = 1
lj = ShiftLeft(lj, lk)
lj = lj And byte_to_send
If lj = 0 Then
'send a zero bit
Low lcd_data
Else
'send a one bit
High lcd_data
Endif
'toggle the clock line
High lcd_sck
ASM: nop
Low lcd_sck
Next li
Return
lcd_clear:
'put the cursor at 0,0
x_value = 0
y_value = 0
Gosub lcd_goto_xy
'put the lcd into data mode
High lcd_command
'send 504 (48*84/8) blank pixels
For i = 0 To 5
For j = 0 To 83
byte_to_send = 0x00
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
Gosub lcd_write_byte
Next j
Next i
'just give everything a sec or two
WaitMs 10
Return
lcd_goto_xy:
Low lcd_command
byte_to_send = 0x80
byte_to_send = byte_to_send Or x_value
Gosub lcd_write_byte
byte_to_send = 0x40
byte_to_send = byte_to_send Or y_value
Gosub lcd_write_byte
High lcd_command
Return
lcd_get_character:
'set the default character to zero
char(0) = 0x00
char(1) = 0x00
char(2) = 0x00
char(3) = 0x00
char(4) = 0x00
char(5) = 0x00
char(6) = 0x00
move_x = 0
Select Case character_to_send
Case "A"
char(0) = 01111110b
char(1) = 00001001b
char(2) = 00001001b
char(3) = 01111110b
move_x = 5
Case "B"
char(0) = 01111111b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110110b
move_x = 5
Case "C"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01000001b
move_x = 5
Case "D"
char(0) = 01111111b
char(1) = 01000001b
char(2) = 01000001b
char(3) = 00100010b
char(4) = 00011100b
move_x = 6
Case "E"
char(0) = 01111111b
char(1) = 01001001b
char(2) = 01000001b
move_x = 4
Case "F"
char(0) = 01111111b
char(1) = 00001001b
char(2) = 00001001b
move_x = 4
Case "G"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01001001b
char(4) = 01111010b
move_x = 6
Case "H"
char(0) = 01111111b
char(1) = 00001000b
char(2) = 00001000b
char(3) = 01111111b
move_x = 5
Case "I"
char(0) = 01000001b
char(1) = 01111111b
char(2) = 01000001b
move_x = 4
Case "J"
char(0) = 00100000b
char(1) = 01000000b
char(2) = 01000001b
char(3) = 00100001b
char(4) = 00011111b
move_x = 6
Case "K"
char(0) = 01111111b
char(1) = 00001000b
char(2) = 00010100b
char(3) = 01100011b
move_x = 5
Case "L"
char(0) = 01111111b
char(1) = 01000000b
char(2) = 01000000b
move_x = 4
Case "M"
char(0) = 01111111b
char(1) = 00000001b
char(2) = 00000010b
char(3) = 00001100b
char(4) = 00000010b
char(5) = 00000001b
char(6) = 01111111b
move_x = 8
Case "N"
char(0) = 01111111b
char(1) = 00000100b
char(2) = 00001000b
char(3) = 00010000b
char(4) = 01111111b
move_x = 6
Case "O"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01000001b
char(4) = 00100010b
char(5) = 00011100b
move_x = 7
Case "P"
char(0) = 01111111b
char(1) = 00010001b
char(2) = 00010001b
char(3) = 00001110b
move_x = 5
Case "Q"
char(0) = 00011100b
char(1) = 00100010b
char(2) = 01000001b
char(3) = 01010001b
char(4) = 00100010b
char(5) = 01011100b
move_x = 7
Case "R"
char(0) = 01111111b
char(1) = 00011001b
char(2) = 00101001b
char(3) = 01000110b
move_x = 5
Case "S"
char(0) = 00100010b
char(1) = 01000101b
char(2) = 01001001b
char(3) = 00110010b
move_x = 5
Case "T"
char(0) = 00000001b
char(1) = 00000001b
char(2) = 01111111b
char(3) = 00000001b
char(4) = 00000001b
move_x = 6
Case "U"
char(0) = 00111111b
char(1) = 01000000b
char(2) = 01000000b
char(3) = 01111111b
move_x = 5
Case "V"
char(0) = 00000011b
char(1) = 00011100b
char(2) = 01100000b
char(3) = 00011100b
char(4) = 00000011b
move_x = 6
Case "W"
char(0) = 00111111b
char(1) = 01000000b
char(2) = 00100000b
char(3) = 00011000b
char(4) = 00100000b
char(5) = 01000000b
char(6) = 00111111b
move_x = 8
Case "X"
char(0) = 01100011b
char(1) = 00010100b
char(2) = 00001000b
char(3) = 00010100b
char(4) = 01100011b
move_x = 6
Case "Y"
char(0) = 00000011b
char(1) = 00000100b
char(2) = 01111100b
char(3) = 00000111b
move_x = 5
Case "Z"
char(0) = 01111001b
char(1) = 01001001b
char(2) = 01001101b
char(3) = 01001011b
move_x = 5
Case "a"
char(0) = 00100000b
char(1) = 01010100b
char(2) = 01010100b
char(3) = 01111000b
move_x = 5
Case "b"
char(0) = 01111111b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 00111000b
move_x = 5
Case "c"
char(0) = 00111000b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 01000100b
move_x = 5
Case "d"
char(0) = 00111000b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 01111111b
move_x = 5
Case "e"
char(0) = 00111000b
char(1) = 01010100b
char(2) = 01010100b
char(3) = 01011100b
move_x = 5
Case "f"
char(0) = 01111110b
char(1) = 00001001b
char(2) = 00000001b
move_x = 4
Case "g"
char(0) = 10011000b
char(1) = 10100100b
char(2) = 10100100b
char(3) = 01111100b
move_x = 5
Case "h"
char(0) = 01111111b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 01111000b
move_x = 5
Case "i"
char(0) = 01000100b
char(1) = 01111101b
char(2) = 01000000b
move_x = 4
Case "j"
char(0) = 10000100b
char(1) = 10000101b
char(2) = 01111100b
move_x = 4
Case "k"
char(0) = 01111111b
char(1) = 00010000b
char(2) = 00010000b
char(3) = 01101100b
move_x = 5
Case "l"
char(0) = 01000001b
char(1) = 01111111b
char(2) = 01000000b
move_x = 4
Case "m"
char(0) = 01111100b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 01111000b
char(4) = 00000100b
char(5) = 00000100b
char(6) = 01111000b
move_x = 8
Case "n"
char(0) = 01111100b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 01111000b
move_x = 5
Case "o"
char(0) = 00111000b
char(1) = 01000100b
char(2) = 01000100b
char(3) = 00111000b
move_x = 5
Case "p"
char(0) = 11111100b
char(1) = 00100100b
char(2) = 00100100b
char(3) = 00011000b
move_x = 5
Case "q"
char(0) = 00011000b
char(1) = 00100100b
char(2) = 00100100b
char(3) = 11111100b
move_x = 5
Case "r"
char(0) = 01111000b
char(1) = 00000100b
char(2) = 00000100b
char(3) = 00000100b
move_x = 5
Case "s"
char(0) = 01001000b
char(1) = 01010100b
char(2) = 01010100b
char(3) = 01010100b
char(4) = 00100000b
move_x = 6
Case "t"
char(0) = 00111111b
char(1) = 01000100b
char(2) = 01000100b
move_x = 4
Case "u"
char(0) = 00111100b
char(1) = 01000000b
char(2) = 01000000b
char(3) = 01111100b
move_x = 5
Case "v"
char(0) = 00011100b
char(1) = 00100000b
char(2) = 01000000b
char(3) = 00100000b
char(4) = 00011100b
move_x = 6
Case "w"
char(0) = 00111100b
char(1) = 01000000b
char(2) = 00100000b
char(3) = 00010000b
char(4) = 00100000b
char(5) = 01000000b
char(6) = 00111100b
move_x = 8
Case "x"
char(0) = 01101100b
char(1) = 00010000b
char(2) = 00010000b
char(3) = 01101100b
move_x = 5
Case "y"
char(0) = 10001100b
char(1) = 10010000b
char(2) = 10010000b
char(3) = 01111100b
move_x = 5
Case "z"
char(0) = 01100100b
char(1) = 01010100b
char(2) = 01001100b
move_x = 4
Case "0"
char(0) = 00111110b
char(1) = 01000001b
char(2) = 01000001b
char(3) = 00111110b
move_x = 5
Case "1", 1
char(0) = 01000010b
char(1) = 01111111b
char(2) = 01000000b
move_x = 4
Case "2", 2
char(0) = 01100010b
char(1) = 01010001b
char(2) = 01010001b
char(3) = 01001110b
move_x = 5
Case "3", 3
char(0) = 01000010b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110110b
move_x = 5
Case "4", 4
char(0) = 00011111b
char(1) = 00010000b
char(2) = 00010000b
char(3) = 01111100b
char(4) = 00010000b
move_x = 6
Case "5", 5
char(0) = 00100111b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110001b
move_x = 5
Case "6", 6
char(0) = 00111110b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110010b
move_x = 5
Case "7", 7
char(0) = 00000001b
char(1) = 01110001b
char(2) = 00011001b
char(3) = 00000111b
move_x = 5
Case "8", 8
char(0) = 00110110b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00110110b
move_x = 5
Case "9", 9
char(0) = 00100110b
char(1) = 01001001b
char(2) = 01001001b
char(3) = 00111110b
move_x = 5
Case "."
char(0) = 01100000b
char(1) = 01100000b
move_x = 3
Case ":"
char(0) = 01100110b
char(1) = 01100110b
move_x = 3
Case 32
move_x = 4
Case "{"
Gosub draw_wifi
EndSelect
Return
send_character_to_lcd:
'put the lcd into data mode
High lcd_command
For i = 0 To 6
byte_to_send = char(i)
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
Gosub lcd_write_byte
Next i
Return
lcd_write_string:
sk = Len(string_to_write) - 1
For si = 0 To sk
'convert the requested character into an array of bits to display
character_to_send = string_to_write(si)
Gosub lcd_get_character
'check the character will fit on the screen
k = x_value + move_x
If k > 82 And wrap_text = 0 Then
'don't write anything more on this line
x_value = 84
Else
If k > 82 Then
x_value = 2
y_value = y_value + 1
Gosub lcd_goto_xy
Endif
'send the character to the lcd
Gosub send_character_to_lcd
'update the "cursor x" position
x_value = x_value + move_x
Gosub lcd_goto_xy
Endif
Next si
Return
draw_band:
x_value = 0
Gosub lcd_goto_xy
'put the lcd into data mode
High lcd_command
byte_to_send = 11110000b
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
For i = 0 To 83
Gosub lcd_write_byte
Next i
byte_to_send = 0xff
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
For i = 0 To 83
Gosub lcd_write_byte
Next i
byte_to_send = 00000111b
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
For i = 0 To 83
Gosub lcd_write_byte
Next i
Return
draw_wifi:
For i = 0 To 14
Select Case i
Case 0, 14
byte_to_send = 00001000b
Case 1, 13
byte_to_send = 00000100b
Case 2, 12
byte_to_send = 00000010b
Case 3, 11
byte_to_send = 00010010b
Case 4, 10
byte_to_send = 00001001b
Case 5, 9
byte_to_send = 00100101b
Case 6, 8
byte_to_send = 10010101b
Case 7
byte_to_send = 11010101b
EndSelect
If invert_display = 1 Then byte_to_send = byte_to_send Nand 0xff
Gosub lcd_write_byte
Next i
x_value = x_value + 16
Gosub lcd_goto_xy
Return
We've written our font "table" as a select case statement.
When it come to being compiled down, a look up table and a select case statement are very similar anyway (and we just prefer using IF statements - just ask Steve!).
The font values are written in long-hand binary, rather than in decimal or their short-hand hex values. This makes no difference whatsoever to the final code (since the compiler treats all constant values the same, however they are written).
We stuck with long-hand binary, as it helps us to "see" the fonts and graphics inside the source code;
Drawing to the screen is as simple as sending an x and a y co-ordinate value (x is any number 0-83 and y is any "row" from 0 to 5, representing an actual co-ordinate value of 0, 8, 16, 32, 40 or 48). The next eight bits (single byte) are then used to draw "upwards" from the cursor position. If more than 8 bits are sent, the cursor position returns to the original y axis value, and the x-position shifts across one pixel.
There are also a couple of extras built into this example.
You can set the "inverted" flag on and off, to draw white text over a black background, or black text on a white background (the background colour should be fully drawn beforehand).
There's also a simple routine to draw a horizontal bar across the screen, to allow inverted text to be seen against a plain/blank background. An example of this in use would be a menu highlight system.
We also added a "text wrap" toggle, which determines - if the text is two large to fit onto one row - whether or not to break the work/string and draw it across two or more rows.
So far we've got upper and lower case letters, numbers and a few punctuation marks.
We're also using special characters to draw bitmaps at the cursor location (this isn't the correct use of the "library" - we were just keen to see how non-alphanumeric characters appeared!)
Heres' a photo of the screen in action:
We feel that the non-fixed width font just looks that little bit more "friendly" and less "hacky" and "homemade" than other library-based fonts.
The code above could easily be ported to another platform (such as Arduino).
We deliberately avoided using the hardware SPI peripheral, to allow it to be ported to any other microcontroller, without spoiling existing libraries or limit it to only those devices with a free hardware SPI module.
We really like these displays and - for a quid more than a 16x2 line character LCD display - we're looking at using these in a future wifi-based project (just as soon as our ESP8266 modules arrive!)
No comments:
Post a Comment