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 ProtocolI2C 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
- Master generates a START condition, signalling all ICs on the bus to listen for data
- Master writes a 7-bit address, followed by a read/write bit
- Receiver sends an acknowledge bit over the bus. Transmitter read this bit to determine whether address is valid
- any number of 8-bit messages are sent, each followed by an acknowledge bit from receiver
- 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
|