' ===============================================================
' Library for controlling the MAX7219 with PIC18 and _SPI_Lib.bas
' Author: COS (dogflu66@yahoo.es)
' Date: 2025/08/14, 2024/12, Pic18 Basic Compiler Oshonsoft v5.91
' Description:
' Controls LED 7-segment displays (Spi library by hardware).
' ===============================================================
' Test: PIC18f46k22 (64mHZ), PCB HL-K18
' Include "_SPI_Lib.bas" (uses internal spi module).
' ===============================================================
' Number of digits
Const MAX7219_Digits_NUMBER = 8
' MAX7219 Constants
Const MAX7219_DECODE_MODE = 0x09
Const MAX7219_INTENSITY = 0x0A
Const MAX7219_SCAN_LIMIT = 0x0B
Const MAX7219_SHUTDOWN = 0x0C
Const MAX7219_DISPLAY_TEST = 0x0F

' Predefined brightness levels for display segments.
Const MAX7219_LOW_BRIGHT = 0x00
Const MAX7219_MID_BRIGHT = 0x08
Const MAX7219_MAX_BRIGHT = 0xFF

'------------------------------------------------------------
' Initialize communication pins for MAX7219
'------------------------------------------------------------
Function MAX7219_Init() As Byte
    'Configure pins as outputs
    'TRISC.0 = 0
    'TRISC.1 = 0
    'TRISC.2 = 0
	'TRISC.3 = 0
	'TRISC.5 = 0

    ' Configure the MAX7219
    Call MAX7219_Send(MAX7219_SHUTDOWN, 1)       ' Exit shutdown mode
    Call MAX7219_Send(MAX7219_SCAN_LIMIT, 7)     ' Enable all 8 digits
    Call MAX7219_Send(MAX7219_DECODE_MODE, 0)    ' Use no-decoding mode
    Call MAX7219_Send(MAX7219_INTENSITY, 15)     ' Set max. brightness
    Call MAX7219_Send(MAX7219_DISPLAY_TEST, 0)   ' Exit display test mode

End Function

'-------------------------------------------------------------
' Send data to the MAX7219
' Parameters:
'   reg: Target register
'   data: Data value to send
'-------------------------------------------------------------
Function MAX7219_Send(reg As Byte, data As Byte) As Byte
	Call _SPI_StartWrite()

	Call _SPI_Write(reg)
	Call _SPI_Write(data)

	Call _SPI_EndWrite()
End Function

'---------------------------------------------------------
' Clear the MAX7219 display
'---------------------------------------------------------
Function MAX7219_Clear() As Byte
    Dim i As Byte
    For i = 1 To 8
        Call MAX7219_Send(i, 0)
    Next i
End Function

'---------------------------------------------------------
' Light up all segments on all digits
'---------------------------------------------------------
Function MAX7219_Full() As Byte
    Dim i As Byte
    For i = 1 To 8
        Call MAX7219_Send(i, 0xFF)
    Next i
End Function

'---------------------------------------------------------
' Adjust MAX7219 brightness
' Parameters:
'   intensity: Brightness level (0 to 15)
'---------------------------------------------------------
Function MAX7219_SetIntensity(intensity As Byte) As Byte
    If intensity > 15 Then
        intensity = 15
    Endif
    Call MAX7219_Send(MAX7219_INTENSITY, intensity)
End Function

'---------------------------------------------------------
' Send a formatted string to the display
'---------------------------------------------------------
Function MAX7219_DisplayString(_string[16] As String) As Bit
    Dim segment(8) As Byte
    Dim lenString As Byte
    Dim i As Byte
    Dim x As Byte
    x = MAX7219_Digits_NUMBER - 1 ' Digits start from zero.

    lenString = Len(_string) ' Get the actual length of the input string.
    If lenString > (MAX7219_Digits_NUMBER * 2) Then lenString = MAX7219_Digits_NUMBER * 2 ' Limit the string length.

    ' Pad the string with zeros if it's shorter than the allowed length.
    For i = 1 To ((MAX7219_Digits_NUMBER * 2) - lenString)
        _string = "0" + _string
    Next i

    ' Assign segments and handle decimal points.
    For i = (MAX7219_Digits_NUMBER * 2 - 1) To 0 Step -1
        If _string(i) = "." Or _string(i) = ":" Then
            segment(x) = 0x80
            If _string(i-1) <> "." And _string(i-1) <> ":" Then
                i--
                segment(x) = segment(x) Or MAX7219_Digits(MAX7219_GetSegmentIndex(_string(i)))
            Endif
        Else
            segment(x) = MAX7219_Digits(MAX7219_GetSegmentIndex(_string(i)))
        Endif
        x--
        If x > MAX7219_Digits_NUMBER - 1 Then Exit For
    Next i

    ' Send the data to MAX7219
    x = 7
    For i = 1 To 8
        Call MAX7219_Send(i, segment(x)) ' Write mask
        x--
    Next i

End Function

'---------------------------------------------------------------------
' Segment description
'     a6
'    ----
' f1| g0 |b5
'    ----
' e2|    |c4
'    ----
'     d3  .7 (decimal point)
' Segment order: point7/g0/f1/e2/d3/c4/b5/a6
' Segment LED patterns: 0123456789ABCDEF.- OFF
'---------------------------------------------------------------------
Function MAX7219_Digits(index As Byte) As Byte
    Dim mask As Byte
    If index = "-" Then
		index = 16
	Else
		If index = "." Or index = ":" Then
			index = 17
		Else
			If index = " " Then
				index = 18
			Endif
		Endif
	Endif

    mask = LookUp(0b01111110, 0b00110000, 0b01101101, 0b01111001, 0b00110011, 0b01011011, 0b01011111, 0b01110000, 0b01111111, 0b01110011, 0b01110111, 0b00011111, 0b01001110, 0b00111101, 0b01001111, 0b01000111, 0b00000001, 0b10000000, 0b00000000), index
    ReturnValue mask
End Function

'---------------------------------------------------------
' Helper function to get the segment index for a character
'---------------------------------------------------------
Function MAX7219_GetSegmentIndex(char As Byte) As Byte
    If char >= "0" And char <= "9" Then
        ReturnValue char - "0"
    Else
        If char >= "A" And char <= "F" Then
            ReturnValue char - "A" + 10
        Else
            If char = "-" Then
                ReturnValue 16 'Minus
            Else
                If char = " " Then
                    ReturnValue 18 'Space
                Else
                    ReturnValue 17 'Default value in case of unrecognized character
                Endif
            Endif
        Endif
    Endif
End Function
