/* --COPYRIGHT--,BSD
 * Copyright (c) 2014, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
// TODO update this diagram
//*****************************************************************************
//
// HAL_MSP-EXP430FR5969_Sharp96x96.c
//
//*****************************************************************************
//
//! \addtogroup display_api
//! @{
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>

#include "kitronix320x240x16_ssd2119_spi.h"
#include "HAL_MSP_EXP432P401R_KITRONIX320X240_SSD2119_SPI.h"

#include "inc/hw_memmap.h"

#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/pwm.h"







static
void LcdMuxSet(void)
{
    //
    // Enable Peripheral Clocks
    //
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOC );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOE );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOF );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOL );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPION );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOP );

	SysCtlPeripheralEnable( LCD_SPI_PERIPHERAL );
	SysCtlPeripheralEnable( SYSCTL_PERIPH_PWM0 );



    //
	// Configure the LCD_PWN to 5 kHz with a 50% duty cycle & turn it on
    //
    GPIOPinTypePWM( GPIO_PORTF_BASE, GPIO_PIN_1);
	GPIOPinConfigure( GPIO_PF1_M0PWM1 );
    PWMClockSet( PWM0_BASE, PWM_SYSCLK_DIV_16 );

    PWMGenConfigure( PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC );

    // 5 kHz period
    PWMGenPeriodSet( PWM0_BASE, PWM_GEN_0, 1500);

    // Set 50% Duty cycle
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, PWMGenPeriodGet(PWM0_BASE, PWM_GEN_0) / 2);

    // Enable the M0PWM1 output signal
    PWMOutputState( PWM0_BASE, PWM_OUT_1_BIT, true );

    // Enable the PWM generator block.
    PWMGenEnable( PWM0_BASE, PWM_GEN_0 );



    //
    // Configure the GPIO pin muxes for the LCD interface signals
    //

    // LCD_SCS
	GPIOPinTypeGPIOOutput( LCD_SCS_PORT, LCD_SCS_PIN );
	GPIOPinWrite( LCD_SCS_PORT, LCD_SCS_PIN, 0 );

	// LCD_SDC
    GPIOPinTypeGPIOOutput( LCD_SDC_PORT, LCD_SDC_PIN );

    // LCD_SDI is basically SSI2XDAT0
	GPIOPinConfigure( LCD_SDI_PIN_FUNCTION );
	GPIOPinTypeSSI( LCD_SDI_PORT, LCD_SDI_PIN );

    // LCD_SCL is SSI2CLK
	GPIOPinConfigure( LCD_SCL_PIN_FUNCTION );
	GPIOPinTypeSSI( LCD_SCL_PORT, LCD_SCL_PIN );

    // LCD_RESET
	GPIOPinTypeGPIOOutput( LCD_RESET_PORT, LCD_RESET_PIN );
	GPIOPinWrite( LCD_RESET_PORT, LCD_RESET_PIN, LCD_RESET_PIN );

}




//*****************************************************************************
//
//! Initializes the display driver.
//!
//! This function initializes the Sharp96x96 display. This function
//! configures the GPIO pins used to control the LCD display when the basic
//! GPIO interface is in use. On exit, the LCD has been reset and is ready to
//! receive command and data writes.
//!
//! \return None.
//
//*****************************************************************************
void HAL_LCD_initLCD(void)
{

	LcdMuxSet();


 	SSIConfigSetExpClk( LCD_SPI_PORT,
						120000000,
						SSI_FRF_MOTO_MODE_0,
						SSI_MODE_MASTER,
						8000000,
						8 );

    SSIIntClear( LCD_SPI_PORT, SSI_RXTO | SSI_RXOR );
    SSIEnable( LCD_SPI_PORT );



    // Set the LCD Backlight high to enable
    //
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);

    // Set the LCD control pins to their default values.
    //
    GPIOPinWrite( LCD_SDC_PORT, LCD_SDC_PIN, LCD_SDC_PIN );
    GPIOPinWrite( LCD_SCS_PORT, LCD_SCS_PIN, 0 );

    // Delay for 1 ms
    HAL_LCD_delay(1);

    // Deassert the LCD reset signal.
    GPIOPinWrite( LCD_RESET_PORT, LCD_RESET_PIN, LCD_RESET_PIN );

    // Delay for 1ms while the LCD comes out of reset.
    HAL_LCD_delay(1);

}


//*****************************************************************************
//
// Writes a command to the UC1701.  This function implements the basic SPI
// interface to the LCD display.
//
//*****************************************************************************
void HAL_LCD_writeCommand(uint8_t command)
{
    // Wait for any SPI transmission to complete before setting the LCD_SDC signal.
    //
    while(SSIBusy( LCD_SPI_PORT ));

    // Set the LCD_SDC signal low, indicating that following writes are commands.
    //
    GPIOPinWrite(LCD_SDC_PORT, LCD_SDC_PIN, 0);

    // Transmit the command.
    //
    SSIDataPut( LCD_SPI_PORT, command );

    // Wait for the SPI transmission to complete before setting the LCD_SDC signal.
    //
    while(SSIBusy( LCD_SPI_PORT ));

    // Set the LCD_SDC signal high, indicating that following writes are data.
    //
    GPIOPinWrite( LCD_SDC_PORT, LCD_SDC_PIN, LCD_SDC_PIN );

}


//*****************************************************************************
//
// Writes a data word to the UC1701.  This function implements the basic SPI
// interface to the LCD display.
//
//*****************************************************************************
void HAL_LCD_writeData(uint16_t data)
{
    uint8_t ui8Data;

    // Extract the high byte to transmit.
    //
    ui8Data = (uint8_t)(data >> 8);

    // Wait for the transmit buffer to become empty.
    //
    while(SSIBusy( LCD_SPI_PORT ));

    // Transmit the high byte.
    //
    SSIDataPut( LCD_SPI_PORT, ui8Data );

    // Extract the low byte to transmit.
    //
    ui8Data = (uint8_t)(data & 0xff);

    // Wait for the transmit buffer to become empty.
    //
    while(SSIBusy( LCD_SPI_PORT ));

    // Transmit the low byte.
    //
    SSIDataPut( LCD_SPI_PORT, ui8Data );

}

//*****************************************************************************
//
// Clears CS line
//
// This macro allows to clear the Chip Select (CS) line
//
// \return None
//
//*****************************************************************************

void HAL_LCD_selectLCD()
{
    // Wait for any SPI transmission to complete before setting the LCD_SCS signal.
    //
    while(SSIBusy( LCD_SPI_PORT ));

    GPIOPinWrite( LCD_SCS_PORT, LCD_SCS_PIN, 0 );
}

//*****************************************************************************
//
// Set CS line
//
// This macro allows to set the Chip Select (CS) line
//
// \return None
//
//*****************************************************************************

void HAL_LCD_deselectLCD()
{

    // Wait for any SPI transmission to complete before setting the LCD_SCS signal.
    //
    while(SSIBusy( LCD_SPI_PORT ));

	GPIOPinWrite( LCD_SCS_PORT, LCD_SCS_PIN, LCD_SCS_PIN );
}


//*****************************************************************************
//
// Generates delay of
//
// \param cycles number of cycles to delay
//
// \return None
//
//*****************************************************************************
void HAL_LCD_delay(uint16_t msec)
{
    uint32_t i=0;
    uint32_t time=(msec/1000)*(SYSTEM_CLOCK_SPEED/15);

    for(i=0;i<time;i++);

}



//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
