//*****************************************************************************
//
// SPIdriver.c - Driver for the Peripheral Device Controller (SPI) on the Stellaris
//         development board.
//
// Copyright (c) 2005-2008 Luminary Micro, Inc.  All rights reserved.
// 
// Software License Agreement
// 
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
// 
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  You may not combine
// this software with "viral" open-source software in order to form a larger
// program.  Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
// 
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 3416 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup dk_lm3s817_api
//! @{
//
//*****************************************************************************

#include <hw_memmap.h>
#include <hw_types.h>
#include <debug.h>
#include <gpio.h>
#include <ssi.h>
#include <sysctl.h>
#include <SPIdriver.h>

// Deklarace funkci
void SPI_InitCSPort();

/******************************************************************************/

//SPI_Init / inicializace SPI modulu-------------------------------------------
void SPI_Init(void)
{
    unsigned long ulIdx;

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);                                 // Povoleni periferii k rizeni SPI
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);


    GPIOPinTypeSSI(GPIO_PORTA_BASE, SSI_CLK | SSI_TX | SSI_RX);                 // nastaveni pinu pro SCK, MISO, MOSI
    //GPIOPadConfigSet(GPIO_PORTA_BASE, SSI_CLK, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU);

    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_1, SSI_MODE_MASTER, 25000000, 16);  //Nastaveni komunikace SPI (prenos 16ti bitu pri 25Mb/s, Master mod
    SSIEnable(SSI0_BASE);                                                       //povoleni modulu
    
    while(SSIDataGetNonBlocking(SSI0_BASE, &ulIdx));                            // Precteni dat z SSI portu
    
    SPI_InitCSPort();                                                           // Inicializace pinu pro ChipSelect (signaly k demultiplexeru)

}

//SPI_InitCSPort / nastaveni pinu pro rizeni ChipSelect------------------------
void SPI_InitCSPort()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);                                // CS - A/D prevodniky
    GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, SPI_CS_PINS);
    
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);                                // CS - D/A prevodnik
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0);
    
    SPI_SetCS(SPI_CS_OFF);                                                      //Vypnuti CS
}

// Nastaveni ChipSelect signalu / podle parametru------------------------------
void SPI_SetCS(char value)
{
  
  if(value==SPI_CS_OUTPUT)                                                      //Nastaveni CS pro D/A prevodnik na portu B
      GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, 0);
  else if (value==SPI_CS_OFF)                                                   //Vsechny signaly do vychoziho stavu
    {
      GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_PIN_0);                    //CS pro D/A prevodnik do vychoziho stavu
      GPIOPinWrite(GPIO_PORTC_BASE, SPI_CS_PINS, 0);                            //CS pro A/D prevodnik do vychoziho stavu
    }
  else                                                                          //Pokud nechci komunikovat s D/A ani vypnout vsechny CS
      GPIOPinWrite(GPIO_PORTC_BASE, SPI_CS_PINS, value<<4);                     //Nastaveni CS pro A/D prevodnik na portu C
}

//*****************************************************************************
//
//! Read a SPI register.
//!
//! \param ucAddr specifies the SPI register to read.
//!
//! This function will perform the SSI transfers required to read a register in
//! the SPI on the Stellaris development board.
//!
//! This function is contained in <tt>SPIdriver.c</tt>, with <tt>SPIdriver.h</tt>
//! containing the API definition for use by applications.
//!
//! \return Returns the value read from the SPI.
//
//*****************************************************************************
unsigned char SPI_Read(unsigned char ucAddr)
{
    unsigned long ulTemp;

    // Send address and read command.
    SSIDataPut(SSI0_BASE, (ucAddr & 0x0F) | SPI_RD);

    // Dummy write to force read.
    SSIDataPut(SSI0_BASE, 0x00);

    // Flush data read during address write.
    SSIDataGet(SSI0_BASE, &ulTemp);

    // If the LCD control register or RAM is being read, then an additional
    // byte needs to be transferred.
//    if((ucAddr == SPI_LCD_CSR) || (ucAddr == SPI_LCD_RAM))
    {
        // Dummy write to force read.
        SSIDataPut(SSI0_BASE, 0x00);

        // Flush read data.
        SSIDataGet(SSI0_BASE, &ulTemp);
    }

    // Read valid data.
    SSIDataGet(SSI0_BASE, &ulTemp);

    // Return the data read.
    return(ulTemp & 0xFF);
}

//*****************************************************************************
//
//! Read a SPI register.
//!
//! \param ucAddr specifies the SPI register to read.
//!
//! This function will perform the SSI transfers required to read a register in
//! the SPI on the Stellaris development board.
//!
//! This function is contained in <tt>SPIdriver.c</tt>, with <tt>SPIdriver.h</tt>
//! containing the API definition for use by applications.
//!
//! \return Returns the value read from the SPI.
//
//*****************************************************************************
unsigned short SPI_Read16b()
{
    unsigned long result;

    // Dummy write to force read.
    SSIDataPut(SSI0_BASE, 0x00);

    // Flush data read during address write.
    SSIDataGet(SSI0_BASE, &result);

    // Return the data read.
    return((unsigned short)result);
}

//*****************************************************************************
//
//! Write a SPI register.
//!
//! \param ucAddr specifies the SPI register to write.
//! \param ucData specifies the data to write.
//!
//! This function will perform the SSI transfers required to write a register
//! in the SPI on the Stellaris development board.
//!
//! This function is contained in <tt>SPIdriver.c</tt>, with <tt>SPIdriver.h</tt>
//! containing the API definition for use by applications.
//!
//! \return None.
//
//*****************************************************************************
void SPI_Write32b(unsigned char command, unsigned char address, unsigned short data)
{
    unsigned long ulTemp;

    // Send command, address and first 4b of data
    SSIDataPut(SSI0_BASE, (command << 8) | ((address & 0x0F)<<4) | (data >> 12));

    // Write the rest of data.
    SSIDataPut(SSI0_BASE, data << 4);   

    // Flush data read during address write.
    SSIDataGet(SSI0_BASE, &ulTemp);

    // Flush data read during data write.
    SSIDataGet(SSI0_BASE, &ulTemp);
}

void SPI_Write16b(unsigned char Shdn, unsigned char address, unsigned short data)
{
    unsigned long ulTemp;

    // Send config.bits and 12b data
    ulTemp=(address<<15) | (0x01 <<13) | ((Shdn & 0x01)<<12) | (data & 0x0fff);   //second part is gain of DAC = 1x
    SSIDataPut(SSI0_BASE, ulTemp);

    // Flush data read during address write.
    SSIDataGet(SSI0_BASE, &ulTemp);
    
}    
    

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