' MAX7219_2.Bas (PICAXE-18X) (Final Test - okay)
'
' Illustrates the use of a MAX7219 interfaced with four blocks of
' eight (32) discrete LEDs arranged in a column.  This could be
' expanded to a maximum of 64 LEDs
'
' Displays a quantity Val in the range of 0 to 100 as a "height" on the
' column of LEDs.
'
'  PICAXE-18X 	             MAX7219
'
'  CS (term 6) ------------ LOAD (term 12)
'  CLK (term 7) ----------- CLK (term 13)
'  DAT (term 8) ----------- DIN (term 1)
'
' In initializing the MAX7219;
'
'    Decode Mode (Register 9) set for Non Code B on all digits.
'    Intensity (Register 10) set for 17/32
'    Scan Limit (Register 11) set for Digits 0, 1, 2, 3
'    Shutdown (Register 12) set for normal operation.
'
' Uses nominally 300 bytes of program memory.
'
' This was a part of a Senior Project by Charne Owens.
'
' copyright, Charne Owens, Peter H Anderson, Baltimore, MD, April, '04


' define inputs and outputs
Symbol CS = 0	' out0
Symbol SCK = 1
Symbol MOSI = 2
Symbol MISO = Pin0 ' not used in this implementation

' define MAX7219 registers
Symbol DecodeMode = $09
Symbol Intensity = $0a
Symbol ScanLimit = 0x0b
Symbol Shutdown = $0c

' variables
Symbol Val = B0		' value to be represented
Symbol NumLEDsTot = B1  ' total number of LEDs to light (32 max)
Symbol NumFullBlocks = B2  ' number of full blocks of eight
Symbol PartBlock = B3	' remaining number of LEDs

Symbol Block = B4	' range of 1 to 4
Symbol NumLEDs = B5	' Number of LEDs within a block

Symbol N = B6
Symbol X = B7

   Pause 1000

   ' set up SPI outputs
   Low SCK
   Low MOSI
   High CS

   Pause 1000

   GoSub SetUp		' configure the MAX7219

Top:
   GoSub BlankLEDs
   For Val = 0 to 100
       ' 32 / 100 = 0.32 LEDs per tick
       NumLEDsTot = Val / 2 * 3 / 5	' NumLEDs = 0.3 * Val
       NumLEDsTot = Val * 2 / 100 + NumLEDsTot
       NumFullBlocks = NumLEDsTot / 8
       PartBlock = NumLEDsTot % 8
       ' SerTxD (#Val, "  ", #NumLedsTot, "  ", #NumFullBlocks, "  ", #PartBlock, 13, 10)
       Block = 1
       If NumFullBlocks = 0 Then OutPartBlock

       For Block = 1 to NumFullBlocks
          NumLEDs = 8
          GoSub OutBlock
       Next
OutPartBlock:
       NumLEDs = PartBlock
       GoSub OutBlock
       Pause 25
   Next
   Pause 10000		' 10 second wait
   Goto TOP

OutBlock:	' light the NumLEDS in digit Block
   Low CS
   X = Block
   GoSub SPI_IO

   Lookup NumLEDs, ($00, $01, $03, $07, $0f, $1f, $3f, $7f, $ff), X
   GoSub SPI_IO
   High CS

   Return

SetUp:

   Low CS
   X = DecodeMode
   GoSub SPI_IO
   X = $00		' non code B for all digits
   GoSub SPI_IO
   High CS

   Low CS
   X = ScanLimit
   GoSub SPI_IO
   X = $03		' display digits 1, 1, 2 and 3
   GoSub SPI_IO
   High CS

   Low CS
   X = Intensity
   GoSub SPI_IO
   X = $08		' 17 / 32 intensity
   GoSub SPI_IO
   High CS

   Low CS
   X = Shutdown
   GoSub SPI_IO
   X = $01		' normal operation - not shutdown
   GoSub SPI_IO
   High CS

   Return


BlankLEDs:	' write $00 to each digit to blank
' could use For Loop
   Low CS
   X = $01
   GoSub SPI_IO
   X = $00
   GoSub SPI_IO
   High CS

   Low CS
   X = $02
   GoSub SPI_IO
   X = $00
   GoSub SPI_IO
   High CS

   Low CS
   X = $03
   GoSub SPI_IO
   X = $00
   GoSub SPI_IO
   High CS

   Low CS
   X = $04
   GoSub SPI_IO
   X = $00
   GoSub SPI_IO
   High CS

SPI_IO:
   For N = 1 to 8
      If X > 127 Then SPI_IO_1	' if most sig bit is a one
      Low MOSI 					' otherwise set MOSI to a zero
      Goto SPI_IO_2

SPI_IO_1:
      High MOSI
SPI_IO_2:
      High SCK 					' clk high
      X = X * 2 + MISO			' read MISO
      Low SCK 					' clk low
   Next

   Return