forked from nodemcu/nodemcu-firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathi2c.c
More file actions
164 lines (146 loc) · 4.35 KB
/
i2c.c
File metadata and controls
164 lines (146 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Module for interfacing with the I2C interface
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
// Lua: speed = i2c.setup( id, sda, scl, speed )
static int i2c_setup( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
unsigned sda = luaL_checkinteger( L, 2 );
unsigned scl = luaL_checkinteger( L, 3 );
MOD_CHECK_ID( i2c, id );
MOD_CHECK_ID( gpio, sda );
MOD_CHECK_ID( gpio, scl );
if ( sda == 0 )
return luaL_error( L, "i2c SDA on D0 is not supported" );
s32 speed = ( s32 )luaL_checkinteger( L, 4 );
if ( speed <= 0 )
return luaL_error( L, "wrong arg range" );
speed = platform_i2c_setup( id, sda, scl, (u32)speed );
if ( speed == 0 )
return luaL_error( L, "failed to initialize i2c %d", id );
lua_pushinteger( L, speed );
return 1;
}
// Lua: i2c.start( id )
static int i2c_start( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( i2c, id );
if (platform_i2c_configured( id ) )
platform_i2c_send_start( id );
else
luaL_error( L, "i2c %d is not configured", id );
return 0;
}
// Lua: i2c.stop( id )
static int i2c_stop( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( i2c, id );
platform_i2c_send_stop( id );
return 0;
}
// Lua: status = i2c.address( id, address, direction )
static int i2c_address( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
int address = luaL_checkinteger( L, 2 );
int direction = luaL_checkinteger( L, 3 );
MOD_CHECK_ID( i2c, id );
if ( address < 0 || address > 127 )
return luaL_error( L, "wrong arg range" );
lua_pushboolean( L, platform_i2c_send_address( id, (u16)address, direction ) );
return 1;
}
// Lua: wrote = i2c.write( id, data1, [data2], ..., [datan] )
// data can be either a string, a table or an 8-bit number
static int i2c_write( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
const char *pdata;
size_t datalen, i;
int numdata;
u32 wrote = 0;
unsigned argn;
MOD_CHECK_ID( i2c, id );
if( lua_gettop( L ) < 2 )
return luaL_error( L, "wrong arg type" );
for( argn = 2; argn <= lua_gettop( L ); argn ++ )
{
// lua_isnumber() would silently convert a string of digits to an integer
// whereas here strings are handled separately.
if( lua_type( L, argn ) == LUA_TNUMBER )
{
numdata = ( int )luaL_checkinteger( L, argn );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "wrong arg range" );
if( platform_i2c_send_byte( id, numdata ) != 1 )
break;
wrote ++;
}
else if( lua_istable( L, argn ) )
{
datalen = lua_objlen( L, argn );
for( i = 0; i < datalen; i ++ )
{
lua_rawgeti( L, argn, i + 1 );
numdata = ( int )luaL_checkinteger( L, -1 );
lua_pop( L, 1 );
if( numdata < 0 || numdata > 255 )
return luaL_error( L, "wrong arg range" );
if( platform_i2c_send_byte( id, numdata ) == 0 )
break;
}
wrote += i;
if( i < datalen )
break;
}
else
{
pdata = luaL_checklstring( L, argn, &datalen );
for( i = 0; i < datalen; i ++ )
if( platform_i2c_send_byte( id, pdata[ i ] ) == 0 )
break;
wrote += i;
if( i < datalen )
break;
}
}
lua_pushinteger( L, wrote );
return 1;
}
// Lua: read = i2c.read( id, size )
static int i2c_read( lua_State *L )
{
unsigned id = luaL_checkinteger( L, 1 );
u32 size = ( u32 )luaL_checkinteger( L, 2 ), i;
luaL_Buffer b;
int data;
MOD_CHECK_ID( i2c, id );
if( size == 0 )
return 0;
luaL_buffinit( L, &b );
for( i = 0; i < size; i ++ )
if( ( data = platform_i2c_recv_byte( id, i < size - 1 ) ) == -1 )
break;
else
luaL_addchar( &b, ( char )data );
luaL_pushresult( &b );
return 1;
}
// Module function map
LROT_BEGIN(i2c)
LROT_FUNCENTRY( setup, i2c_setup )
LROT_FUNCENTRY( start, i2c_start )
LROT_FUNCENTRY( stop, i2c_stop )
LROT_FUNCENTRY( address, i2c_address )
LROT_FUNCENTRY( write, i2c_write )
LROT_FUNCENTRY( read, i2c_read )
LROT_NUMENTRY( FASTPLUS, PLATFORM_I2C_SPEED_FASTPLUS )
LROT_NUMENTRY( FAST, PLATFORM_I2C_SPEED_FAST )
LROT_NUMENTRY( SLOW, PLATFORM_I2C_SPEED_SLOW )
LROT_NUMENTRY( TRANSMITTER, PLATFORM_I2C_DIRECTION_TRANSMITTER )
LROT_NUMENTRY( RECEIVER, PLATFORM_I2C_DIRECTION_RECEIVER )
LROT_END( i2c, NULL, 0 )
NODEMCU_MODULE(I2C, "i2c", i2c, NULL);