169 lines
4.1 KiB
C
169 lines
4.1 KiB
C
|
// Module for interfacing with adc hardware
|
||
|
|
||
|
#include "module.h"
|
||
|
#include "lauxlib.h"
|
||
|
#include "platform.h"
|
||
|
|
||
|
#include "CAN.h"
|
||
|
|
||
|
#include "freertos/FreeRTOS.h"
|
||
|
#include "freertos/task.h"
|
||
|
#include "freertos/queue.h"
|
||
|
#include "esp_task.h"
|
||
|
#include "esp_log.h"
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "task/task.h"
|
||
|
|
||
|
CAN_device_t CAN_cfg = {
|
||
|
.speed = CAN_SPEED_1000KBPS, // CAN Node baudrade
|
||
|
.tx_pin_id = -1, // CAN TX pin
|
||
|
.rx_pin_id = -1, // CAN RX pin
|
||
|
.rx_queue = NULL, // FreeRTOS queue for RX frames
|
||
|
.code = 0,
|
||
|
.mask = 0xffffffff,
|
||
|
.dual_filter = false
|
||
|
};
|
||
|
|
||
|
static task_handle_t can_data_task_id;
|
||
|
static int can_on_received = LUA_NOREF;
|
||
|
|
||
|
static xTaskHandle xCanTaskHandle = NULL;
|
||
|
|
||
|
// LUA
|
||
|
static void can_data_task( task_param_t param, task_prio_t prio ) {
|
||
|
CAN_frame_t *frame = (CAN_frame_t *)param;
|
||
|
|
||
|
if(can_on_received == LUA_NOREF) {
|
||
|
free( frame );
|
||
|
return;
|
||
|
}
|
||
|
lua_State *L = lua_getstate();
|
||
|
|
||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, can_on_received);
|
||
|
lua_pushinteger(L, frame->Extended? 1 : 0);
|
||
|
lua_pushinteger(L, frame->MsgID);
|
||
|
lua_pushlstring(L, (char *)frame->data.u8, frame->DLC);
|
||
|
free( frame );
|
||
|
lua_call(L, 3, 0);
|
||
|
}
|
||
|
|
||
|
// RTOS
|
||
|
static void task_CAN( void *pvParameters ){
|
||
|
(void)pvParameters;
|
||
|
|
||
|
//frame buffer
|
||
|
CAN_frame_t frame;
|
||
|
|
||
|
//create CAN RX Queue
|
||
|
CAN_cfg.rx_queue = xQueueCreate(10, sizeof(CAN_frame_t));
|
||
|
|
||
|
//start CAN Module
|
||
|
CAN_init();
|
||
|
|
||
|
for (;;){
|
||
|
//receive next CAN frame from queue
|
||
|
if( xQueueReceive( CAN_cfg.rx_queue, &frame, 3 * portTICK_PERIOD_MS ) == pdTRUE ){
|
||
|
CAN_frame_t *postFrame = (CAN_frame_t *)malloc( sizeof( CAN_frame_t ) );
|
||
|
memcpy(postFrame, &frame, sizeof( CAN_frame_t ));
|
||
|
task_post_medium( can_data_task_id, (task_param_t)postFrame );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Lua: setup( {}, callback )
|
||
|
static int can_setup( lua_State *L )
|
||
|
{
|
||
|
if(xCanTaskHandle != NULL)
|
||
|
luaL_error( L, "Stop CAN before setup" );
|
||
|
luaL_checkanytable (L, 1);
|
||
|
|
||
|
luaL_checkanyfunction (L, 2);
|
||
|
lua_settop (L, 2);
|
||
|
if(can_on_received != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, can_on_received);
|
||
|
can_on_received = luaL_ref(L, LUA_REGISTRYINDEX);
|
||
|
|
||
|
lua_getfield (L, 1, "speed");
|
||
|
CAN_cfg.speed = luaL_checkint(L, -1);
|
||
|
lua_getfield (L, 1, "tx");
|
||
|
CAN_cfg.tx_pin_id = luaL_checkint(L, -1);
|
||
|
lua_getfield (L, 1, "rx");
|
||
|
CAN_cfg.rx_pin_id = luaL_checkint(L, -1);
|
||
|
lua_getfield (L, 1, "dual_filter");
|
||
|
CAN_cfg.dual_filter = lua_toboolean(L, 0);
|
||
|
lua_getfield (L, 1, "code");
|
||
|
CAN_cfg.code = (uint32_t)luaL_optnumber(L, -1, 0);
|
||
|
lua_getfield (L, 1, "mask");
|
||
|
CAN_cfg.mask = (uint32_t)luaL_optnumber(L, -1, 0x0ffffffff);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int can_start( lua_State *L )
|
||
|
{
|
||
|
if(xCanTaskHandle != NULL)
|
||
|
luaL_error( L, "CAN started" );
|
||
|
xTaskCreate(task_CAN, "CAN", 2048, NULL, ESP_TASK_MAIN_PRIO + 1, &xCanTaskHandle);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int can_stop( lua_State *L )
|
||
|
{
|
||
|
if(xCanTaskHandle) {
|
||
|
vTaskDelete(xCanTaskHandle);
|
||
|
xCanTaskHandle = NULL;
|
||
|
}
|
||
|
CAN_stop();
|
||
|
if(CAN_cfg.rx_queue) {
|
||
|
vQueueDelete( CAN_cfg.rx_queue );
|
||
|
CAN_cfg.rx_queue = NULL;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int can_send( lua_State *L )
|
||
|
{
|
||
|
uint32_t format = (uint8_t)luaL_checkinteger( L, 1 );
|
||
|
uint32_t msg_id = luaL_checkinteger( L, 2 );
|
||
|
size_t len;
|
||
|
const char *data = luaL_checklstring( L, 3, &len );
|
||
|
uint8_t i;
|
||
|
CAN_frame_t frame;
|
||
|
|
||
|
if(xCanTaskHandle == NULL)
|
||
|
luaL_error( L, "CAN not started" );
|
||
|
|
||
|
if(len > 8)
|
||
|
luaL_error( L, "CAN can not send more than 8 bytes" );
|
||
|
|
||
|
frame.Extended = format? 1 : 0;
|
||
|
frame.MsgID = msg_id;
|
||
|
frame.DLC = len;
|
||
|
|
||
|
for(i = 0; i < len; i++)
|
||
|
frame.data.u8[i] = data[i];
|
||
|
|
||
|
CAN_write_frame(&frame);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Module function map
|
||
|
static const LUA_REG_TYPE can_map[] =
|
||
|
{
|
||
|
{ LSTRKEY( "setup" ), LFUNCVAL( can_setup ) },
|
||
|
{ LSTRKEY( "start" ), LFUNCVAL( can_start ) },
|
||
|
{ LSTRKEY( "stop" ), LFUNCVAL( can_stop ) },
|
||
|
{ LSTRKEY( "send" ), LFUNCVAL( can_send ) },
|
||
|
{ LSTRKEY( "STANDARD_FRAME" ), LNUMVAL( 0 ) },
|
||
|
{ LSTRKEY( "EXTENDED_FRAME" ), LNUMVAL( 1 ) },
|
||
|
{ LNILKEY, LNILVAL }
|
||
|
};
|
||
|
|
||
|
int luaopen_can( lua_State *L ) {
|
||
|
can_data_task_id = task_get_id( can_data_task ); // reset CAN after sw reset
|
||
|
CAN_stop();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
NODEMCU_MODULE(CAN, "can", can_map, luaopen_can);
|