Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
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
Hide 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,106 +21,211 @@
...
@@ -19,106 +21,211 @@
#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
];
lua_State
*
L
=
lua_getstate
();
if
(
is
->
cb
!=
LUA_NOREF
)
{
int
event_cb
=
post
->
status
->
event_cb
;
lua_State
*
L
=
lua_getstate
();
if
(
event_cb
==
LUA_NOREF
)
{
lua_rawgeti
(
L
,
LUA_REGISTRYINDEX
,
is
->
cb
);
free
(
post
);
lua_pushinteger
(
L
,
i2s_id
);
return
;
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
);
}
}
lua_rawgeti
(
L
,
LUA_REGISTRYINDEX
,
event_cb
);
}
if
(
post
->
event
.
type
==
I2S_EVENT_TX_DONE
)
lua_pushstring
(
L
,
"sent"
);
static
void
i2s_disposal_task
(
task_param_t
param
,
task_prio_t
prio
)
{
else
if
(
post
->
event
.
type
==
I2S_EVENT_RX_DONE
)
lua_State
*
L
=
lua_getstate
();
lua_pushstring
(
L
,
"data"
);
int
ref
=
(
int
)
param
;
else
lua_pushstring
(
L
,
"error"
);
luaL_unref
(
L
,
LUA_REGISTRYINDEX
,
ref
);
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
)
{
i
2s_status_t
*
is
=
(
i2s_status_t
*
)
pvParameters
;
i
nt
i2s_id
=
(
int
)
pvParameters
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
i2s_event_t
event
;
i2s_event_t
i2s_event
;
for
(;;){
if
(
xQueueReceive
(
is
->
event_queue
,
&
event
,
3
*
portTICK_PERIOD_MS
)
==
pdTRUE
)
{
for
(;;)
{
i2s_event_post_type
*
post
=
(
i2s_event_post_type
*
)
malloc
(
sizeof
(
i2s_event_post_type
)
);
// process I2S RX events
post
->
status
=
is
;
xQueueReceive
(
is
->
rx
.
queue
,
&
i2s_event
,
portMAX_DELAY
)
;
memcpy
(
&
(
post
->
event
),
&
event
,
sizeof
(
i2s_event_t
));
if
(
i2s_event
.
type
==
I2S_EVENT_RX_DONE
)
{
task_post_high
(
i2s_
event
_task_id
,
(
task_param_t
)
post
);
task_post_high
(
i2s_
rx
_task_id
,
i2s_id
);
}
}
}
}
}
}
static
void
task_I2S_tx
(
void
*
pvParameters
)
{
int
i2s_id
=
(
int
)
pvParameters
;
i2s_status_t
*
is
=
&
i2s_status
[
i2s_id
];
i2s_tx_data_t
tx_data
;
for
(;;)
{
// request new TX data
task_post_high
(
i2s_tx_task_id
,
i2s_id
);
// 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
);
}
}
// Lua: start( i2s_id, {}, callback )
// Lua: start( i2s_id, {}, callback )
static
int
node_i2s_start
(
lua_State
*
L
)
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_settop
(
L
,
3
);
lua_getfield
(
L
,
2
,
"dac_mode"
);
i2s_status
[
i2s_id
].
event_cb
=
luaL_ref
(
L
,
LUA_REGISTRYINDEX
);
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
);
esp_err_t
err
=
i2s_driver_install
(
i2s_id
,
&
i2s_config
,
i2s_config
.
dma_buf_count
,
&
i2s_status
[
i2s_id
].
event_queue
);
// handle optional callback functions TX and RX
if
(
err
!=
ESP_OK
)
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
;
}
esp_err_t
err
;
if
(
i2s_config
.
mode
&
I2S_MODE_RX
)
{
err
=
i2s_driver_install
(
i2s_id
,
&
i2s_config
,
i2s_config
.
dma_buf_count
,
&
is
->
rx
.
queue
);
}
else
{
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,20 +235,30 @@ static int node_i2s_stop( lua_State *L )
...
@@ -128,20 +235,30 @@ 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
(
is
->
tx
.
taskHandle
!=
NULL
)
{
if
(
i2s_status
[
i2s_id
].
taskHandle
!=
NULL
)
{
vTaskDelete
(
is
->
tx
.
taskHandle
);
vTaskDelete
(
i2s_status
[
i2s_id
].
taskHandle
);
is
->
tx
.
taskHandle
=
NULL
;
i2s_status
[
i2s_id
].
taskHandle
=
NULL
;
}
}
if
(
is
->
tx
.
queue
!=
NULL
)
{
if
(
i2s_status
[
i2s_id
].
event_cb
!=
LUA_NOREF
)
{
vQueueDelete
(
is
->
tx
.
queue
);
luaL_unref
(
L
,
LUA_REGISTRYINDEX
,
i2s_status
[
i2s_id
].
event_cb
);
is
->
tx
.
queue
=
NULL
;
i2s_status
[
i2s_id
].
event_cb
=
LUA_NOREF
;
}
if
(
is
->
rx
.
taskHandle
!=
NULL
)
{
vTaskDelete
(
is
->
rx
.
taskHandle
);
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
;
}
}
...
@@ -150,80 +267,86 @@ static int node_i2s_read( lua_State *L )
...
@@ -150,80 +267,86 @@ static int node_i2s_read( 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
);
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
;
lua_pushlstring
(
L
,
data
,
read
);
//read = i2s_read_bytes(i2s_id, data, bytes, wait_ms / portTICK_RATE_MS);
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
;
char
*
data
;
if
(
lua_istable
(
L
,
2
)
)
{
bytes
=
lua_objlen
(
L
,
2
);
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
;
i2s_tx_data_t
tx_data
;
tx_data
.
data
=
(
const
char
*
)
luaL_checklstring
(
L
,
++
stack
,
&
tx_data
.
len
);
lua_pushvalue
(
L
,
stack
);
tx_data
.
ref
=
luaL_ref
(
L
,
LUA_REGISTRYINDEX
);
// 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
static
const
LUA_REG_TYPE
i2s_map
[]
=
static
const
LUA_REG_TYPE
i2s_map
[]
=
{
{
{
LSTRKEY
(
"start"
),
LFUNCVAL
(
node_i2s_start
)
},
{
LSTRKEY
(
"start"
),
LFUNCVAL
(
node_i2s_start
)
},
{
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_MSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_MSB
)
},
{
LSTRKEY
(
"FORMAT_I2S"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S
)
},
{
LSTRKEY
(
"FORMAT_I2S_LSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_LSB
)
},
{
LSTRKEY
(
"FORMAT_I2S_MSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_MSB
)
},
{
LSTRKEY
(
"FORMAT_PCM"
),
LNUMVAL
(
I2S_COMM_FORMAT_PCM
)
},
{
LSTRKEY
(
"FORMAT_I2S_LSB"
),
LNUMVAL
(
I2S_COMM_FORMAT_I2S_LSB
)
},
{
LSTRKEY
(
"FORMAT_PCM_SHORT"
),
LNUMVAL
(
I2S_COMM_FORMAT_PCM_SHORT
)
},
{
LSTRKEY
(
"FORMAT_PCM"
),
LNUMVAL
(
I2S_COMM_FORMAT_PCM
)
},
{
LSTRKEY
(
"FORMAT_PCM_SHORT"
),
LNUMVAL
(
I2S_COMM_FORMAT_PCM_SHORT
)
},
{
LSTRKEY
(
"FORMAT_PCM_LONG"
),
LNUMVAL
(
I2S_COMM_FORMAT_PCM_LONG
)
},
{
LSTRKEY
(
"FORMAT_PCM_LONG"
),
LNUMVAL
(
I2S_COMM_FORMAT_PCM_LONG
)
},
{
LSTRKEY
(
"CHANNEL_RIGHT_LEFT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_RIGHT_LEFT
)
},
{
LSTRKEY
(
"CHANNEL_RIGHT_LEFT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_RIGHT_LEFT
)
},
{
LSTRKEY
(
"CHANNEL_ALL_LEFT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ALL_LEFT
)
},
{
LSTRKEY
(
"CHANNEL_ALL_LEFT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ALL_LEFT
)
},
{
LSTRKEY
(
"CHANNEL_ONLY_LEFT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ONLY_LEFT
)
},
{
LSTRKEY
(
"CHANNEL_ONLY_LEFT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ONLY_LEFT
)
},
{
LSTRKEY
(
"CHANNEL_ALL_RIGHT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ALL_RIGHT
)
},
{
LSTRKEY
(
"CHANNEL_ALL_RIGHT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ALL_RIGHT
)
},
{
LSTRKEY
(
"CHANNEL_ONLY_RIGHT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ONLY_RIGHT
)
},
{
LSTRKEY
(
"CHANNEL_ONLY_RIGHT"
),
LNUMVAL
(
I2S_CHANNEL_FMT_ONLY_RIGHT
)
},
{
LSTRKEY
(
"MODE_MASTER"
),
LNUMVAL
(
I2S_MODE_MASTER
)
},
{
LSTRKEY
(
"MODE_MASTER"
),
LNUMVAL
(
I2S_MODE_MASTER
)
},
{
LSTRKEY
(
"MODE_SLAVE"
),
LNUMVAL
(
I2S_MODE_SLAVE
)
},
{
LSTRKEY
(
"MODE_SLAVE"
),
LNUMVAL
(
I2S_MODE_SLAVE
)
},
{
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.CHANNEL_RIGHT_LEFT`
-
`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_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