/**
* \file swif.c
*
* \brief swif APIs.
*
* This file contains the APIs for swif.
*/
/*
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
*/
/*
* 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.
*
*/
#include "..\Common\device.h"
#include "..\Common\types.h" // Basic Type declarations
#include "..\Common\hal_UCS.h"
#include "..\Common\hal_pmm.h"
#include "usb2any.h"
#include "..\wavevision\_include\fpga.h"
unsigned int DUTY_CYCLE_25,DUTY_CYCLE_50,DUTY_CYCLE_75,DUTY_CYCLE_35,DUTY_CYCLE_65;
#define SWIF_INPUT 0x10
#define SWIF_OUTPUT 0x08
//definition for reading a register
#define RD_TIME_UINT 125000
#define RD_TIME_UINT_25 781
#define RD_TIME_UINT_35 1093
#define RD_TIME_UINT_50 1562
#define RD_TIME_UINT_65 2031
#define RD_TIME_UINT_75 2381
static unsigned int cur_clk_s;
//definition for sending a symbol to lmp91300
#define SET_TX_HIGH 0xF7
#define SET_TX_LOW 0x08
#define ZERO_SYM 0
#define ONE_SYM 1
#define IDLE_SYM 2
//------------------------------------------------------------------------------
// reset_swif_for_spi
//
// DESCRIPTION:
// initialize the pins for SPI interface
//
//------------------------------------------------------------------------------
void reset_swif_for_spi(void)
{
P2SEL &= ~0x08; // p2.3 rx
P2SEL &= ~0x10; // p2.4 tx
P2DIR |= 0x18; // make it out, in spi mode, these two pin muts be low
P2OUT &= ~0x18; // Make Low
}
//------------------------------------------------------------------------------
// init_swif_set
//
// DESCRIPTION:
// initialize the pins for SWIF interface
// unsigned char swif_clk: SWIF transfer speed(k unit)
//------------------------------------------------------------------------------
void init_swif_set(unsigned char swif_clk)
{
unsigned int one_time_uint_cycles;
P2SEL &= ~0x08; // p2.3 tx
P2SEL &= ~0x10; // p2.4 rx
P2DIR &= ~0x10; // make it input
P2DIR |= 0x08; // make it output
P2OUT &= ~0x08; // Make Low
one_time_uint_cycles = MASTER_CLOCK_KHZ/swif_clk;
DUTY_CYCLE_50 = one_time_uint_cycles >>1;
DUTY_CYCLE_25 = DUTY_CYCLE_50>>1;
DUTY_CYCLE_75 = DUTY_CYCLE_50 + DUTY_CYCLE_25 ;
}
//------------------------------------------------------------------------------
// delay_cycles
//
// DESCRIPTION:
// delay cpu cycles.
//------------------------------------------------------------------------------
void delay_cycles(unsigned int delay_cycles)
{
unsigned char count[4];
unsigned int cur_clk;
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 10; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
//RTCNT3 = 0;
//RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
do {
cur_clk = 0;
cur_clk = RTCNT2;
cur_clk <<=8;
cur_clk |= RTCNT1;
}while (cur_clk < delay_cycles );
}
//------------------------------------------------------------------------------
// void SWIFSendSymbol(uint8_t sym)
//
// DESCRIPTION:
// Send symbol "sym" to lmp91300 on the SWIF TX pin.
//------------------------------------------------------------------------------
void SWIF_send_symbol(uint8_t sym)
{
P2OUT &= SET_TX_HIGH;
switch (sym) {
case ZERO_SYM:
{
delay_cycles(DUTY_CYCLE_25); // high period for symbol 0
break;
}
case ONE_SYM:
{
delay_cycles(DUTY_CYCLE_75); // high period for symbol 1
break;
}
case IDLE_SYM:
{
delay_cycles(DUTY_CYCLE_50); // high period for symbol idle
break;
}
default:
{
delay_cycles(DUTY_CYCLE_50); // all low period
break;
}
}
// P2OUT &= SET_TX_LOW; // assert PRI_TX_EN_N
P2OUT |= SET_TX_LOW;
switch (sym) {
case ZERO_SYM:
{
delay_cycles(DUTY_CYCLE_75); // low period for symbol 0
break;
}
case ONE_SYM:
{
delay_cycles(DUTY_CYCLE_25); // low period for symbol 1
break;
}
case IDLE_SYM:
{
delay_cycles(DUTY_CYCLE_50); // low period for idle symbol
break;
}
default:
{
delay_cycles(DUTY_CYCLE_50); // all low period
break;
}
}
}
//------------------------------------------------------------------------------
// void SWIF_write_byte
//
// DESCRIPTION:
// Send a byte to lmp91300 by swif interface
// unsigned char data: the data written to lmp91300 via swif
//------------------------------------------------------------------------------
void SWIF_write_byte(unsigned char data)
{
int i;
for ( i=7; i>=0; i--) {
//output MSB first
SWIF_send_symbol((data>>i) & 1 );
}
}
//------------------------------------------------------------------------------
// void SWIF_get_idle
//
// DESCRIPTION:
// wait for a idle coming and measure a idle time unit
// return: true, if the symbol is idle
//------------------------------------------------------------------------------
unsigned char SWIF_get_idle()
{
unsigned int cur_clk_d, cur_clk_e;
unsigned int one_time_uint_cycles;
do {
{//wait for input become low
cur_clk_d = RTCNT2;
cur_clk_d <<=8;
cur_clk_d |=RTCNT1;
}
if ((cur_clk_d - cur_clk_s) > RD_TIME_UINT) //8kbit, 1 time unit is 3125 (125* 25)
return 0;
if ((P2IN & SWIF_INPUT)==0x10)
break;
}while (1);
do {
{//wait for input become low
cur_clk_e = RTCNT2;
cur_clk_e <<=8;
cur_clk_e |=RTCNT1;
}
if ((cur_clk_e - cur_clk_d) > RD_TIME_UINT) //8kbit, 1 time unit is 3125 (125* 25)
return 0;
//wait for high
if ((P2IN & SWIF_INPUT)==0x0)
break;
}while (1);
one_time_uint_cycles = cur_clk_e - cur_clk_s-5 ;
DUTY_CYCLE_50 = one_time_uint_cycles >>1;
DUTY_CYCLE_25 = DUTY_CYCLE_50>>1;
DUTY_CYCLE_75 = DUTY_CYCLE_50 + DUTY_CYCLE_25 ;
DUTY_CYCLE_35 = DUTY_CYCLE_25 + (DUTY_CYCLE_25>>1);//adjust 150 clk.
DUTY_CYCLE_65 = DUTY_CYCLE_50 + (DUTY_CYCLE_25>>1);
//keep the current change point
if (((cur_clk_d- cur_clk_s) > DUTY_CYCLE_35 ) && ((cur_clk_d- cur_clk_s) < DUTY_CYCLE_65) ) {
cur_clk_s = cur_clk_e;
return 1;
}
return 0;
}
//------------------------------------------------------------------------------
// void SWIF_get_sym
//
// DESCRIPTION:
// read a sym
// return : a sym
//------------------------------------------------------------------------------
unsigned char SWIF_get_sym()
{
unsigned char one_sym = 0xFF;
unsigned int cur_clk_d, cur_clk_e;
do {
{//wait for input become low
cur_clk_d = RTCNT2;
cur_clk_d <<=8;
cur_clk_d |=RTCNT1;
}
if ((cur_clk_d - cur_clk_s) > RD_TIME_UINT) //8kbit, 1 time unit is 3125 (125* 25)
return 0xFF;
//wait for low
if ((P2IN & SWIF_INPUT)==0x10)
break;
}while (1);
do {
{//wait for input become high
cur_clk_e = RTCNT2;
cur_clk_e <<=8;
cur_clk_e |=RTCNT1;
}
if ((cur_clk_e - cur_clk_d) > RD_TIME_UINT) { //8kbit, 1 time unit is 3125 (125* 25)
return 0XFF;
}
//wait for high
if ((P2IN & SWIF_INPUT)==0x0)
break;
}while (1);
if (((cur_clk_d- cur_clk_s) < DUTY_CYCLE_35 ) && ((cur_clk_e- cur_clk_d) > DUTY_CYCLE_65) )
one_sym = ZERO_SYM;
else one_sym = ONE_SYM;
//keep the current change point
cur_clk_s = cur_clk_e;
return one_sym;
}
//------------------------------------------------------------------------------
// void SWIF_read_reg
//
// DESCRIPTION:
// read a register from lmp91300 by swif interface
// unsigned char cmd: the register address
// unsigned char swif_capture_data[2]: the buffer to store the received data
// return: none
//------------------------------------------------------------------------------
void SWIF_read_reg(unsigned char cmd,unsigned char swif_capture_data[2])
{
unsigned char data;
unsigned int cur_clk;
int i;
//send read command
SWIF_send_symbol(IDLE_SYM);
SWIF_write_byte(cmd);
SWIF_send_symbol(IDLE_SYM);
//end transfer
P2OUT &= SET_TX_HIGH;
P2OUT &= SET_TX_HIGH;
P2OUT &= SET_TX_HIGH;
P2OUT |= SET_TX_LOW;
//start time clk
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 0; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
RTCNT3 = 0;
RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
//wait for getting the idle start point.
do {
if ((P2IN & SWIF_INPUT)==0x10) {//wait for input become high
cur_clk = RTCNT2;
cur_clk <<=8;
cur_clk |=RTCNT1;
} else {
//reset the clk count
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 0; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
RTCNT3 = 0;
RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
//initialize start point clk
cur_clk_s = 0;
break;
}
}while (1);
if (SWIF_get_idle() ==0) { //for reading, the first symbol must be idle
return ;
}
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 0; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
RTCNT3 = 0;
RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
//initialize start point clk
cur_clk_s = 0;
data = 0;
for ( i=7; i>=0; i--) {
//output MSB first
//reset the clk count
data |= (SWIF_get_sym()<< i);
}
swif_capture_data[0] = data;
//don't read the second byte because some register only outputs a byte
#if 0
data =0;
for ( i=7; i>=0; i--) {
//output MSB first
data |= (SWIF_get_sym()<< i);
}
swif_capture_data[1] = data;
#endif
//wait for the read done (8*8*125*25), one bit:125us
__delay_cycles(4*125*25);
}
//------------------------------------------------------------------------------
// void SWIF_read_data
//
// DESCRIPTION:
// read data from lmp91300 by swif interface, this is for stream mode
// unsigned char swif_capture_data[2]: the buffer to store the received data
// return: none
//------------------------------------------------------------------------------
void SWIF_read_data(unsigned char swif_capture_data[2])
{
unsigned char data;
unsigned char cmd;
unsigned int cur_clk;
int i;
// init_swif_set(ctrl_data[FPGA_SPI_CFG]);
init_swif_set(7);
cmd =0xFA;//read address 0x7a|readflag
//send read command
SWIF_send_symbol(IDLE_SYM);
SWIF_write_byte(cmd);
SWIF_send_symbol(IDLE_SYM);
//end transfer
P2OUT &= SET_TX_HIGH;
P2OUT &= SET_TX_HIGH;
P2OUT &= SET_TX_HIGH;
P2OUT |= SET_TX_LOW;
//start time clk
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 0; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
RTCNT3 = 0;
RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
//wait for getting the idle start point.
do {
if ((P2IN & SWIF_INPUT)==0x10) {//wait for input become high
cur_clk = RTCNT2;
cur_clk <<=8;
cur_clk |=RTCNT1;
} else {
//reset the clk count
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 0; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
RTCNT3 = 0;
RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
//initialize start point clk
cur_clk_s = 0;
break;
}
}while (1);
if (SWIF_get_idle() ==0) { //for reading, the first symbol must be idle
return ;
}
RTCCTL01 = 0;
RTCCTL01 |= RTCHOLD; // Make sure RTC_A is stopped
RTCNT1 = 0; // Load RTC_A (4 bytes to make a 32-bit)
RTCNT2 = 0;
RTCNT3 = 0;
RTCNT4 = 0;
RTCCTL01 = RTCSSEL_1 + RTCTEV_3; // CTR_A: Counter Mode, Enable Interrupt, MCLK Input, 32-bit overflow, Start counter
//initialize start point clk
cur_clk_s = 0;
data = 0;
for ( i=7; i>=0; i--) {
data |= (SWIF_get_sym()<< i);
}
swif_capture_data[0] = data;
data =0;
for ( i=7; i>=0; i--) {
//output MSB first
data |= (SWIF_get_sym()<< i);
}
swif_capture_data[1] = data;
}
//------------------------------------------------------------------------------
// void SWIF_write_reg
//
// DESCRIPTION:
// write the value to a register by swif interface
// unsigned char cmd: the register address
// unsigned char data[2]: the value to write to register
// unsigned char data_width: 0 8 bits, 1: 16 bits
// return: none
//------------------------------------------------------------------------------
void SWIF_write_reg(unsigned char cmd, unsigned char data[2], unsigned char data_width)
{
//send idle
SWIF_send_symbol(IDLE_SYM);
//write write command
SWIF_write_byte(cmd);
//write data
SWIF_write_byte(data[0]);
if (data_width)//if it is 16 bit data
SWIF_write_byte(data[1]);
//send idle
SWIF_send_symbol(IDLE_SYM);
P2OUT &= SET_TX_HIGH;
P2OUT &= SET_TX_HIGH;
P2OUT &= SET_TX_HIGH;
P2OUT |= SET_TX_LOW;
}
//------------------------------------------------------------------------------
// unsigned char SWIF_Transfer
//
// DESCRIPTION:
// perform SWIF transfer
// unsigned char *ctrl_data: data package
// return: none
//------------------------------------------------------------------------------
unsigned char SWIF_Transfer(unsigned char *ctrl_data)
{
unsigned char swif_capture_cmd;
unsigned char swif_capture_data[2];
unsigned char rw_flag;
unsigned char data_width;
init_swif_set(ctrl_data[FPGA_SPI_CFG]);
// init_swif_set(7);
//get address
swif_capture_cmd = ctrl_data[FPGA_SPI_ADDR_H];
//get read/write flag
rw_flag = (ctrl_data[FPGA_SPI_CMD]>>1)&1;
swif_capture_cmd |= ((( ctrl_data[FPGA_SPI_CMD]>>1)&1 ) <<7);
data_width = (ctrl_data[FPGA_SPI_CMD]>>3) & 3;
//get data
swif_capture_data[0] = ctrl_data[FPGA_SPI_DATA_H];//if the data is 16 bits, it hold the MSB byte, if it is 8bit, it holds LSB
swif_capture_data[1] = ctrl_data[FPGA_SPI_DATA_L];//if the data is 16 bits, it hold the LSB byte,
if (rw_flag) {// rw_flag ==1: read)
SWIF_read_reg(swif_capture_cmd,swif_capture_data);
ctrl_data[FPGA_SPI_DATA_H] = swif_capture_data[0];//if the data is 16 bits, it hold the MSB byte, if it is 8bit, it holds LSB
ctrl_data[FPGA_SPI_DATA_L] = swif_capture_data[1];//if the data is 16 bits, it hold the LSB byte,
} else {
SWIF_write_reg(swif_capture_cmd, swif_capture_data, data_width);
}
return 0;
}
//-------------------------------------------------------------------------------------------