Skip to content

Commit fc82ceb

Browse files
committed
This commit allows the user to communicate with I2C slaves devices. It consists of a soft i2c core along with a shift register and an examples directory to show its usage.
1 parent 0ddd377 commit fc82ceb

File tree

6 files changed

+817
-1
lines changed

6 files changed

+817
-1
lines changed

examples/download.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash -e
2+
3+
DEVS=$(lsusb|grep -E '(2a19|16c0|04b4|1d50|fb9a|1443)' |sed 's/:.*//;s/Bus //;s/Device //;s/ /\//')
4+
5+
if [ -z "$1" ]; then
6+
echo "$0: usage: $0 <file>"
7+
exit 1;
8+
fi
9+
10+
for dev in $DEVS;do
11+
echo "Downloading $1 to $dev"
12+
/sbin/fxload -D /dev/bus/usb/$dev -t fx2lp -I $1
13+
done
14+
15+
exit 0

examples/i2c_bitbang/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FX2LIBDIR=../../
2+
BASENAME = i2c_main
3+
SOURCES=i2c_main.c
4+
CODE_SIZE = --code-size 0x3000
5+
XRAM_LOC = --xram-loc 0x3200
6+
XRAM_SIZE = --xram-size 0x700
7+
DSCR_AREA=
8+
INT2JT=
9+
include $(FX2LIBDIR)/lib/fx2.mk
10+
fx2_download:
11+
../download.sh build/$(BASENAME).ihx

examples/i2c_bitbang/i2c_main.c

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/**
2+
* Copyright (C) 2009 Ubixum, Inc.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+
**/
18+
#include <stdio.h>
19+
#include <fx2regs.h>
20+
#include <fx2macros.h>
21+
#include <delay.h>
22+
#include <fx2ints.h>
23+
#include <i2c/i2c_utils.h>
24+
25+
//DELETE once merged.
26+
void fast_uart(BYTE a);
27+
28+
29+
/**************************************************
30+
I2C declarations
31+
***************************************************/
32+
//Buffer to load up the data and insert into
33+
//the i2c_client queue
34+
__xdata unsigned char write_addr[I2C_ADDR];
35+
//This is the data buffer.
36+
__xdata unsigned char write_data[I2C_DATA];
37+
//This is the address length
38+
__xdata unsigned char rx_addr_length;
39+
//This is the data length which needs to be read from or written to.
40+
__xdata unsigned char rx_data_length;
41+
//Implementation specific. Not needed for all examples. Used here
42+
//to read and write from different address locations.
43+
__xdata unsigned char wr_addr;
44+
45+
46+
void main() {
47+
SETCPUFREQ(CLK_48M);
48+
EA = 1; // global interrupt enable
49+
/********************************
50+
I2C BLOCK BITBANG
51+
*********************************/
52+
//Called with number of retries
53+
i2c_init(3);
54+
configure_start_timer();
55+
ENABLE_TIMER1();
56+
wr_addr = 0x03;
57+
while (TRUE)
58+
{
59+
60+
write_addr[0] = 0xa0;
61+
write_addr[1] = 0x00;
62+
write_addr[2] = wr_addr;
63+
write_data[0] = 0x44;
64+
//Address, data, address length and data length
65+
I2CPutTX(&write_addr[0],&write_data[0],0x03,0x01);
66+
//i2c_control();
67+
write_addr[0] = 0xa1;
68+
write_data[0] = 0x34;
69+
I2CPutRXRead(&write_addr[0],0x01,0x01);
70+
I2CGetRXData(&write_addr[0],&write_data[0]);
71+
fast_uart(data[0]);
72+
i2c_control();
73+
if(wr_addr == 0x00)
74+
{
75+
wr_addr = 0x03;
76+
}
77+
else
78+
{
79+
wr_addr--;
80+
}
81+
}
82+
}
83+
84+
void timer1_isr ()
85+
__interrupt TF1_ISR
86+
{
87+
__asm
88+
mov a,_tx_rx //(2 cycles. Move the state into the accumulator.)
89+
CJNE A, #0x02, state //(4 cycles. If in halt state, do nothing.)
90+
ajmp finish //(3 cycles. Return from ISR if buffer is not ready to shift the data out.)
91+
state:
92+
djnz _bit_count,cont; //(4 cycles. This is sued to keep track of the number of data bytes which need to be shifted out.)
93+
mov _tx_rx,#0x02 //(3 cycles. Set our current status to busy so nothing else can interrupt us till we shift data in or out.)
94+
ajmp finish //(3 cycles. If data has been shifted, but has not been read, then jump to finish.)
95+
cont:
96+
orl _OEA,#0x40 //(3 cycles. First always set out clock pin direction. This is needed as discussed already in comments.)
97+
clr _PA6 //(2 cycles. Set the SCL line low.)
98+
mov a,_tx_rx //(2 cycles. Move the state back into the accumulator.)
99+
CJNE A, #0x00, rx //(4 cycles. Check if we are in RX or TX mode.)
100+
tx:
101+
orl _OEA,#0x80 //(3 cycles. We are in TX mode. Set the SDA direction.)
102+
mov a, _tx_i2c_buffer //(2 cycles. Move the data which needs to be transmitted into the accumulator.)
103+
rlc a //(1 cycles. Rotate and move the bit which needs to be sent out into the carry.)
104+
mov _PA7, c //(2 cycles. Move the data into the SDA pin.)
105+
mov _tx_i2c_buffer,a //(2 cycles. Now move the data back so that the next rotate can be performed when the ISR executes.)
106+
sjmp sclh //(3 cycles. Jump to toggle SCL now.)
107+
rx:
108+
anl _OEA,#0x7f //(3 cycles. Set the mode of SDA pin again.)
109+
mov a, _tx_i2c_buffer //(2 cycles. Move data received into accumulator.)
110+
mov c,_PA7 //(2 cycles. Move the SDA line value into the carry. Delay has already been introduced between setting clock low and reading the first bit of data. Otherwise, follow the MPSSE i2c routine.)
111+
rlc a //(1 cycle. Since the next bit will be received in the same ISR we need to shift the data.)
112+
mov _tx_i2c_buffer,a //(2 cycles. Move the data back into accumulator for next ISR execution routine)
113+
nop //(1 cycle. Wait for 1 cycle before setting the bit high again.)
114+
sclh:
115+
setb _PA6 //(2 cycles. Set the SCL high)
116+
finish:
117+
nop
118+
__endasm;
119+
}
120+
121+
/**************************
122+
Will be DELETED once the pull requests are merged
123+
**************************/
124+
void fast_uart(BYTE a) {
125+
OEA |= 0x04;
126+
//An efficient UART bitbang routine in assembly
127+
__asm
128+
//Like #define in C. Can easily be used to change the pin
129+
.equ TX_PIN, _PA2
130+
//Disable interrupts
131+
clr _EA
132+
//Move the data to be sent into the ACC
133+
mov a , dpl
134+
//Clear carry
135+
clr c
136+
//We need to send out 8 bits of data
137+
//Load r0 with value 8
138+
mov r0, #0x08;
139+
//Create the start bit
140+
clr TX_PIN;
141+
//Precalculated delay since 1 cycle takes 88.33ns
142+
//Mov takes 2 cycles
143+
mov r1, #0x22;
144+
0006$:
145+
//DJNZ on Rn takes 3 cycle. This waits for
146+
//23*3, 69 cycles
147+
//71 cycle delay
148+
djnz r1, 0006$;
149+
//Add 2 more cycles of delay
150+
//97 cycles
151+
nop;
152+
nop;
153+
0001$:
154+
//2 cycles
155+
rrc a;
156+
//Move the carry into the port
157+
mov _PA2, c
158+
//Now we need to add delay for the next
159+
//2 cycles of delay
160+
mov r1, #0x1F;
161+
//31*3 , 93 cycles of delay
162+
0004$:
163+
djnz r1, 0004$;
164+
//1 more cycle, now upto 94
165+
nop;
166+
//3 more cycles of delay
167+
//97 cycles
168+
djnz r0, 0001$;
169+
setb _PA2;
170+
mov r1, #0x80;
171+
0005$:
172+
djnz r1, 0005$;
173+
nop
174+
setb _EA;
175+
__endasm;
176+
}

include/i2c/i2c_utils.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#ifndef I2C_UTILS_
2+
#define I2C_UTILS_
3+
4+
#include "fx2regs.h"
5+
#include "fx2types.h"
6+
7+
#define I2C_ELEMENTS 5
8+
#define I2C_DATA 5
9+
#define I2C_ADDR 5
10+
#define I2C_SIZE (I2C_ELEMENTS + 1)
11+
#define SCL PA6
12+
#define SDA PA7
13+
#define SYNCDELAY SYNCDELAY4
14+
15+
//Structure for writing the I2C data onto SDA and SCL
16+
struct i2c_client
17+
{
18+
//Address
19+
unsigned short addr[I2C_ADDR];
20+
//Upto 5 data bytes can be written
21+
BYTE data[I2C_DATA];
22+
//The length of data to write to I2C lines
23+
//Does not include the address byte
24+
BYTE data_length;
25+
BYTE addr_length;
26+
};
27+
28+
//Structure for reading data from I2C device.
29+
struct i2c_client_read
30+
{
31+
//Address
32+
unsigned short addr[I2C_ADDR];
33+
//The length of data to write to I2C lines
34+
//Does not include the address byte
35+
BYTE data_length;
36+
BYTE addr_length;
37+
};
38+
__bit I2CPutTX(BYTE * addr, BYTE * data, BYTE addr_length, BYTE data_length);
39+
__bit I2CPutRXRead(BYTE * addr, BYTE addr_length, BYTE data_length);
40+
__bit I2CGetRXRead();
41+
__bit I2CCheckRXRead();
42+
__bit I2CPutRXData(BYTE * addr, BYTE * data, BYTE addr_length, BYTE data_length);
43+
__bit I2CGetRXData(BYTE * addr, BYTE * data);
44+
__bit I2CCheckRXData();
45+
__bit I2CGetTX();
46+
__bit I2CCheckTX();
47+
void i2c_init(BYTE retry);
48+
void i2c_control();
49+
void configure_start_timer();
50+
51+
52+
53+
/*************************
54+
I2C Controller
55+
*************************/
56+
57+
enum isr_state
58+
{
59+
state_tx = 0, //0
60+
state_rx = 1 , //1
61+
state_wait = 2
62+
};
63+
enum i2c_states
64+
{
65+
idle = 0,
66+
start = 1,
67+
address = 2,
68+
addr_ack = 3,
69+
data_write = 4,
70+
data_write_ack = 5,
71+
data_read = 6,
72+
data_read_ack = 7,
73+
stop = 8,
74+
read_addr_ack = 9,
75+
read_data_ack = 10,
76+
};
77+
extern enum isr_state tx_rx;
78+
extern BYTE bit_count;
79+
extern BYTE tx_i2c_buffer;
80+
//Variable declarations for address and data
81+
extern __xdata BYTE addr[I2C_ADDR];
82+
extern __xdata BYTE data[I2C_DATA];
83+
extern __xdata BYTE length;
84+
extern __xdata BYTE retries;
85+
/****************************************
86+
Cant pass so many arguments in a function
87+
*****************************************/
88+
extern __xdata BYTE write_addr[I2C_ADDR];
89+
extern __xdata BYTE write_data[I2C_DATA];
90+
extern __xdata BYTE rx_addr_length;
91+
extern __xdata BYTE rx_data_length;
92+
extern __xdata BYTE wr_addr;
93+
#endif

lib/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1616

1717
AS8051?=sdas8051
18-
SOURCES = serial.c i2c.c delay.c setupdat.c gpif.c eputils.c $(wildcard interrupts/*.c)
18+
SOURCES = serial.c i2c.c delay.c setupdat.c gpif.c eputils.c softuart.c $(wildcard interrupts/*.c) $(wildcard i2c/*.c)
1919
FX2_OBJS = $(patsubst %.c,%.rel, $(SOURCES)) usbav.rel
2020
INCLUDES = -I../include
2121
SDCC = sdcc -mmcs51 $(SDCCFLAGS)

0 commit comments

Comments
 (0)