Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
daa58484
Commit
daa58484
authored
Oct 14, 2018
by
devsaurus
Browse files
rework parts of I2S
parent
5e64def6
Changes
2
Show whitespace changes
Inline
Side-by-side
components/modules/i2s.c
View file @
daa58484
// Module for interfacing with i2s hardware
// Module for interfacing with i2s hardware
#include <string.h>
#include "module.h"
#include "module.h"
#include "lauxlib.h"
#include "lauxlib.h"
#include "lmem.h"
#include "lmem.h"
...
@@ -19,55 +21,101 @@
...
@@ -19,55 +21,101 @@
#define I2S_CHECK_ID(id) if(id >= MAX_I2C_NUM) luaL_error( L, "i2s not exists" )
#define I2S_CHECK_ID(id) if(id >= MAX_I2C_NUM) luaL_error( L, "i2s not exists" )
typedef
struct
{
typedef
struct
{
xTaskHandle
taskHandle
;
int
ref
;
QueueHandle_t
*
event_queue
;
const
char
*
data
;
int
event_cb
;
size_t
len
;
}
i2s_
status
_t
;
}
i2s_
tx_data
_t
;
typedef
struct
{
typedef
struct
{
i2s_event_t
event
;
struct
{
i2s_status_t
*
status
;
xTaskHandle
taskHandle
;
}
i2s_event_post_type
;
QueueHandle_t
queue
;
}
tx
;
struct
{
xTaskHandle
taskHandle
;
QueueHandle_t
queue
;
}
rx
;
int
cb
;
int
i2s_bits_per_sample
,
data_bits_per_sample
;
}
i2s_status_t
;
static
task_handle_t
i2s_
event
_task_id
;
static
task_handle_t
i2s_
tx_task_id
,
i2s_rx_task_id
,
i2s_disposal
_task_id
;
static
i2s_status_t
i2s_status
[
MAX_I2C_NUM
];
static
i2s_status_t
i2s_status
[
MAX_I2C_NUM
];
// LUA
// LUA
static
void
i2s_event_task
(
task_param_t
param
,
task_prio_t
prio
)
{
static
void
i2s_tx_task
(
task_param_t
param
,
task_prio_t
prio
)
{
i2s_event_post_type
*
post
=
(
i2s_event_post_type
*
)
param
;
int
i2s_id
=
(
int
)
param
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
if
(
is
->
cb
!=
LUA_NOREF
)
{
lua_State
*
L
=
lua_getstate
();
lua_rawgeti
(
L
,
LUA_REGISTRYINDEX
,
is
->
cb
);
lua_pushinteger
(
L
,
i2s_id
);
lua_pushstring
(
L
,
"tx"
);
lua_call
(
L
,
2
,
0
);
}
}
static
void
i2s_rx_task
(
task_param_t
param
,
task_prio_t
prio
)
{
int
i2s_id
=
(
int
)
param
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
if
(
is
->
cb
!=
LUA_NOREF
)
{
lua_State
*
L
=
lua_getstate
();
lua_rawgeti
(
L
,
LUA_REGISTRYINDEX
,
is
->
cb
);
lua_pushinteger
(
L
,
i2s_id
);
lua_pushstring
(
L
,
"rx"
);
lua_call
(
L
,
2
,
0
);
}
}
static
void
i2s_disposal_task
(
task_param_t
param
,
task_prio_t
prio
)
{
lua_State
*
L
=
lua_getstate
();
lua_State
*
L
=
lua_getstate
();
int
event_cb
=
post
->
status
->
event_cb
;
int
ref
=
(
int
)
param
;
if
(
event_cb
==
LUA_NOREF
)
{
free
(
post
);
luaL_unref
(
L
,
LUA_REGISTRYINDEX
,
ref
);
return
;
}
lua_rawgeti
(
L
,
LUA_REGISTRYINDEX
,
event_cb
);
if
(
post
->
event
.
type
==
I2S_EVENT_TX_DONE
)
lua_pushstring
(
L
,
"sent"
);
else
if
(
post
->
event
.
type
==
I2S_EVENT_RX_DONE
)
lua_pushstring
(
L
,
"data"
);
else
lua_pushstring
(
L
,
"error"
);
lua_pushinteger
(
L
,
post
->
event
.
size
);
free
(
post
);
lua_call
(
L
,
2
,
0
);
}
}
// RTOS
// RTOS
static
void
task_I2S
(
void
*
pvParameters
){
static
void
task_I2S_rx
(
void
*
pvParameters
)
{
i2s_status_t
*
is
=
(
i2s_status_t
*
)
pvParameters
;
int
i2s_id
=
(
int
)
pvParameters
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
i2s_event_t
i2s_event
;
for
(;;)
{
// process I2S RX events
xQueueReceive
(
is
->
rx
.
queue
,
&
i2s_event
,
portMAX_DELAY
);
if
(
i2s_event
.
type
==
I2S_EVENT_RX_DONE
)
{
task_post_high
(
i2s_rx_task_id
,
i2s_id
);
}
}
}
i2s_event_t
event
;
static
void
task_I2S_tx
(
void
*
pvParameters
)
{
int
i2s_id
=
(
int
)
pvParameters
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
for
(;;){
i2s_tx_data_t
tx_data
;
if
(
xQueueReceive
(
is
->
event_queue
,
&
event
,
3
*
portTICK_PERIOD_MS
)
==
pdTRUE
){
i2s_event_post_type
*
post
=
(
i2s_event_post_type
*
)
malloc
(
sizeof
(
i2s_event_post_type
)
);
for
(;;)
{
post
->
status
=
is
;
// request new TX data
memcpy
(
&
(
post
->
event
),
&
event
,
sizeof
(
i2s_event_t
));
task_post_high
(
i2s_tx_task_id
,
i2s_id
);
task_post_high
(
i2s_event_task_id
,
(
task_param_t
)
post
);
// get TX data from Lua task
xQueueReceive
(
is
->
tx
.
queue
,
&
tx_data
,
portMAX_DELAY
);
// write TX data to I2S, note that this call might block
size_t
dummy
;
if
(
is
->
data_bits_per_sample
==
is
->
i2s_bits_per_sample
)
{
i2s_write
(
i2s_id
,
tx_data
.
data
,
tx_data
.
len
,
&
dummy
,
portMAX_DELAY
);
}
else
{
i2s_write_expand
(
i2s_id
,
tx_data
.
data
,
tx_data
.
len
,
is
->
data_bits_per_sample
,
is
->
i2s_bits_per_sample
,
&
dummy
,
portMAX_DELAY
);
}
}
// notify Lua to dispose object
task_post_low
(
i2s_disposal_task_id
,
tx_data
.
ref
);
}
}
}
}
...
@@ -76,49 +124,108 @@ static int node_i2s_start( lua_State *L )
...
@@ -76,49 +124,108 @@ static int node_i2s_start( lua_State *L )
{
{
int
i2s_id
=
luaL_checkinteger
(
L
,
1
);
int
i2s_id
=
luaL_checkinteger
(
L
,
1
);
I2S_CHECK_ID
(
i2s_id
);
I2S_CHECK_ID
(
i2s_id
);
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
int
top
=
lua_gettop
(
L
);
luaL_checkanytable
(
L
,
2
);
luaL_checkanytable
(
L
,
2
);
i2s_config_t
i2s_config
;
i2s_config_t
i2s_config
;
memset
(
&
i2s_config
,
0
,
sizeof
(
i2s_config
)
);
i2s_pin_config_t
pin_config
;
i2s_pin_config_t
pin_config
;
memset
(
&
pin_config
,
0
,
sizeof
(
pin_config
)
);
lua_getfield
(
L
,
2
,
"mode"
);
lua_getfield
(
L
,
2
,
"mode"
);
i2s_config
.
mode
=
luaL_optint
(
L
,
-
1
,
I2S_MODE_MASTER
|
I2S_MODE_TX
);
i2s_config
.
mode
=
luaL_optint
(
L
,
-
1
,
I2S_MODE_MASTER
|
I2S_MODE_TX
);
//
lua_getfield
(
L
,
2
,
"rate"
);
lua_getfield
(
L
,
2
,
"rate"
);
i2s_config
.
sample_rate
=
luaL_optint
(
L
,
-
1
,
44100
);
i2s_config
.
sample_rate
=
luaL_optint
(
L
,
-
1
,
44100
);
//
lua_getfield
(
L
,
2
,
"bits"
);
lua_getfield
(
L
,
2
,
"bits"
);
i2s_config
.
bits_per_sample
=
16
;
is
->
data_bits_per_sample
=
luaL_optint
(
L
,
-
1
,
16
);
is
->
i2s_bits_per_sample
=
is
->
data_bits_per_sample
<
I2S_BITS_PER_SAMPLE_16BIT
?
I2S_BITS_PER_SAMPLE_16BIT
:
is
->
data_bits_per_sample
;
i2s_config
.
bits_per_sample
=
is
->
i2s_bits_per_sample
;
//
lua_getfield
(
L
,
2
,
"channel"
);
lua_getfield
(
L
,
2
,
"channel"
);
i2s_config
.
channel_format
=
luaL_optint
(
L
,
-
1
,
I2S_CHANNEL_FMT_RIGHT_LEFT
);
i2s_config
.
channel_format
=
luaL_optint
(
L
,
-
1
,
I2S_CHANNEL_FMT_RIGHT_LEFT
);
//
lua_getfield
(
L
,
2
,
"format"
);
lua_getfield
(
L
,
2
,
"format"
);
i2s_config
.
communication_format
=
luaL_optint
(
L
,
-
1
,
I2S_COMM_FORMAT_I2S
|
I2S_COMM_FORMAT_I2S_MSB
);
i2s_config
.
communication_format
=
luaL_optint
(
L
,
-
1
,
I2S_COMM_FORMAT_I2S
|
I2S_COMM_FORMAT_I2S_MSB
);
//
lua_getfield
(
L
,
2
,
"buffer_count"
);
lua_getfield
(
L
,
2
,
"buffer_count"
);
i2s_config
.
dma_buf_count
=
luaL_optint
(
L
,
-
1
,
2
);
i2s_config
.
dma_buf_count
=
luaL_optint
(
L
,
-
1
,
2
);
//
lua_getfield
(
L
,
2
,
"buffer_len"
);
lua_getfield
(
L
,
2
,
"buffer_len"
);
i2s_config
.
dma_buf_len
=
luaL_optint
(
L
,
-
1
,
i2s_config
.
sample_rate
/
100
);
i2s_config
.
dma_buf_len
=
luaL_optint
(
L
,
-
1
,
i2s_config
.
sample_rate
/
100
);
i2s_config
.
intr_alloc_flags
=
ESP_INTR_FLAG_LEVEL2
;
//
i2s_config
.
intr_alloc_flags
=
ESP_INTR_FLAG_LOWMED
|
ESP_INTR_FLAG_IRAM
;
//
lua_getfield
(
L
,
2
,
"bck_pin"
);
lua_getfield
(
L
,
2
,
"bck_pin"
);
pin_config
.
bck_io_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
pin_config
.
bck_io_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
//
lua_getfield
(
L
,
2
,
"ws_pin"
);
lua_getfield
(
L
,
2
,
"ws_pin"
);
pin_config
.
ws_io_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
pin_config
.
ws_io_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
//
lua_getfield
(
L
,
2
,
"data_out_pin"
);
lua_getfield
(
L
,
2
,
"data_out_pin"
);
pin_config
.
data_out_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
pin_config
.
data_out_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
//
lua_getfield
(
L
,
2
,
"data_in_pin"
);
lua_getfield
(
L
,
2
,
"data_in_pin"
);
pin_config
.
data_in_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
pin_config
.
data_in_num
=
luaL_optint
(
L
,
-
1
,
I2S_PIN_NO_CHANGE
);
//
lua_getfield
(
L
,
2
,
"dac_mode"
);
i2s_dac_mode_t
dac_mode
=
luaL_optint
(
L
,
-
1
,
I2S_DAC_CHANNEL_DISABLE
);
//
lua_getfield
(
L
,
2
,
"adc1_channel"
);
adc1_channel_t
adc1_channel
=
luaL_optint
(
L
,
-
1
,
ADC1_CHANNEL_MAX
);
// handle optional callback functions TX and RX
lua_settop
(
L
,
top
);
if
(
lua_isfunction
(
L
,
3
))
{
lua_pushvalue
(
L
,
3
);
is
->
cb
=
luaL_ref
(
L
,
LUA_REGISTRYINDEX
);
}
else
{
is
->
cb
=
LUA_NOREF
;
}
lua_settop
(
L
,
3
);
esp_err_t
err
;
i2s_status
[
i2s_id
].
event_cb
=
luaL_ref
(
L
,
LUA_REGISTRYINDEX
);
if
(
i2s_config
.
mode
&
I2S_MODE_RX
)
{
err
=
i2s_driver_install
(
i2s_id
,
&
i2s_config
,
i2s_config
.
dma_buf_count
,
&
is
->
rx
.
queue
);
esp_err_t
err
=
i2s_driver_install
(
i2s_id
,
&
i2s_config
,
i2s_config
.
dma_buf_count
,
&
i2s_status
[
i2s_id
].
event_queue
);
}
else
{
if
(
err
!=
ESP_OK
)
err
=
i2s_driver_install
(
i2s_id
,
&
i2s_config
,
i2s_config
.
dma_buf_count
,
NULL
);
}
if
(
err
!=
ESP_OK
)
luaL_error
(
L
,
"i2s can not start"
);
luaL_error
(
L
,
"i2s can not start"
);
i2s_set_pin
(
i2s_id
,
&
pin_config
);
char
pcName
[
5
];
if
(
dac_mode
!=
I2S_DAC_CHANNEL_DISABLE
)
{
snprintf
(
pcName
,
5
,
"I2S%d"
,
i2s_id
);
if
(
i2s_set_dac_mode
(
dac_mode
)
!=
ESP_OK
)
pcName
[
4
]
=
'\0'
;
luaL_error
(
L
,
"error setting dac mode"
);
xTaskCreate
(
task_I2S
,
pcName
,
2048
,
&
i2s_status
[
i2s_id
],
ESP_TASK_MAIN_PRIO
+
1
,
&
i2s_status
[
i2s_id
].
taskHandle
);
}
if
(
adc1_channel
!=
ADC1_CHANNEL_MAX
)
{
if
(
i2s_set_adc_mode
(
ADC_UNIT_1
,
adc1_channel
)
!=
ESP_OK
)
luaL_error
(
L
,
"error setting adc1 mode"
);
}
if
(
i2s_set_pin
(
i2s_id
,
&
pin_config
)
!=
ESP_OK
)
luaL_error
(
L
,
"error setting pins"
);
if
(
i2s_config
.
mode
&
I2S_MODE_TX
)
{
// prepare TX task
char
pcName
[
8
];
snprintf
(
pcName
,
8
,
"I2S_tx_%d"
,
i2s_id
);
pcName
[
7
]
=
'\0'
;
if
((
is
->
tx
.
queue
=
xQueueCreate
(
2
,
sizeof
(
i2s_tx_data_t
)
))
==
NULL
)
return
luaL_error
(
L
,
"cannot create queue"
);
xTaskCreate
(
task_I2S_tx
,
pcName
,
2048
,
(
void
*
)
i2s_id
,
ESP_TASK_MAIN_PRIO
+
1
,
&
is
->
tx
.
taskHandle
);
}
if
(
i2s_config
.
mode
&
I2S_MODE_RX
)
{
// prepare RX task
char
pcName
[
8
];
snprintf
(
pcName
,
8
,
"I2S_rx_%d"
,
i2s_id
);
pcName
[
7
]
=
'\0'
;
xTaskCreate
(
task_I2S_rx
,
pcName
,
1024
,
(
void
*
)
i2s_id
,
ESP_TASK_MAIN_PRIO
+
1
,
&
is
->
rx
.
taskHandle
);
}
return
0
;
return
0
;
}
}
...
@@ -128,18 +235,28 @@ static int node_i2s_stop( lua_State *L )
...
@@ -128,18 +235,28 @@ static int node_i2s_stop( lua_State *L )
{
{
int
i2s_id
=
luaL_checkinteger
(
L
,
1
);
int
i2s_id
=
luaL_checkinteger
(
L
,
1
);
I2S_CHECK_ID
(
i2s_id
);
I2S_CHECK_ID
(
i2s_id
);
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
i2s_driver_uninstall
(
i2s_id
);
i2s_driver_uninstall
(
i2s_id
);
i2s_status
[
i2s_id
].
event_queue
=
NULL
;
if
(
i2s_status
[
i2s_id
].
taskHandle
!=
NULL
)
{
if
(
is
->
tx
.
taskHandle
!=
NULL
)
{
vTaskDelete
(
i2s_status
[
i2s_id
].
taskHandle
);
vTaskDelete
(
is
->
tx
.
taskHandle
);
i2s_status
[
i2s_id
].
taskHandle
=
NULL
;
is
->
tx
.
taskHandle
=
NULL
;
}
if
(
is
->
tx
.
queue
!=
NULL
)
{
vQueueDelete
(
is
->
tx
.
queue
);
is
->
tx
.
queue
=
NULL
;
}
}
if
(
i2s_status
[
i2s_id
].
event_cb
!=
LUA_NOREF
)
{
if
(
is
->
rx
.
taskHandle
!=
NULL
)
{
luaL_unref
(
L
,
LUA_REGISTRYINDEX
,
i2s_status
[
i2s_id
].
event_cb
);
vTaskDelete
(
is
->
rx
.
taskHandle
);
i2s_status
[
i2s_id
].
event_cb
=
LUA_NOREF
;
is
->
rx
.
taskHandle
=
NULL
;
}
// the rx queue is created and destroyed by the I2S driver
if
(
is
->
cb
!=
LUA_NOREF
)
{
luaL_unref
(
L
,
LUA_REGISTRYINDEX
,
is
->
cb
);
is
->
cb
=
LUA_NOREF
;
}
}
return
0
;
return
0
;
...
@@ -152,40 +269,33 @@ static int node_i2s_read( lua_State *L )
...
@@ -152,40 +269,33 @@ static int node_i2s_read( lua_State *L )
I2S_CHECK_ID
(
i2s_id
);
I2S_CHECK_ID
(
i2s_id
);
size_t
bytes
=
luaL_checkinteger
(
L
,
2
);
size_t
bytes
=
luaL_checkinteger
(
L
,
2
);
int
wait_ms
=
luaL_optint
(
L
,
3
,
0
);
//
int wait_ms = luaL_optint(L, 3, 0);
char
*
data
=
luaM_malloc
(
L
,
bytes
);
char
*
data
=
luaM_malloc
(
L
,
bytes
);
size_t
read
=
i2s_read_bytes
(
i2s_id
,
data
,
bytes
,
wait_ms
/
portTICK_RATE_MS
);
size_t
read
=
0
;
//read = i2s_read_bytes(i2s_id, data, bytes, wait_ms / portTICK_RATE_MS);
lua_pushlstring
(
L
,
data
,
read
);
lua_pushlstring
(
L
,
data
,
read
);
luaM_free
(
L
,
data
);
luaM_free
(
L
,
data
);
return
1
;
return
1
;
}
}
// Lua: write( i2s_id, data
[, wait_ms]
)
// Lua: write( i2s_id, data )
static
int
node_i2s_write
(
lua_State
*
L
)
static
int
node_i2s_write
(
lua_State
*
L
)
{
{
int
i2s_id
=
luaL_checkinteger
(
L
,
1
);
int
stack
=
0
;
int
i2s_id
=
luaL_checkinteger
(
L
,
++
stack
);
I2S_CHECK_ID
(
i2s_id
);
I2S_CHECK_ID
(
i2s_id
);
size_t
bytes
;
i2s_tx_data_t
tx_data
;
char
*
data
;
tx_data
.
data
=
(
const
char
*
)
luaL_checklstring
(
L
,
++
stack
,
&
tx_data
.
len
);
if
(
lua_istable
(
L
,
2
)
)
{
lua_pushvalue
(
L
,
stack
);
bytes
=
lua_objlen
(
L
,
2
);
tx_data
.
ref
=
luaL_ref
(
L
,
LUA_REGISTRYINDEX
);
data
=
(
char
*
)
luaM_malloc
(
L
,
bytes
);
for
(
int
i
=
0
;
i
<
bytes
;
i
++
)
{
lua_rawgeti
(
L
,
2
,
i
+
1
);
data
[
i
]
=
(
uint8_t
)
luaL_checkinteger
(
L
,
-
1
);
}
}
else
{
data
=
(
char
*
)
luaL_checklstring
(
L
,
2
,
&
bytes
);
}
int
wait_ms
=
luaL_optint
(
L
,
3
,
0
);
size_t
wrote
=
i2s_write_bytes
(
i2s_id
,
data
,
bytes
,
wait_ms
/
portTICK_RATE_MS
);
if
(
lua_istable
(
L
,
2
)
)
luaM_free
(
L
,
data
);
lua_pushinteger
(
L
,
(
lua_Integer
)
wrote
);
return
1
;
// post this to the TX task
xQueueSendToBack
(
i2s_status
[
i2s_id
].
tx
.
queue
,
&
tx_data
,
portMAX_DELAY
);
return
0
;
}
}
// Module function map
// Module function map
...
@@ -195,6 +305,7 @@ static const LUA_REG_TYPE i2s_map[] =
...
@@ -195,6 +305,7 @@ static const LUA_REG_TYPE i2s_map[] =
{
LSTRKEY
(
"stop"
),
LFUNCVAL
(
node_i2s_stop
)
},
{
LSTRKEY
(
"stop"
),
LFUNCVAL
(
node_i2s_stop
)
},
{
LSTRKEY
(
"read"
),
LFUNCVAL
(
node_i2s_read
)
},
{
LSTRKEY
(
"read"
),
LFUNCVAL
(
node_i2s_read
)
},
{
LSTRKEY
(
"write"
),
LFUNCVAL
(
node_i2s_write
)
},
{
LSTRKEY
(
"write"
),
LFUNCVAL
(
node_i2s_write
)
},
{
LSTRKEY
(
"FORMAT_I2S"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S
)
},
{
LSTRKEY
(
"FORMAT_I2S"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S
)
},
{
LSTRKEY
(
"FORMAT_I2S_MSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_MSB
)
},
{
LSTRKEY
(
"FORMAT_I2S_MSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_MSB
)
},
{
LSTRKEY
(
"FORMAT_I2S_LSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_LSB
)
},
{
LSTRKEY
(
"FORMAT_I2S_LSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_LSB
)
},
...
@@ -213,17 +324,29 @@ static const LUA_REG_TYPE i2s_map[] =
...
@@ -213,17 +324,29 @@ static const LUA_REG_TYPE i2s_map[] =
{
LSTRKEY
(
"MODE_TX"
),
LNUMVAL
(
I2S_MODE_TX
)
},
{
LSTRKEY
(
"MODE_TX"
),
LNUMVAL
(
I2S_MODE_TX
)
},
{
LSTRKEY
(
"MODE_RX"
),
LNUMVAL
(
I2S_MODE_RX
)
},
{
LSTRKEY
(
"MODE_RX"
),
LNUMVAL
(
I2S_MODE_RX
)
},
{
LSTRKEY
(
"MODE_DAC_BUILT_IN"
),
LNUMVAL
(
I2S_MODE_DAC_BUILT_IN
)
},
{
LSTRKEY
(
"MODE_DAC_BUILT_IN"
),
LNUMVAL
(
I2S_MODE_DAC_BUILT_IN
)
},
{
LSTRKEY
(
"MODE_ADC_BUILT_IN"
),
LNUMVAL
(
I2S_MODE_ADC_BUILT_IN
)
},
{
LSTRKEY
(
"MODE_PDM"
),
LNUMVAL
(
I2S_MODE_PDM
)
},
{
LSTRKEY
(
"DAC_CHANNEL_DISABLE"
),
LNUMVAL
(
I2S_DAC_CHANNEL_DISABLE
)
},
{
LSTRKEY
(
"DAC_CHANNEL_RIGHT"
),
LNUMVAL
(
I2S_DAC_CHANNEL_RIGHT_EN
)
},
{
LSTRKEY
(
"DAC_CHANNEL_LEFT"
),
LNUMVAL
(
I2S_DAC_CHANNEL_LEFT_EN
)
},
{
LSTRKEY
(
"DAC_CHANNEL_BOTH"
),
LNUMVAL
(
I2S_DAC_CHANNEL_BOTH_EN
)
},
{
LNILKEY
,
LNILVAL
}
{
LNILKEY
,
LNILVAL
}
};
};
int
luaopen_i2s
(
lua_State
*
L
)
{
int
luaopen_i2s
(
lua_State
*
L
)
{
for
(
int
i2s_id
=
0
;
i2s_id
<
MAX_I2C_NUM
;
i2s_id
++
)
{
for
(
int
i2s_id
=
0
;
i2s_id
<
MAX_I2C_NUM
;
i2s_id
++
)
{
i2s_status
[
i2s_id
].
event_queue
=
NULL
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
i2s_status
[
i2s_id
].
taskHandle
=
NULL
;
is
->
tx
.
queue
=
NULL
;
i2s_status
[
i2s_id
].
event_cb
=
LUA_NOREF
;
is
->
tx
.
taskHandle
=
NULL
;
is
->
rx
.
queue
=
NULL
;
is
->
rx
.
taskHandle
=
NULL
;
is
->
cb
=
LUA_NOREF
;
}
}
i2s_event_task_id
=
task_get_id
(
i2s_event_task
);
i2s_tx_task_id
=
task_get_id
(
i2s_tx_task
);
i2s_rx_task_id
=
task_get_id
(
i2s_rx_task
);
i2s_disposal_task_id
=
task_get_id
(
i2s_disposal_task
);
return
0
;
return
0
;
}
}
...
...
docs/en/modules/i2s.md
View file @
daa58484
# I2S Module
# I2S Module
| Since | Origin / Contributor | Maintainer | Source |
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| :----- | :-------------------- | :---------- | :------ |
| 2017-04-29 | zelll | |
[
i2s.c
](
../../../components/modules/i2s.c
)
|
| 2017-04-29 | zelll |
[
Arnim Läuger
](
https://github.com/devsaurus
)
|
[
i2s.c
](
../../../components/modules/i2s.c
)
|
The I2S module provides access to the in-built two I2S controllers.
The I2S module provides access to the in-built two I2S controllers.
!!! note "DAC mode configuration"
DACs are only available for DAC built-in mode on I2S peripheral 0.
!!! note "ADC mode configuration"
Only ADC1 is available for ADC built-in mode.
## i2s.start()
## i2s.start()
Configuration and start I2S bus.
Configuration and start I2S bus.
#### Syntax
#### Syntax
```
lua
```
lua
i2s
.
start
(
i2s_num
,
cfg
=
{
i2s
.
start
(
i2s_num
,
cfg
,
cb
)
mode
=
can
.
MODE_MASTER
+
can
.
MODE_TX
,
rate
=
44100
,
bits
=
16
,
channel
=
i2s
.
CHANNEL_RIGHT_LEFT
,
format
=
i2s
.
FORMAT_I2S
+
i2s
.
FORMAT_I2S_MSB
,
buffer_count
=
2
,
buffer_len
=
441
,
bck_pin
=
16
,
ws_pin
=
17
,
data_out_pin
=
18
,
data_in_pin
=
-
1
},
callback
)
```
```
#### Parameters
#### Parameters
-
`i2s_num`
`1`
or
`2`
-
`i2s_num`
I2S peripheral 0 or 1
-
`cfg`
configuration
-
`cfg`
table containing configuration data:
-
`mode`
combine of following constants
`i2s.MODE_MASTER`
,
`i2s.MODE_SLAVE`
,
`i2s.MODE_TX`
,
`i2s.MODE_RX`
,
`i2s.MODE_DAC_BUILT_IN`
. Default:
`i2s.MODE_MASTER + i2s.MODE_TX`
-
`mode`
I2S work mode. Optional, defaults to
`i2s.MODE_MASTER + i2s.MODE_TX`
when omitted
-
`rate`
Audio sample rate, such as
`44100`
,
`48000`
,
`16000`
,
`800`
. Default:
`44100`
-
`i2s.MODE_MASTER`
-
`bits`
`32`
,
`24`
,
`16`
or
`8`
. Default:
`16`
-
`i2s.MODE_SLAVE`
-
`channel`
One of following constants. Default:
`i2s.CHANNEL_RIGHT_LEFT`
-
`i2s.MODE_TX`
-
`i2s.MODE_RX`
-
`i2s.MODE_DAC_BUILT_IN`
-
`i2s.MODE_ADC_BUILT_IN`
-
`i2s.MODE_PDM`
-
`rate`
audio sample rate. Optional, defauls to 44100 when omitted
-
`bits`
bits per sample. Optional, defaults to 16 when omitted
-
`channel`
channel format of I2S stream. Optional, defaults to
`i2s.CHANNEL_RIGHT_LEFT`
when omitted
-
`i2s.CHANNEL_RIGHT_LEFT`
-
`i2s.CHANNEL_RIGHT_LEFT`
-
`i2s.CHANNEL_ALL_LEFT`
-
`i2s.CHANNEL_ALL_LEFT`
-
`i2s.CHANNEL_ONLY_LEFT`
-
`i2s.CHANNEL_ONLY_LEFT`
-
`i2s.CHANNEL_ALL_RIGHT`
-
`i2s.CHANNEL_ALL_RIGHT`
-
`i2s.CHANNEL_ONLY_RIGHT`
-
`i2s.CHANNEL_ONLY_RIGHT`
-
`format`
combine of following constants
`i2s.FORMAT_I2S`
,
`i2s.FORMAT_I2S_MSB`
,
`i2s.FORMAT_I2S_LSB`
,
`i2s.FORMAT_PCM`
,
`i2s.FORMAT_PCM_SHORT`
,
`i2s.FORMAT_PCM_LONG`
.
-
`format`
communicarion format. Optional, defaults to
`i2s.FORMAT_I2S + i2s.FORMAT_I2S_MSB`
when omitted
Default:
`i2s.FORMAT_I2S + i2s.FORMAT_I2S_MSB`
-
`i2s.FORMAT_I2S`
-
`buffer_count`
Buffer count. Default: 2
-
`i2s.FORMAT_I2S_MSB`
-
`buffer_len`
Size of one buffer. Default: rate/100
-
`i2s.FORMAT_I2S_LSB`
-
`bck_pin`
Clock pin. Default:
`-1`
-
`i2s.FORMAT_PCM`
-
`ws_pin`
WS pin. Default:
`-1`
-
`i2s.FORMAT_PCM_SHORT`
-
`data_out_pin`
Pin for data output. Default:
`-1`
-
`i2s.FORMAT_PCM_LONG`
-
`data_in_pin`
Pin for data input. Default:
`-1`
-
`buffer_count`
number of dma buffers. Optional, defaults to 2 when omitted
-
`callback`
function called when i2s event occurs.
-
`buffer_len`
size of one dma buffer. Optional, defaults to rate/100
-
`event`
Event type, one of
`sent`
,
`data`
,
`error`
-
`bck_pin`
clock pin, optional
-
`size`
bytes
-
`ws_pin`
WS pin, optional
-
`data_out_pin`
data output pin, optional
-
`data_in_pin`
data input pin, optional
-
`dac_mode`
DAC mode configuration. Optional, defaults to
`i2s.DAC_CHANNEL_DISABLE`
if omitted
-
`i2s.DAC_CHANNEL_DISABLE`
-
`i2s.DAC_CHANNEL_RIGHT`
-
`i2s.DAC_CHANNEL_LEFT`
-
`i2s.DAC_CHANNEL_BOTH`
-
`adc1_channel`
ADC1 channel number 0..7. Optional, defaults to off is omitted
-
`cb`
function called when transmit data is requested or received data is available
-
the function is called with parameters
`i2s_num`
and
`dir`
-
`dir`
is "tx" for TX data request. Function shall call
`i2s.write()`
.
-
`dir`
is "rx" for RX data available. Function shall call
`i2s.read()`
.
#### Returns
#### Returns
nil
`nil`
An error is thrown in case of invalid parameters or if the channel failed.
## i2s.stop()
## i2s.stop()
...
@@ -61,37 +75,40 @@ Stop I2S bus
...
@@ -61,37 +75,40 @@ Stop I2S bus
`i2s.stop(i2s_num)`
`i2s.stop(i2s_num)`
#### Parameters
#### Parameters
-
`i2s_num`
`1`
or
`2`
-
`i2s_num`
I2S peripheral 0
or
1
#### Returns
#### Returns
nil
`nil`
An error is thrown in case of invalid parameters or if the channel failed.
## i2s.read()
## i2s.read()
Read data from data-in
Read data from data-in
#### Syntax
#### Syntax
`i2s.read(
i2s_num, size[, wait_ms]
)`
`i2s.read(i2s_num, size[, wait_ms])`
#### Parameters
#### Parameters
-
`
adc
_num
ber`
Only
`adc.ADC1`
now
-
`
i2s
_num
`
I2S peripheral 0 or 1
-
`size`
Bytes to read
-
`size`
Bytes to read
-
`wait_ms`
Millisecond to wait if data is not ready.
Default:
`0`
(not to wait)
-
`wait_ms`
Millisecond to wait if data is not ready.
Optional, defaults to 0
(not to wait)
if omitted.
#### Returns
#### Returns
Data read from data-in pin. If data is not ready in
`wait_ms`
millisecond, less than
`size`
bytes can be returned.
Data read from data-in pin. If data is not ready in
`wait_ms`
millisecond, less than
`size`
bytes can be returned.
## i2s.write()
## i2s.write()
Write to I2S bus
Write to I2S bus
.
#### Syntax
#### Syntax
`i2s.write(
i2s_num,
size[, wait_ms]
)`
`i2s.write(i2s_num,
data
)`
#### Parameters
#### Parameters
-
`adc_number`
Only
`adc.ADC1`
now
-
`i2s_num`
I2S peripheral 0 or 1
-
`size`
Bytes to send
-
`data`
string containing I2S stream data
-
`wait_ms`
Millisecond to wait if DMA buffer is full. Default:
`0`
(not to wait)
#### Returns
#### Returns
Integer, bytes wrote to buffer.
`nil`
An error is thrown in case of invalid parameters or if the channel failed.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment