Dot Matrix
Dot Matrix
display
BASCOM guru Ben Zijlstra wrote support for the neat matrix board based on some code he found on the net.
Paulvk (check out his forums blog projects) added a lot of functionality such as IR control as you can read in his blog.
So a good moment to create an AN out if it.
Because size of schematic of main board it can be downloaded from here : jy-
mcu_3208_schematic.pdf (34.10 KB)
Full commented source code: (can be downloaded with rest files from here : Matrix-Clock-Programs.zip )
( code is based on Ben Zijlstra’s code published on MCS Forum )
'---------------------------------------------------------------------------------------
'This is for the 4 digit HT1632 driven 32 x 8 matrix display JY-MCU-3208
' Note as the code takes almost all the flash some parts need
' to be commented out to use the debug prints
' A RX8025 real time clock and resistors have been soldered to the board
' also a MCP9700 analog temprature sensor has been used in place of an I2C
' one as the RTC is on diffrent pins and we can only have one I2C port in Bascom
' with this board/AVR
' A TSOP31236 infra-red reciver is used but any suitable one that runs off 5 volts will do
' The 3 buttons on the board are not used as space in flash was needed
' and they are redundant with an IR remote
' It is nessary to load and run the infra-red timing and decode programs
' to determin the characteristics and codes for the remote used Demo version of
' Bascom can be used for this but the full is required for this code'
'--------------------------------------------------------------------------
' I have left some replaced code in but commented out so that it can be seen
' how Sub programs can be used to reduce code & flash use
'
'
'
'-------------------------------------------------------------------------------------------------
-------------
'
'I used an old VCR remote control hence PLAY & EJECT just replace the codes received for the butto
ns
'in your remote at the constants and re-type the instructions with your button choices
'Note I wrote these instructions for myself as there are too many to remember!
'
'
'CLOCK OPERATING INSTRUCTIONS
'
'
'Constant Button Function
'
'Pause PAUSE This displays the temprature
'
'Irclock CLOCK This puts theclock into time set mode
'
'Play PLAY This causes the date to be displayed
'
'Eject EJECT This turns the display off
'
'Poweron POWER ON This turns the display on
'
'Square SQUARE This sets the display to max brightness
'
'Arrowright ARROWRIGHT This changes the brightnes in steps from low to high in a loop
'
'Rew REWIND This stors the current brightness as the DUSK SETTING
'
'Ff FAST FORWARD This stors the current brightness as the DAYLIGHT SETTING
'
'Sstop STOP This stors the current brightness as the DARK SETTING
'
'Rec RECORD This turns the alarm on
'
'Tvvcr TVVCR This turns the alarm off & stops the display flashing
'
'TIME SET MODE-------------------AFTER PRESSING CLOCK
'
'Longp LONGPLAY This selects - Set the time
'
'Av AV This selects - Set the date
'
'Skip SKIP This selects - Set the alarm time and days
'
'How to set Time & Date
'----------------------------
'
'Press CLOCK this puts us into setting mode at any time pressing CLEAR will abort the mode
'
'Press LONGPLAY to set the time
'Enter hours and minutes via the number buttons then press OK to store them
'
'Press AV to set the date
'Enter month then day then two digits for the year the 20 is entered automatically (so it works fo
r only 98 years)
'now press REC Record Day will be displayed then enter the day of the week starting at 0 for sunda
y
'when the correct day is shown press OK to store the date
'
'Press SKIP to set the alarm time and days
'Enter hours and minutes
'then press ARROW UP to move through the days of the week SUN MON TUE will display on the clock
'then press 1 or 0 1 will set that day for an alarm 0 with turn that day off any other number is
a 1
'press OK to store the alarm setting
'
'-------------------------------------------------------------------------------------------------
--------------------
$regfile = "m8adef.dat"
$crystal = 8000000 'using internal RC
$hwstack = 128
$swstack = 256
$framesize = 256
$baud = 19200
'--fuse settings
'$PROG &HFF,&HC4,&HC7,&H00' generated. Take care that the chip supports all fuse bytes.
'address of rx8025
Const Rx8025w = &H64 ' Addresses of rx8025 clock
Const Rx8025r = &H65
Const 24hr = &HE0 'select 24 hour mode
Const 24hron = &H20
Const Alarmon = &HE3
Const Alarmoff = &H23
'--remote control constants need to test with chosen remote to get codes
'--using the infra-red debugging programs with a serial port on a pc
'--
'Set Portd.5
'Set Portd.6 'Switch on the pullup for the buttons
'Set Portd.7
'Config Debounce = 1
Dim Alarmmins As Eram Byte 'this is the alarm settings for minutes
Dim Alarmhours As Eram Byte 'this is the alarm settings for hours
Dim Alarmdays As Eram Byte 'this is the alarm settings for days
Dim B As Byte
Config Scl = Portb.1 ' we need to provide the SCL pin name
Config Sda = Portb.2 ' we need to provide the SDA pin name
Dim G As String * 32
'--infra red
Dim Bb(8) As Byte 'a place to stor the 8 bytes of the character
'font from eeprom
'--digits 1 to four with space for two digits the before and after
'--so we can roll them in
'--this holds each 8x8 digit in one variable
Dim Dig1 As Double
Dim Dig2 As Double
Dim Dig3 As Double
Dim Dig4 As Double
'--with the overlay we break up each double into 8 bytes which gives us each row 1 t 8
'--and importantly uses no RAM
Dim Light As Word 'value from the ADC connected to the light sensor
'used in deguging
'Dim N As Byte
'Dim M As Byte
'Dim O As Byte
'Dim P As Byte
'
'Set up the ADC part of the chip let the compliler handle Prescaler = Auto set the Reference = A
vcc this uses the voltage
'fed to the micro, the board has a 1nF capacitor from AREF to ground already so no need to add it
'
Config Clock = User 'we do our own clock (User) not using t
he megaAVR timer and 32KHz crystal
'---
'--- NOTE You must enable the individual interrupts for them to work
'--- Enable Interrupts does not do this
'---
Enable Interrupts
I2caddress = &HE4
Call I2c_read
'debug prints
Eereg = Ereg
If I2cdata = Eereg Then 'if it does not match the stored value
'this may be because the alarm is on
nop
I2caddress = &HE0
I2cdata = Eereg
Call I2c_write
End If
'--debug prints
'----------------------------
'--this shows how to read the control registers of the RX8025
'I2crbyte N , Ack
'I2crbyte M , Ack
'I2crbyte O , Ack
'I2crbyte P , Nack
'I2cstop
Daybit = 1
D = 12
Set Cs1
Shiftdat = Sysen
Call Commandout
Shiftdat = Ledon
Call Commandout
Call Commandout
Shiftdat = Rc
Call Commandout
Shiftdat = Commonsoption
Call Commandout
Pulswidth = 2368
Shiftdat = Pwmduty
Call Commandout
'here we get the alarm time from eeprom to write to the RTC
'at default these will be all 0 but if we set alarm values and
'the back up battery is flat we will have not to reset the alarm data
'also as I intend to have a clock with a retrofited mega328 which will
'get its time from the internet via NTP so it does not even need back up
Lmins = Alarmmins
Lhour = Alarmhours
Daybyte = Alarmdays
'if the value is greater than 0
If Lhour > 0 Then 'write alarm time to real time clock
End If
Dignum = 1
Dotim = 0
Dodat = 0
Klk = 0
Tick = 60
'Call Showtime
Do
If Klk = 0 Then 'if Klk 1 we are setting the time & date
'so leave display alone
If Tick >= 59 Then
'--debug print
'Print "Light" ; Light 'this is so you can determin what is the da
rk, dusk, daylight value
'comment out date$ print to use
Select Case Light
Case Else
End Select
Shiftdat = Pulswidth
Call Commandout
Call Showtime
Call Set_tick
End If
End If
Call Commandout
End If
End
I2cstop
End Sub
I2cstop
End Sub
Call Get_chr
Call Rotate_chr
Call Roll_over
End Sub
'-display digit 1 & 2
Sub Dig1_2
Dignum = 1
Kar = Left(lt , 1)
Call Display_chr
Dignum = 2
Kar = Mid(lt , 2 , 1)
Call Display_chr
End Sub
Dignum = 3
Kar = Mid(lt , 4 , 1)
Call Display_chr
Dignum = 4
Kar = Mid(lt , 5 , 1)
Call Display_chr
End Sub
Sub Showtime
Local Lm As String * 2
Local Ln As String * 2
Local Lo As String * 4
Case 0
Lt = Time$
Case 1
Lt = Date$
Tick = 0
Lm = Left(lt , 2) 'month
Ln = Mid(lt , 4 , 2) 'day
Lo = Right(lt , 2) 'year
Print Lt
Seeprm = 26 'eeprom start point
Steps = 4 'number of bytes from eeprom
Wait 2
End Select
'--debug print
'Print "LT>>" ; Lt
Call Dig1_2
Call Dig3_4
If Timedate = 1 Then
Wait 5
Seeprm = 34
Steps = 2
Call St_time
Dignum = 3
Kar = Mid(lt , 7 , 1)
Call Display_chr
Dignum = 4
Kar = Mid(lt , 8 , 1)
Call Display_chr
Wait 5
Timedate = 0
Tick = 60
Exit Sub
Call Set_tick
End If
End Sub
Sub Set_tick
Local Lk As String * 2
Lt = Time$
Lk = Right(lt , 2)
Tick = Val(lk) - 2
End Sub
'--this gets the data from the infra-red
Int_one:
'--the values in the case statements can be found with the infra-red debug programs
Case Is < 60
Recvdata.bx = 0
Incr Bx
Recvdata.bx = 1
Incr Bx
'Print "1" 'debug
End Select
Return
'--this gets characters from the eeprom which have been placed in a particular
'--place and order there to make them simple to read this saves code space
Sub St_time
Local Lb As Byte
Dignum = Lb
Call Display_chr
Incr Seeprm
Next Lb
End Sub
'--this reduced the code by over 100 bytes
'--any task done a number of times can in most cases
'--be done in a sub saving flash
Sub Add_kar
Call Display_chr
Incr Dignum
End Sub
Sub Add_chr
Case 1 To 2
Call Add_kar
Case 3
Call Add_kar
Case 4
Call Display_chr
Dignum = 1
End Select
Case 1 To 2
Call Add_kar
Case 3
Call Add_kar
Case 4
Call Add_kar
Case 5
Lkar = Kar 'save character
Seeprm = 34
Steps = 2
Call St_time
'debug print
'Print "tset-mel>>" ; Kar
Dignum = 3
Call Add_kar
Dignum = 6
Case 6
Dignum = 4
Call Add_kar
Digit = 1
Case 7
Dignum = 4
Dayweek = Val(kar)
Call Display_chr
End Select
Case 2
Call Add_kar
Dignum = 4
Call Display_chr
Lbit = Val(kar)
'debug
'Print "Lbit" ; Lbit
If Lbit > 1 Then 'so if you press a number higher than 1 we asume it to be 1
Lbit = 1
End If
Daybyte.daybit = Lbit
'DEBUG PRINT
'Print "tset>>" ; Timeset
'Print "YES" ; Bin(daybyte)
Incr Daybit
End Select
End Select
End Sub
'debug
'Print Datain(1) 'these are to see the codes from remote
'Print Datain(2)
Datain(1) = 0
Dotim = 1
Dodat = 0
Timeset = ""
Seeprm = 22
Steps = 4 'number of bytes from eeprom
Call St_time
Dignum = 1
Timeset = ""
Seeprm = 26
Steps = 4 'number of bytes from eeprom
Call St_time
Dignum = 1
Dotim = 2
Timeset = ""
Seeprm = 45
Steps = 4
Days = 1
Daybit = 0 'number of bytes from eeprom
Call St_time
Dignum = 1
'Case 0
Kar = "1"
Call Add_chr
Kar = "2"
Call Add_chr
Kar = "3"
Call Add_chr
Kar = "4"
Call Add_chr
Kar = "5"
Call Add_chr
Kar = "6"
Call Add_chr
Kar = "7"
Call Add_chr
Case Numeight 'number 8
Kar = "8"
Call Add_chr
Kar = "9"
Call Add_chr
Kar = "0"
Call Add_chr
Dotim = 2
Call St_time
Dignum = 5
'Wait 1
Call St_time
Dignum = 7
Case Ok
Case 0 'date
Tick = 0
Klk = 0
Case 1 'time
Tick = 0
Klk = 0
Case 2 'alarm set
Alm = Left(timeset , 2)
Lhour = Val(alm)
Lhour = Makebcd(lhour)
Alm = Mid(timeset , 3 , 2)
Lmins = Val(alm)
Lmins = Makebcd(lmins)
Tick = 58
Klk = 0
End Select
Call Showtime
Klk = 0
Dignum = 1
Call Showtime
End Select
Recvdata = 0
Else
Seeprm = 30
Steps = 4 'number of bytes from eeprom
'to display the word TEMP
Call St_time
Dignum = 1
Wait 2
Temp = Getadc(2)
Lt = Tval + ":" 'the ":" character has been replaced by a deg C one in the eeprom
Call Dig1_2
Call Dig3_4
Timedate = 1
Call Showtime
'Call Commandout
Case Eject
Call Commandout
Case Poweron
Call Commandout
Case Square
Call Commandout
Case Arrowright
Call Bright_up
'Case Ff
'I2caddress = &H34
'Call I2c_read
'Print ">>>>" ; Bin(i2cdata)
'I2caddress = &H70
'I2cdata = 0
'Call I2c_write
'Print ">>>>" ; Bin(i2cdata)
'
'I2caddress = &H94
'Call I2c_read
'Print ">>>>" ; Bin(i2cdata)
'I2caddress = &HA4
'Call I2c_read
'Print ">>>>" ; Bin(i2cdata)
'I2caddress = &HF4
'Call I2c_read
'Print ">>>>" ; Bin(i2cdata)
'Call I2c_print
'Case Rew
'I2caddress = &H94
'Call I2c_print
'-------------------------------------------------
Case Rew
Case Ff
Case Sstop
Almison = 0
I2caddress = &HE0
I2cdata = Alarmon
Call I2c_write
I2caddress = &HE0
I2cdata = Alarmoff
Call I2c_write
Call I2c_write
Call Commandout
End Select
Recvdata = 0
End If
End If
End Sub
'Call I2c_read
'Print ">>>>" ; Bin(i2cdata)
'End Sub
Pulswidth = 2368
End If
Shiftdat = Pulswidth
Call Commandout
Pulswidth = Pulswidth + 4
End Sub
'--This ISR gets called once every second using the 1Hz from the RTC chip
Sectic:
'--this If > Then flashes the leds in the center for a clock display
'--once every second
If Klk = 0 Then
Tick = Tick + 1
If Col = 0 Then
'D2(1).7 = 0
D2(2).7 = 1 '*
D2(3).7 = 1 '*
D2(4).7 = 0 '
D2(5).7 = 1 '*
D2(6).7 = 1 '*
D2(7).7 = 0 '
'D2(8).7 = 0
Col = 1
Else
'D2(1).7 = 0
D2(2).7 = 0 '
D2(3).7 = 1 '*
D2(4).7 = 1 '*
D2(5).7 = 0 '
D2(6).7 = 1 '*
D2(7).7 = 1 '*
'D2(8).7 = 0
Col = 0
End If
D2(8).7 = 0
Ana = Dig2
W = 16
Cd = 1
Call Show_text
End If
Return
Sub Show_text
Shiftout Dat , Clk , Ana , 3 , 64 'clock out data 64 bits= one character
'or 8 for one line,
Next Lz
Set Cs1
End Sub
Sub Get_chr
Local Le As Word
Local Lf As Word
Local Lz As Byte
Le = Le - 48
'If Le = 0 Then
'Le = 1
'End If
Lf = Le + Lz
Bb(lz) = Chrrom(lf)
Next Lz
End Sub
'--This rotates the character 90deg to the left each time it is called
Sub Rotate_chr
Local Lj As Byte
Local Lx As Byte
Local Ln As Byte
Local Lp As Byte
For Lj = 1 To 8
Ln = Lj - 1
For Lx = 1 To 8
Lp = Lx - 1
Aa(lj).lp = Bb(lx).ln
Next Lx
Next Lj
End Sub
Sub Roll_over
'Local Lv As Byte
'--changed Lv to global to use Sub Roll_digit
'--removing 3 repeates of similar code saving 166 bytes of flash!
Case 1
Digtemp = Dig1
Call Roll_digit
Dig1 = Digtemp
Ana = Dig1
W = 0 'start of digit 1
Case 2
Digtemp = Dig2
Call Roll_digit
Dig2 = Digtemp
Ana = Dig2
W = 16 'start of digit 2
Case 3
Digtemp = Dig3
Call Roll_digit
Dig3 = Digtemp
Ana = Dig3
W = 32 'start of digit 3
Case 4
Digtemp = Dig4
Call Roll_digit
Dig4 = Digtemp
Ana = Dig4
W = 48 'start of digit 4
End Select
Call Show_text
Next Lv
End Sub
Ddtemp(8) = Ddtemp(7)
Ddtemp(7) = Ddtemp(6)
Ddtemp(6) = Ddtemp(5)
Ddtemp(5) = Ddtemp(4)
Ddtemp(4) = Ddtemp(3)
Ddtemp(3) = Ddtemp(2)
Ddtemp(2) = Ddtemp(1)
Ddtemp(1) = Ddnew(lv)
End Sub
Sub Clrd
End Sub
Sub Commandout
Reset Cs1
Waitus 100
Set Cs1
End Sub
'called from ds1307clock.lib so a DS1307 could be used as they both are similar but
'the RX8025 has its own internal crystal which has been calibrated at the factory
'so it has a higher accuracy
Getdatetime:
I2cstart ' Generate start code
I2cwbyte Rx8025w ' send address
I2cwbyte &H04 ' start address in rx8025
I2crbyte _sec , Ack
I2crbyte _min , Ack ' MINUTES
I2crbyte _hour , Ack ' Hours
I2crbyte Weekday , Ack ' Day of Week
I2crbyte _day , Ack ' Day of Month
I2crbyte _month , Ack ' Month of Year
I2crbyte _year , Nack ' Year
I2cstop
_sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour)
_day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year)
Return
Setdate:
_day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year)
Settime:
I2cstop
Return
'--------------------------------------
'--Here we stor text in eeprom to save on flash space
Data 0 , 62 , 81 , 73 , 69 , 62 , 0 , 0 ' 0
Data 0 , 0 , 66 , 127 , 64 , 0 , 0 , 0 ' 1
Data 0 , 98 , 81 , 73 , 73 , 70 , 0 , 0 ' 2
Data 0 , 34 , 73 , 73 , 73 , 54 , 0 , 0 ' 3
Data 0 , 24 , 20 , 18 , 127 , 16 , 0 , 0 ' 4
Data 0 , 47 , 73 , 73 , 73 , 49 , 0 , 0 ' 5
Data 0 , 60 , 74 , 73 , 73 , 48 , 0 , 0 ' 6
Data 0 , 1 , 113 , 9 , 5 , 3 , 0 , 0 ' 7
Data 0 , 54 , 73 , 73 , 73 , 54 , 0 , 0 ' 8
Data 0 , 6 , 73 , 73 , 41 , 30 , 0 , 0 ' 9
Data 7 , 5 , 7 , 0 , 60 , 66 , 66 , 66 ' : DEG C
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' ;
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' <
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' =
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' >
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' ?
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ' @
Data 0 , 126 , 17 , 17 , 17 , 126 , 0 , 0 ' A
Data 0 , 127 , 73 , 73 , 73 , 54 , 0 , 0 ' B
Data 0 , 62 , 65 , 65 , 65 , 34 , 0 , 0 ' C
Data 0 , 127 , 65 , 65 , 65 , 62 , 0 , 0 ' D
Data 0 , 127 , 73 , 73 , 73 , 65 , 0 , 0 ' E
Data 0 , 127 , 9 , 9 , 9 , 1 , 0 , 0 ' F
Data 0 , 62 , 65 , 73 , 73 , 122 , 0 , 0 ' G
Data 0 , 127 , 8 , 8 , 8 , 127 , 0 , 0 ' H
Data 0 , 0 , 65 , 127 , 65 , 0 , 0 , 0 ' I
Data 0 , 48 , 64 , 64 , 64 , 63 , 0 , 0 ' J
Data 0 , 127 , 8 , 20 , 34 , 65 , 0 , 0 ' K
Data 0 , 127 , 64 , 64 , 64 , 64 , 0 , 0 ' L
Data 0 , 127 , 2 , 4 , 2 , 127 , 0 , 0 ' M
Data 0 , 127 , 2 , 4 , 8 , 127 , 0 , 0 ' N
Data 0 , 62 , 65 , 65 , 65 , 62 , 0 , 0 ' O
Data 0 , 127 , 9 , 9 , 9 , 6 , 0 , 0 ' P
Data 0 , 62 , 65 , 81 , 33 , 94 , 0 , 0 ' Q
Data 0 , 127 , 9 , 9 , 25 , 102 , 0 , 0 ' R
Data 0 , 38 , 73 , 73 , 73 , 50 , 0 , 0 ' S
Data 0 , 1 , 1 , 127 , 1 , 1 , 0 , 0 ' T
Data 0 , 63 , 64 , 64 , 64 , 63 , 0 , 0 ' U
Data 0 , 31 , 32 , 64 , 32 , 31 , 0 , 0 ' V
Data 0 , 63 , 64 , 60 , 64 , 63 , 0 , 0 ' W
Data 0 , 99 , 20 , 8 , 20 , 99 , 0 , 0 ' X
Data 0 , 7 , 8 , 112 , 8 , 7 , 0 , 0 ' Y
'data 0 , 113 , 73 , 69 , 67 , 0 , 0 , 0 ' Z
'Data 7 , 5 , 7 , 0 , 60 , 66 , 66 , 66 ' !
'-------------prompts
Data "S" , "U" , "N" , "M" , "O" , "N" , "T" , "U" , "E" , "W" , "E" , "D"
Data "T" , "H" , "R" , "F" , "R" , "I" , "S" , "A" , "T"
Data "T" , "I" , "M" , "E" , "D" , "A" , "T" , "E" , "T" , "E" , "M" , "P"
Data "2"
Data "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9",
Data "A" , "L" , "A" , "M" , "D" , "A" , "Y" ', "M" , "A" , "L" , "A" , "M"
'Data "A" , "L" , "A" , "M"
Data &H23 'this is the register E control byte
'&H23 is the default with alarm off
'&HA3 is alarm on this is the
'eram variable Ereg