' *****************************************************************************
' File: SPI_Lib.bas
' Description: Configuration of the MSSP module in SPI mode for the PIC18F26K22
' Author: By COS (dogflu66@yahoo.es)
' Date: 2024/12/17, 2024/06/02
' Version: 1.0, Pic18 Basic Oshonsoft v5.91
' *****************************************************************************
' *****************************************************************************
' Function: SPI_Init()
' Description: Configures the MSSP1 module in SPI master mode (for now).
' Arguments: mode (byte) - SPI operation mode (0 to 3)
'             speed (byte) - SPI speed (bits 3-0 of SSPCON1)
' *****************************************************************************
' Define MSSP module pins in SPI mode
Symbol _SPI_RST = LATC.0    ' RST RESET pin
Symbol _SPI_DC  = LATC.1    ' DC (SS) Data/Command pin
Symbol _SPI_CS  = LATC.2    ' (CS) CS Chip Select pin
Symbol _SPI_SCK = LATC.3    ' (CLK) SCK as output
Symbol _SPI_SDI = PORTC.4   ' SDI as input -> SDO
Symbol _SPI_SDO = LATC.5    ' (DIN) SDO as output -> SDI

Symbol _SPI_RST_IO = TRISC.0    ' RST RESET pin
Symbol _SPI_DC_IO  = TRISC.1    ' DC (SS) Data/Command pin
Symbol _SPI_CS_IO  = TRISC.2    ' (CS) CS Chip Select pin
Symbol _SPI_SCK_IO = TRISC.3    ' (CLK) SCK as output
Symbol _SPI_SDI_IO = TRISC.4    ' SDI as input -> SDO
Symbol _SPI_SDO_IO = TRISC.5    ' (DIN) SDO as output -> SDI

Const _SPI_USE_RST = 0 '1 Use Reset pin
Const _SPI_USE_DC  = 0 '1 Use DC (SS) pin
Const _SPI_USE_CS  = 1 '1 Use CS pin

' Operation mode:
Const _SPI_MODE0 = 0 'Clock low level (CKP)/(CKE) high to low (Host or client mode) (SSPxSTAT).
Const _SPI_MODE1 = 1 'Clock low level/low to high
Const _SPI_MODE2 = 2 'Clock High level/High to low
Const _SPI_MODE3 = 3 'Clock High Level/low to high
' Speed | bIT SMP | SSPxCONx
Const _SPI_MASTER_SPEED0 = 0 'Master Clock Fosc/4 (SSPxCONx)
Const _SPI_MASTER_SPEED1 = 1 'Master Clock Fosc/16
Const _SPI_MASTER_SPEED2 = 2 'Master Clock Fosc/64
Const _SPI_MASTER_SPEED3 = 3 'Master Clock TMR2 output/2

' Definition of constants for the SMP bit
Const _SMP_MIDDLE = %00000000 ' Data sampling in the middle of the output time (SMP = 0), for slave always zero.
Const _SMP_END    = %10000000 ' Data sampling at the end of the output time (SMP = 1)
' Enable module
Const _SPI_ENABLE  = %00100000  ' SSPxCONx.SSPxEN
Const _SPI_DISABLE = %00000000 ' SSPxCONx.SSPxEN
'Example: Call _SPI1_Init(_SPI_MODE0, _SPI_MASTER_SPEED1 | _SPI_ENABLE) 'CLK 4Mhz (64Mhz)
Function _SPI1_Init(mode As Byte, speed As Byte) As Byte
    ' Configure SPI pins
	Low _SPI_RST_IO  ' RESET as output
    Low _SPI_DC_IO   ' DC (SS) data/Command pin As Output
    Low _SPI_CS_IO   ' (CS) CS Chip Select pin
    Low _SPI_SCK_IO  ' (CLK) SCK as output
    High _SPI_SDI_IO ' SDI as input
    Low _SPI_SDO_IO  ' (DIN) SDO as output

	' Estado inicial de los pin
	If _SPI_USE_RST Then High _SPI_RST
	If _SPI_USE_DC Then High _SPI_DC
    If _SPI_USE_CS Then High _SPI_CS

    ' Configure SPI operation mode
    Select Case mode
        Case 0
            SSPCON1.4 = 0 ' CKP = 0
            SSPSTAT.6 = 1 ' CKE = 1
        Case 1
            SSPCON1.4 = 0 ' CKP = 0
            SSPSTAT.6 = 0 ' CKE = 0
        Case 2
            SSPCON1.4 = 1 ' CKP = 1
            SSPSTAT.6 = 1 ' CKE = 1
        Case 3
            SSPCON1.4 = 1 ' CKP = 1
            SSPSTAT.6 = 0 ' CKE = 0
    EndSelect

    SSPCON1 = SSPCON1 | speed

End Function
' *****************************************************************************
' Function: _SPI_Write
' Description: Sends a byte of data via the SPI bus
' Arguments: dato (byte) - Data to send
' *****************************************************************************
Function _SPI_Write(data As Byte) As Byte
	Dim counter As Byte
	counter = 100

    SSP1BUF = data ' Load the data in the transmission buffer
    While SSPSTAT.0 == 0 && counter > 0 ' Wait until the transmission is complete
		--counter
    Wend

End Function
' *****************************************************************************
' Function: _SPI_Read
' Description: Receives a byte of data via the SPI bus
' Returns: Byte - Received data
' *****************************************************************************
Function _SPI_Read() As Byte
	Dim counter As Byte
	counter = 100
    'If _SPI_USE_DC Then Low _SPI_DC
    SSPBUF = 0x00 ' Send a null byte to generate the clock
    While SSPSTAT.0 == 0 && counter > 0 ' Wait until the reception is complete
		--counter
    Wend
    'If _SPI_USE_DC Then High _SPI_DC
    ReturnValue SSP1BUF ' Return the received data
End Function

' *****************************************************************************
' Function: _SPI_WriteRead
' Description: Sends and receives a byte of data via the SPI bus
' Arguments: dato (byte) - Data to send
' Returns: Byte - Received data
' *****************************************************************************
Function _SPI_WriteRead(dato As Byte) As Byte
	Dim counter As Byte
	counter = 100
    'If _SPI_USE_DC Then Low _SPI_DC
    SSPBUF = dato ' Load the data in the transmission buffer
    While SSPSTAT.0 == 0 && counter > 0 ' Wait until the transmission/reception is complete
		--counter
    Wend
    'If _SPI_USE_DC Then High _SPI_DC
    ReturnValue SSP1BUF ' Return the received data
End Function

' ****************************************************************************
' Call before issuing command(s) or data to display. Performs
' chip-Select (if required). Required
' for all display types; Not an SPI-specific function.
' ******************************************************************************
Function _SPI_StartWrite() As Byte
	If _SPI_USE_CS Then Low _SPI_CS
    If _SPI_USE_DC Then High _SPI_DC
End Function
Function _SPI_StartXFER() As Byte
	If _SPI_USE_CS Then Low _SPI_CS
    If _SPI_USE_DC Then Low _SPI_DC
End Function
' ******************************************************************************
' Call after issuing command(s) or data to display. Performs
' chip-deselect (if required). Required
' for all display types; Not an SPI-specific function.
' ******************************************************************************
Function _SPI_EndWrite() As Byte
	If _SPI_USE_DC Then High _SPI_DC
    If _SPI_USE_CS Then High _SPI_CS
End Function
