Laboratory‎ > ‎

SPI

Serial Peripheral Interface is one of synchronous serial data link standards widely used, contrasted by having 4-wire serial buses.

SPI protocol implementation for communication between Qualcomm MSM7227 and a camera module via FPGA(SiliconBlue ICE65L), as part of RealDica project at LG Electronics Mobile Handset R&D Centre in 2009.


Phone side implementation

Provisional SPI implementation on the phone side(MSM 7200A). For mode controlling communication use with a camera module through FPGA. Written in C

spi.h

#include <stdio.h>
#include <string.h>
#include "../../build/cust/customer.h"
#include "../bio/bio_mbGC970.h"
#include "../bio/Bio.h"
#include "clk.h"
#include "clkrtc.h"
#include "gpio_int.h"
#include "../../app/pal/phonepal/include/PalDef_OemCommon.h"
 
 
extern unsigned char  packet_set[6];
extern int  counter;
extern int  phData_read;
extern unsigned char data2send[4];
extern unsigned char cmd2send;
extern int phone_init_trans;
 
//SPI cmd
#define cmd_POFF_P2C 0x82
#define cmd_PON  0x84
#define cmd_REQSTATUS 0x72
#define cmd_POFF_C2P 0x12
#define cmd_SENDBT  0x14
#define cmd_SENDMMS 0x16
#define cmd_TIME   0x02
#define cmd_LANG   0x04
#define cmd_CAMSTATUS 0x06
#define cmd_READY 0x22
 
#define false 0
#define true 1
 
#define GPIO_LOW_VALUE 0
#define GPIO_HIGH_VALUE 1
 
void SPI_configure_onboot();
 
void SPI_ISR();
 
void SPI_temp(byte arrString[]);
 
unsigned char spi_read_byte();
 
void spi_write_byte(unsigned char out_packet);
 
unsigned char spi_rw_byte(unsigned char byte2send);
 
unsigned char spi_calculate_checksum(byte data_stream[]);
 
//global variables
typedef unsigned int CAMERA_STATUS;
typedef unsigned char U8 ;
typedef U8 bool ;
 
//function definition.
void SPI_ISR();
dword convert_endian(dword x);
boolean command(unsigned char cmd);
void SPI_Rx_ISR();
void SPI_CmdRead(byte* cmd, byte* checkcode);
void SPI_CmdWrite(const byte cmd, byte* checkcode);
void SPI_DataRead(byte* arrData, byte* checkcode);
void SPI_DataWrite(const byte* arrData, byte* checkcode);
void SPI_CmdDataRead(byte* arrPacket);
void SPI_CmdDataWrite(const byte* arrPacket);
byte spi_read_byte();
void spi_write_byte(unsigned char out_packet);
byte spi_rw_byte(unsigned char byte2send);
 
typedef enum
{
	SPI_DATA_INTEGER,
	SPI_DATA_STRING,
} DataType;
 
typedef enum 
{
	cmdListAlarm = 0x89,
	cmdListSchedule = 0x8B,
	cmdListBTFileAccept =0x8D,
	cmdListTime = 0x92,
	cmdListLanguage = 0x94,
	cmdListCamStatusNotify = 0x96,
 
	cmdListPowerOffSigToPhone = 0x02,
	cmdListSendViaBT = 0x05,
	cmdListSendViaMMS = 0x07,	
	cmdListCamStatusSend=0x08,
	//more to do
}cmdList;
 
typedef struct
{
	cmdList cmd;
	DataType dataType;
	void* pData;
	unsigned int nSize;
} PacketParsed;
 
typedef struct
{
	DataType dataType;
	void* pData;
	unsigned int nSize;
}OnlyDataPacket;
 
typedef enum
{
	A	
} SPI_Req_Command;
 
 
typedef enum
{
	SPI_INIT_TIME,
	SPI_INIT_LANGUAGE,
	SPI_INIT_CAM_STATUS
} SPI_Init_Command;
 
//boolean isrFlag = FALSE;
 
typedef struct s_PacketQueue
{
	PacketParsed m_Packet;
	struct s_PacketQueue* m_pNext;
}PacketQueue;
 
extern rex_tcb_type spi_rx_tcb;//PARKJAEWOO 20090709 To add SPI Rx Task
extern rex_tcb_type spi_tx_tcb;//PARKJAEWOO 20090710 To add SPI Tx Task
 
#define SPI_RX_PACKET_SIG 	0x00000001
#define SPI_RX_EVENT_SIG	(SPI_RX_PACKET_SIG)
 
#define SPI_RECEIVE_SIG 0xFF00
 
 
 
OnlyDataPacket *SPI_Rx_ProcessCmd(byte cmd);
void destroyPacket(PacketParsed* pDestroyed);
 
void spi_rx_main(rex_sigs_type sigs);

spi.c

#include "spi.h"
 
unsigned char packet_set[6];
int counter;
int phData_read;
unsigned char data2send[4];
unsigned char cmd2send;
int phone_init_trans;
boolean isrFlag = FALSE;
 
void SPI_configure_onboot()
{
	spi_rx_init();//PARKJAEWOO 20090713
	spi_tx_init();//PARKJAEWOO 20090713
	counter = 0;
	phone_init_trans = false;
 
	BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_HI_V); // SPI CLK high
	clk_busy_wait(100);
	BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V); // reset FPGA state machine
	BIO_OUT(BIO_MSM_INT_PREQ_REG, BIO_MSM_INT_PREQ_M, BIO_MSM_INT_PREQ_HI_V);	
 
	gpio_int_set_detect((gpio_int_type)(SPI_INT),DETECT_EDGE);
	gpio_int_set_handler((gpio_int_type)(SPI_INT), ACTIVE_LOW, SPI_ISR);
 
	gpio_tlmm_config(MSM_INT_PREQ);
	gpio_tlmm_config(MSM_SDI);
	gpio_tlmm_config(MSM_SDO);
	gpio_out(MSM_INT_PREQ, GPIO_HIGH_VALUE);
 
}
 
void SPI_temp(byte arrString[])
{
	unsigned char recv_crc;
	unsigned char incoming_data[4];
 
	BIO_OUT(BIO_MSM_INT_PREQ_REG, BIO_MSM_INT_PREQ_M, BIO_MSM_INT_PREQ_LO_V);
	spi_write_byte(arrString[0]);
	BIO_OUT(BIO_MSM_INT_PREQ_REG, BIO_MSM_INT_PREQ_M, BIO_MSM_INT_PREQ_HI_V);	
	spi_write_byte(arrString[1]);
	spi_write_byte(arrString[2]);
	spi_write_byte(arrString[3]);
	spi_write_byte(arrString[4]);
	recv_crc = spi_rw_byte(arrString[5]);
 
	if( isrFlag == TRUE ) return;
	isrFlag = TRUE;
	counter++;
}
 
void SPI_ISR()
{
 
byte arrPacket[6];
byte send_crc;
 
 
	BIO_OUT(BIO_MSM_INT_PREQ_REG, BIO_MSM_INT_PREQ_M, BIO_MSM_INT_PREQ_LO_V);
	arrPacket[0] = spi_read_byte();
	BIO_OUT(BIO_MSM_INT_PREQ_REG, BIO_MSM_INT_PREQ_M, BIO_MSM_INT_PREQ_HI_V);	
	arrPacket[1] = spi_read_byte();
	arrPacket[2] = spi_read_byte();
	arrPacket[3] = spi_read_byte();
	arrPacket[4] = spi_read_byte();
	send_crc = arrPacket[0] ^ arrPacket[1] ^ arrPacket[2] ^arrPacket[3] ^arrPacket[4];
	arrPacket[5] = spi_rw_byte(send_crc);
 
	SPI_temp(arrPacket);
        return;
 
}
 
#define SPI_CLK  (BIO_INM(BIO_MSM_SCK_REG, BIO_MSM_SCK_M))
#define SPI_TX_HIGH	(BIO_OUT(BIO_MSM_SDO_REG, BIO_MSM_SDO_M, BIO_MSM_SDO_HI_V))
#define SPI_TX_LOW	(BIO_OUT(BIO_MSM_SDO_REG, BIO_MSM_SDO_M, BIO_MSM_SDO_LO_V))
#define SPI_RX  (BIO_INM(BIO_MSM_SDI_REG, BIO_MSM_SDI_M))
 
 
 
 
unsigned char spi_read_byte()
{
	unsigned char recv_packet = 0;
	int i;
	clk_busy_wait(100);
	for (i=0; i < 8; i++)
	{
		BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_LO_V);
		clk_busy_wait(20);
		recv_packet = recv_packet + (BIO_INM(BIO_MSM_SDI_REG, BIO_MSM_SDI_M)/BIO_MSM_SDI_M);
		recv_packet = ((recv_packet >> 1) | (recv_packet << 7));
		BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_HI_V);
		clk_busy_wait(20);
	}
	clk_busy_wait(100);
	return (recv_packet);
}
 
 
void spi_write_byte(unsigned char out_packet)
{
	int i;
	clk_busy_wait(100);
	for (i=0; i < 8; i++)
	{
		if ( (out_packet) & (0x00000001 << i))
		{				
			BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_LO_V);
			clk_busy_wait(5);
			BIO_OUT(BIO_MSM_SDO_REG, BIO_MSM_SDO_M, BIO_MSM_SDO_HI_V);
		}
		else
		{
			BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_LO_V);
			clk_busy_wait(5);
			BIO_OUT(BIO_MSM_SDO_REG, BIO_MSM_SDO_M, BIO_MSM_SDO_LO_V);
		}
		clk_busy_wait(15);
		BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_HI_V);
		clk_busy_wait(20);
	}
	clk_busy_wait(100);
}
 
 
unsigned char spi_rw_byte(unsigned char byte2send)
{
	unsigned char recv_packet = 0;
	int i;
	clk_busy_wait(100);
	for (i=0; i < 8; i++)
	{
		if ( (byte2send) & (0x00000001 << i))
		{				
			BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_LO_V);
			clk_busy_wait(5);
			BIO_OUT(BIO_MSM_SDO_REG, BIO_MSM_SDO_M, BIO_MSM_SDO_HI_V);
		}
		else
		{
			BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_LO_V);
			clk_busy_wait(5);
			BIO_OUT(BIO_MSM_SDO_REG, BIO_MSM_SDO_M, BIO_MSM_SDO_LO_V);
		}
		clk_busy_wait(15);
		recv_packet = recv_packet + (BIO_INM(BIO_MSM_SDI_REG, BIO_MSM_SDI_M)/BIO_MSM_SDI_M);
		recv_packet = ((recv_packet >> 1) | (recv_packet << 7));
		BIO_OUT(BIO_MSM_SCK_REG, BIO_MSM_SCK_M, BIO_MSM_SCK_HI_V);
		clk_busy_wait(20);
	}
	clk_busy_wait(100);
	return (recv_packet);
}
 
 
unsigned char spi_calculate_checksum(byte data_stream[])
{
	unsigned char xor_read_data = packet_set[1] ^ packet_set[2] ^ packet_set[3] ^ packet_set[4];
	unsigned char xor_write_data =  data2send[0] ^ data2send[1] ^ data2send[2] ^ data2send[3];
 
	if (phone_init_trans)
	{
		if (phData_read == 1) // phone to camera read
			return (cmd2send ^ xor_read_data);
		else // phone to camera write
			return (cmd2send ^ xor_write_data);
	}
	else
	{
		if (phData_read == 1)	// camera to phone write
			return (packet_set[0] ^ xor_read_data);
		else // camera to phone read
			return (packet_set[0] ^ xor_write_data);
	}
}
 
 
boolean command(unsigned char cmd)
{
	clk_julian_type	curTime;
	dword	curTimeInSec;
	dword   convValue = 0x55555555;
 
	switch( cmd )
	{
		case cmdListTime:
			/* Get the current time and store it in the NV */
			clk_rtc_get_time(&curTime);
			/* Convert to seconds */
			curTimeInSec = clk_julian_to_secs(&curTime);
			//convValue = convert_endian(curTimeInSec);
			//memcpy( data2send, &convValue, sizeof(dword) ); 
			break;
		case cmdListLanguage:
			break;
		case cmdListCamStatusNotify:
 
			break;
	}
	//for test
	memcpy( data2send, &convValue, sizeof(dword) ); 
	return TRUE;
}
 
 
//e.g 0x12345678 > 0x78563412
dword convert_endian(dword x)
{
	dword y = x;
	x = ( (x >> 8) | ( x & 0x000000ff ) << 24 ) & 0xff00ff00;
	y = ( (y << 8) | ( y & 0xff000000 ) >> 24 ) & 0x00ff00ff;
	return (x | y);
}


Provisional test script for camera side operation

Test script for camera-side(master) testing. Provisional Mock-up implementation for FPGA board utilization. Written in VHDL.

spi.vhd

-------------------------------------------------------------
-- SPI test code (spi.vhd)     
-- Date: 4/21/2009             
-- 2가지의 시나리오에 대한 테스트 코드입니다.
-- code syntax 확인 부탁드리며 
--  wait period에 대해서는 임의 결정된대로 구현 부탁드립니다.
--------------------------------------------------------------
 
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity SPItest is
    Port ( 
     Clk_32MHz : in std_logic;
		 CAM_SDI : in std_logic;
		 PREQ : in std_logic;
		 CAM_SDO : out std_logic;
		 SPI_CLK : out std_logic;
		 );
end SPItest;
 
architecture Behavioral of SPItest is
 
signal data : std_logic_vector(31 downto 0);
signal cnt2Clk    :  std_logic_vector(7 downto 0) := "00000000";
signal clk_80kHz	: std_logic;
signal clk_160kHz	: std_logic;
signal cmd_out : std_logic_vector(7 downto 0) := "00100010";
 
begin
 
		clk_generate:process(Clk_in)
		begin
	    if Clk_32MHz = '1' and Clk_in'Event then  
        cnt2Clk <= cnt2Clk + 1; 
      end if;
    end process;
 		clk_80kHz <= cnt2Clk(7);
		clk_160kHz <= cnt2Clk(6);
 
 
		send_packet:process(clk_160kHz, clk_80kHz)
		begin
			-- scenario 4
			-- send command to get_data
			-- wait for 25us (provisional)
			for I in 0 to 15 loop
				if(falling_edge(clk_160kHz)) then
					SPI_CLK <= clk_80kHz;
					CAM_SDO <= cmd_out(I/2);
				end if;
			end loop;
			SPI_CLK <= 1;	--halt
 
			-- receiving 4 bytes of data packet
			for J in 3 to 0 loop	
				-- wait for 100 us
				if(falling_edge(PREQ)) then	
					-- wait for 25us (provisional)
					for I in 0 to 15 loop
						if(falling_edge(clk_160kHz)) then
							SPI_CLK <= clk_80kHz;
							data(J*8+I/2) <= CAM_SDI;	
-- fetch data once at falling edge, then once again at rising edge
end if; end loop; end if; SPI_CLK <= 1; --break end loop;   -- checksum -- wait for 100 us if(falling_edge(PREQ)) then -- wait for 25us (provisional) for I in 0 to 15 loop if(falling_edge(clk_160kHz)) then SPI_CLK <= clk_80kHz; CAM_SDO <= cmd_out(I/2); end if; end loop; end if; SPI_CLK <= 1; --halt   -- scenario 2 -- send cmd(ready) if(falling_edge(PREQ)) then -- wait for 25us (provisional) for I in 0 to 15 loop if(falling_edge(clk_160kHz)) then SPI_CLK <= clk_80kHz; CAM_SDO <= cmd_out(I/2); end if; end loop; end if; SPI_CLK <= 1; --halt   -- sending 4 bytes of data packet for J in 3 to 0 loop -- wait for 100 us for I in 0 to 15 loop if(falling_edge(clk_160kHz)) then SPI_CLK <= clk_80kHz; CAM_SDO <= data(J*8+I/2); end if; end loop; SPI_CLK <= 1; --break end loop;   -- checksum -- wait for 100 us if(falling_edge(PREQ)) then -- wait for 25us (provisional) for I in 0 to 15 loop if(falling_edge(clk_160kHz)) then SPI_CLK <= clk_80kHz; CAM_SDO <= cmd_out(I/2); end if; end loop; end if; SPI_CLK <= 1; --halt end process;   end Behavioral;


FPGA configuration

CPU download method implementation for FPGA configuration(Silicon Blue iCE65); Written in C (Qualcomm MSM7227/ARM architecture)

for information on data source conversion, please refer to the Perl code at the bottom of this page.

#define CONFIGURATION_SIZE	17022	//Number of 32-bit words in FPGA cbit file
 
int arbiter_init( void )
{
// Hoonio - 2009.5.8
	unsigned int spibit;
	int c_done, i, j; 				  //Loop variables
 
	c_done = 0;
 
		//LGE_UPDATE_S poongdi@lge.com 2009-10-29 for touch move to hs_init
	gpio_tlmm_config(SPI_SCK);
	gpio_tlmm_config(SPI_SDO);
    gpio_tlmm_config(MSM_SS);
	gpio_tlmm_config(CRESET_B);
	gpio_tlmm_config(MSM_MODE_CTRL3);
	//gpio_tlmm_config_remote(MSM_MODE_CTRL3); //poongdi@lge.com 2009-10-23 remote -> 
	//gpio_tlmm_config_remote(MSM_SDI);
	//gpio_tlmm_config(CDONE);
	//LGE_UPDATE_S poongdi@lge.com 2009-10-23
	//LGE_UPDATE_S poongdi@lge.com 2009-10-23
	HAL_tlmm_SetOwner((uint16)57, 0);
	HAL_tlmm_SetOwner((uint16)111, 0);
	HAL_tlmm_SetOwner((uint16)120, 0);
	HAL_tlmm_SetOwner((uint16)90, 0);
	HAL_tlmm_SetOwner((uint16)30, 0);
	//HAL_tlmm_SetOwner((uint16)119, 0);
	HAL_tlmm_SetOwner((uint16)29, 0);
 
 
#if defined(fpga_powersave_mode)
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_LO_V);
	BIO_OUT(BIO_CRESET_B_REG, BIO_CRESET_B_M, BIO_CRESET_B_LO_V);	// Step 1 CReset low for 200ns
	clk_busy_wait(10);
	BIO_OUT(BIO_CRESET_B_REG, BIO_CRESET_B_M, BIO_CRESET_B_HI_V);   
	clk_busy_wait(300);                  // Step 2: Wait > 300us until iCe65 completes internal house keeping
	arbiter_xtra_download();			// Step 3: start feeding in SPI_CLK
#else
//Reset FPGA Configuration State Machine
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_LO_V);
	BIO_OUT(BIO_CRESET_B_REG, BIO_CRESET_B_M, BIO_CRESET_B_LO_V);	
	for (i=0; i < 32; i++) {
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
	}
	//HWIO_OUT(WDOG_RESET, HWIO_FMSK(WDOG_RESET,WATCH_DOG));	// kick watchdog
 
	//Force FPGA Configuration Slave Mode
	BIO_OUT(BIO_CRESET_B_REG, BIO_CRESET_B_M, BIO_CRESET_B_HI_V);
 
	for (i=0; i < 32; i++) {
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);	
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
	}
#endif //fpga_powersave_mode
 
//Step 13 Configure FPGA
	for (i=0; i < CONFIGURATION_SIZE; i++)
	{
		//HWIO_OUT(WDOG_RESET, HWIO_FMSK(WDOG_RESET,WATCH_DOG));	// kick watchdog
		spibit = arrBinary[i];
		for (j=31; j >=0; j--)
		{			
			BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
 
			if ( (spibit) & (0x00000001 << j))
			{				
				BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
				BIO_OUT(BIO_SPI_SDO_REG, BIO_SPI_SDO_M, BIO_SPI_SDO_HI_V);
			}
			else
			{
				BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
				BIO_OUT(BIO_SPI_SDO_REG, BIO_SPI_SDO_M, BIO_SPI_SDO_LO_V);
			}			
		}
	}
 
//INTLOCK();
#if defined(fpga_powersave_mode)
	hold_ss_high(100);	// step 14 hold SS high for 100 clock cycles
#else
	BIO_OUT(BIO_SPI_SDO_REG, BIO_SPI_SDO_M, BIO_SPI_SDO_LO_V);
	for (i=0; i < 25; i++)
	{
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
	}
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_HI_V);
  	for (i=0; i < 25; i++) 
	{
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
	}		  
#endif //fpga_powersave_mode
 
	c_done = (BIO_INM(BIO_CDONE_REG, BIO_CDONE_M)/BIO_CDONE_M);
 
	return c_done;		// Step 15 monitor C_DONE
}


Extra download setting

for power consumption reduction (Silicon Blue iCE65 scheme)

#define fpga_powersave_mode;
 
//Hoonio - FPGA power save mode, extra scheme
void bitstream_out_byte(byte data_byte)
{
	int j;
	for (j=7; j >=0; j--)
	{			
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
 
		if ( (data_byte) & (0x00000001 << j))
		{				
			BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
			BIO_OUT(BIO_SPI_SDO_REG, BIO_SPI_SDO_M, BIO_SPI_SDO_HI_V);
		}
		else
		{
			BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
			BIO_OUT(BIO_SPI_SDO_REG, BIO_SPI_SDO_M, BIO_SPI_SDO_LO_V);
		}			
	}
}
 
void hold_ss_high(int num_cycles)
{
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_HI_V);
  	for (num_cycles=0; num_cycles < 8; num_cycles++) 
	{
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_LO_V);
		BIO_OUT(BIO_SPI_SCK_REG, BIO_SPI_SCK_M, BIO_SPI_SCK_HI_V);
	}		  
}
 
 
 
void arbiter_xtra_download()
{
	hold_ss_high(8); 	// step 4 hold SS high for 8 clock cycles
 
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_LO_V); // step 5 switch SS low and init command out
	bitstream_out_byte(0x7E);
	bitstream_out_byte(0xAA);
	bitstream_out_byte(0x99);
	bitstream_out_byte(0x7E);
	bitstream_out_byte(0x01);
	bitstream_out_byte(0x0E);
 
	hold_ss_high(13000);	// step 6 hold SS high for 13000 clock cycles
 
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_LO_V); // step 7 switch SS low and init command out
	bitstream_out_byte(0x83);
	bitstream_out_byte(0x00);
	bitstream_out_byte(0x00);
	bitstream_out_byte(0x26);
	bitstream_out_byte(0x11);
 
	hold_ss_high(8);	// step 8 hold SS high for 8 clock cycles
 
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_LO_V); // step 9 switch SS low and init command out
	bitstream_out_byte(0x83);
	bitstream_out_byte(0x00);
	bitstream_out_byte(0x00);
	bitstream_out_byte(0x27);
	bitstream_out_byte(0x21);
 
	hold_ss_high(8);	// step 10 hold SS high for 8 clock cycles
 
	BIO_OUT(BIO_MSM_SS_REG, BIO_MSM_SS_M, BIO_MSM_SS_LO_V); // step 11 switch SS low and init command out
	bitstream_out_byte(0x81);
 
	hold_ss_high(8);	// step 12 hold SS high for 8 clock cycles
 
}


Hex data conversion

Perl script for binary to hexadecimal conversion; for use with FPGA configuration (SiliconBlue iCE65)

e.g. 7e AA 99 7E 51 00 01 05 -> 0x7EAA997E, 0x51000105,
#
# BIN to HEX conversion script
# based on Chami script
#
# perl bin2hex.pl [BINFILE] 0 > [OUTPUT]
 
# number of characters per line
$chars_per_line = 4;
 
# -------------------------------------
 
$lang  = $ARGV[1];
 
$rem_begin  = "__align(4) unsigned int const arrBinary[CONFIGURATION_SIZE]
={";
$rem_end    = "00};";
 
# initialize for Perl strings
# by default
$_var       = "$rem_begin";
$_begin     = "0x";
$_end       = "";
$_break     = "\, 0x";
$_format    = "\%02X";
$_separator = "";
$_comment   = "$rem_end ";
 
 
if(open(F, "<".$ARGV[0]))
{
  binmode(F);
 
  $s = '';
  $i = 0;
  $count = 0;
  $first = 3;
  $s .= $_begin;
  while(!eof(F))
  {
    if($i >= $chars_per_line)
    {
			if (($count % 32)==0)
			{
				$s .= "\,\n 0x";
			}
			else
			{
      	$s .= $_break;
    	}
      $i = 0;
    }
    if($first==3)
    {
      $s .= $_separator;
    }
    $s .= sprintf(
            $_format, ord(getc(F)));
    ++$i;
    ++$count;
    $first=0;
  }
  $s .= $_end;
  $s .= sprintf $_comment, $count;
  $s .= "\n\n";
 
  $s = "\n".sprintf($_var, $count).$s;
 
  print $s;
 
  close( F );
}
else
{
  print
    "FPGA binary to hexadecimal converter".
    "\n".
    "usage:\n".
    "  perl bin2hex.pl <binary file>".
    " <language id>\n".
    "\n".
    "  <binary file> : path to the ".
    "binary file\n".
    "  <language id> : 0 = Perl, ".
    "\n";
}

Sample Output

 #define CONFIGURATION_SIZE	17022	//Number of 32-bit words in FPGA cbit file
 
 __align(4) unsigned int const arrBinary[CONFIGURATION_SIZE]
 ={0x7EAA997E, 0x51000105, 0x92002062, 0x028F7200, 0xB0820000, 0x11000101, 0x00000200, 0x00000000,
  0x00080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
  ........
  ........
  ........
  ........
  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00002215, 0xF9010600};


Appendix: I2C Protocol

I2C system: bi-directional 2-wire bus for efficient inter-IC control

  • Features
    • requires only two bus lines: serial data line(SDA), serial clock line(SCL)
  • each device is software addressable by a unique address and a simple master/slave relationships exist at all times
  • serial, 8-bit oriented, bi-directional data transfers upto 100kbps in standard-mode, 400kbps in fast-mode

Bus operation concept


  1. Master generates a START condition, signalling all ICs on the bus to listen for data
  2. Master writes a 7-bit address, followed by a read/write bit
  3. Receiver sends an acknowledge bit over the bus. Transmitter read this bit to determine whether address is valid
  4. any number of 8-bit messages are sent, each followed by an acknowledge bit from receiver
  5. Message terminated by the master with a STOP condition; frees the bus for next master to begin communication. or continue by generating repeated START condition
  • both lines high at idle periods
  • high = Vdd for respective devices
  • data transferred most significant bit(MSB) first

Data transfer


  • START condition: SDA lowered while SCL is high)
    • 7-bit address + R/W'
    • Data line can only change when SCL is low
    • SCL line held low by slave to signal a wait state
  • STOP condition: SDA raised while SCL is high
Comments