Getting closer to how I'd like to handle dictionary calls with lua.

Effectively deleted old dictionary call function/files.
Created lua_usb_vend_xfr function so lua can directly send and receive
vendor setup transfers.

Dictionary calls are more like function calls now, and all args aren't
required so the LED can be turned on for example in lua like so:
dict_pinport("LED_ON")
general format is:
dict_name( opcode, operand, misc, datastring )
Also added ability to store opcode's return length in shared dict library
files with RL=number in the comments following the opcode.
Negative numbers designate OUT transfers, positive for IN.
Default value can be determined by each dictionary's calling function.
Decided pinport is 1 for SUCCESS/ERROR CODE.
Also have default return data means with second byte giving length of
return data in bytes that follows.
dictionary call function reports any errors reported by the device and
returns any return data from the device excluding error code / data len

Now time to start implementing some of these dictionaries on the device.
This commit is contained in:
Paul Molloy 2017-08-01 17:17:13 -05:00
parent 1e5ea8cc7e
commit ec725f7e33
10 changed files with 301 additions and 72 deletions

View File

@ -717,7 +717,7 @@
#define _ADDRL(low) A76bank->ODR = (A76bank->ODR & 0xFCFF) | ((low & 0xC0)<<2);A50bank->ODR = (A50bank->ODR & 0xFF03) | ((low & 0x3F)<<2)
//clocks must be initialized, Data bus clear
#define _ADDRH(high) _DATA_OP(); _DATA_SET(high); _AHL_CLK(); _DATA_IP();
#define _ADDR(hword) ADDRL(hword); _ADDRH(hword<<8)
#define _ADDR(hword) ADDRL(hword); _ADDRH(hword>>8)
#endif //STM_ADAPTER
@ -730,6 +730,7 @@
#define _ADDRL(low) GPIOA->PORT = low
//clocks must be initialized, Data bus clear
#define _ADDRH(high) _DATA_OP(); _DATA_SET(high); _AHL_CLK(); _DATA_IP();
#define _ADDR(hword) ADDRL(hword); _ADDRH(hword>>8)
#endif //AVR_KAZZO

View File

@ -77,6 +77,16 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
//now it's the opcode's responsiblity to update these values
//rv[RETURN_DATA] start of return data
//fake some return data
rv[RETURN_ERR_IDX] = SUCCESS;
rv[RETURN_LEN_IDX] = 3;
rv[RETURN_DATA] = 0xAA;
rv[RETURN_DATA+1] = 0xDE;
rv[RETURN_DATA+2] = 0xAD;
rv[RETURN_DATA+3] = 0xBE;
rv[RETURN_DATA+4] = 0xEF;
rv[RETURN_DATA+5] = 0xCC;
/* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data
* block and return the length of the data in 'usbFunctionSetup()'. The driver
* will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The
@ -105,7 +115,7 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
switch(spacket->bRequest) {
case DICT_PINPORT:
switch (spacket->opcode) {
//Turn on LED
#ifdef STM_CORE
RCC->AHBENR |= (IOP_LED_EN);
@ -113,6 +123,10 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
// PCb_OP_EN(LEDbank, LED);
// PCb_SET_HI(LEDbank, LED);
CTL_IP_PU(LEDbank, LED);
switch (spacket->opcode) {
/*
case PP_OPCODE_ONLY_MIN ... PP_OPCODE_ONLY_MAX:
rv[RV_ERR_IDX] = pinport_opcode_only( spacket->opcode );
@ -133,9 +147,9 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
rv[RV_ERR_IDX] = pinport_opcode_8b_return( spacket->opcode, &rv[RV_DATA0_IDX]);
rlen ++;
break;
*/
default: //pinport opcode min/max definition error
rv[RETURN_ERR_IDX] = ERR_BAD_PP_OP_MINMAX;
*/
}
break; //end of PINPORT

View File

@ -20,7 +20,9 @@ function create_dict_tables( table, file )
local count = 0
local define = 0
local define_end = 0
local comment = 0
local slash = 0
local line
local comment
for line in io.lines() do
count = count + 1
--search for multiline comment opening, starting at index 1, plain search = true
@ -31,26 +33,32 @@ function create_dict_tables( table, file )
end
define, define_end = string.find( line, "#define")
if define then
comment = string.find(line, "//")
slash = string.find(line, "//")
--check for comment following define, if present cut out comment
if comment and (comment>define) then
line = string.sub(line, 1, comment-1 )
if slash and (slash>define) then
--store comment contents for later parsing
comment = string.sub(line, slash, -1)
line = string.sub(line, 1, slash-1 )
end
--check for comment prior to define, skip if present
if not (comment and (comment<define)) then
if not (slash and (slash<define)) then
--print( count, define, line)
line = string.sub(line, define_end+1, -1)
--match alpha and any trailing printable chars besides white space
--this doesn't match guarded header/footer that starts with underscore
local key = string.match( line, "%s%a%g+" )
if key then
--print ("\n\n",line)
-- print ("\n\n",line)
--key found, trim key from line
local key_start, key_end
key_start, key_end = string.find( line, key )
line = string.sub( line, key_end+1, -1)
--trim preceeding space needed to filter out underscore
key = string.match( key, "%a%g+" )
--trim any trailing underscore, trick that allows firmware to call macro with "same" macro
if( (key:sub(-1,-1)) == '_' ) then
key = key:sub(1,-2)
end
--match the number
if string.match( line, "[^%s0-9a-fxA-F]+") then
print("\n\n!!!ERROR!!!\ndictionary file #define parsing problem line:", count)
@ -62,24 +70,144 @@ function create_dict_tables( table, file )
if number then
number = string.match( number, "%s+[0-9a-fxA-F]+")
end
--print (number)
-- print (number)
--at this point we have the key and value, just convert from string
number = tonumber( number )
--print("key/val:", key, number)
--print("key type:", type(key), "value type:", type(number))
-- print("key/val:", key, number)
-- print("key type:", type(key), "value type:", type(number))
--add the key and value pair to the table
table[key] = number
--now process comment to find extra dictionary values stored in comments
-- print(comment)
if comment then
--return length "rlen" is set by RL=number (ie RL=10, RL=-0x100, etc)
--positive RL denotes endpoint IN, negative denotes endpoint OUT
--first match positive values
local rlen = string.match( comment, "%s*RL%s*=%s*[0-9a-fA-Fx]+")
if (rlen) then
--trim RL= portion
rlen = string.match( rlen, "[0-9a-fA-Fx]+")
rlen = tonumber( rlen )
--add return length to table
table[key.."rlen"] = rlen;
end
--next check for negative values
rlen = string.match( comment, "%s*RL%s*=%s*-%s*[0-9a-fA-Fx]+")
if (rlen) then
--trim RL=- portion
rlen = string.match( rlen, "[0-9a-fA-Fx]+")
rlen = - tonumber( rlen )
--add return length to table
table[key.."rlen"] = rlen;
end
end
-- print(key, ": val/rlen:", table[key], table[key.."rlen"], "\n\n")
end
end
end
end
end
--determine endpoint & wLength for usb transfer
--default is ep=IN, rlen=1 if different than those values it must be defined in dictionary
--positive values are associated with ep IN, negative ep OUT
function default_rlen_1_in( rlen )
local ep
if rlen then
--RL defined in dictionary
if rlen < 1 then
ep = USB_OUT
rlen = -rlen
else
ep = USB_IN
end
else --RL not defined, assume default
ep = USB_IN
rlen = 1
end
return rlen, ep
end
function string_to_int( string, numbytes)
local i = 0
local rv = 0
while i < numbytes do
rv = rv | (string:byte(i+1) << 8*i)
i = i+1
end
return rv
end
RETURN_ERR_IDX = 1
RETURN_LEN_IDX = 2
RETURN_DATA = 3
function dict_pinport( opcode, operand, misc, data )
if not operand then operand = 0 end
if not misc then misc = 0 end
local wLength, ep = default_rlen_1_in(op_pinport[opcode.."rlen"])
local count
count, data = usb_vend_xfr(
-- ep, dictionary wValue[misc:opcode] wIndex wLength data
ep, dict["DICT_PINPORT"], ( misc<<8 | op_pinport[opcode]), operand, wLength, data)
--print(count)
local error_code = data:byte(RETURN_ERR_IDX)
local data_len = data:byte(RETURN_LEN_IDX)
--print("error:", error_code, "data_len:", data_len)
if error_code ~= err_codes["SUCCESS"] then
print("ERROR!!! device error code:", error_code)
end
if data_len and data_len ~= (wLength - RETURN_LEN_IDX) then
print("WARNING!! Device's return data length:", data_len, "did not match expected:", wLength-RETURN_LEN_IDX)
end
--process the return data string and return it to calling function
if data_len then
return string_to_int( data:sub(RETURN_DATA, data_len+RETURN_DATA), data_len)
else
return nil
end
end
-- initial function called from C main
function main ()
--check that dictionary files were found and parsed
--print(op_buffer)
--if not ( dict and op_pinport and op_buffer and op_io and op_operation and op_nes and op_snes ) then
-- print("ERROR: couldn't find/parse dictionary files in shared folder!")
--end
-- print dictionary opcode addr miscdata endpt buffer length
print("dict_call ", dict_call( 1, dict["DICT_PINPORT"], op_pinport["LED_OFF"], 0, 0, USB_IN, nil, 8), "\n")
--print("dict_call ", dict_call( 1, dict["DICT_PINPORT"], op_pinport["LED_OFF"], 0, 0, USB_IN, nil, 8), "\n")
--
print("return len", op_pinport["LED_ONrlen"])
local rv = dict_pinport( "LED_ON" )
if rv then
print(string.format("%X", rv))
end
--[[{i=0
while ( i < 8192 ) do
usb_vend_xfr( USB_IN, dict["DICT_PINPORT"], op_pinport["LED_ON"], 0, 128, "wowdata!!!!")
i = i+1
end
--]]
end
-- Dictionary table definitions
@ -90,7 +218,9 @@ op_io = {}
op_operation = {}
op_nes = {}
op_snes = {}
err_codes = {}
-- Dictionary table definitions created by calling parser
-- call functions desired to run when script is called
create_dict_tables( dict, "../shared/shared_dictionaries.h")
create_dict_tables( op_pinport, "../shared/shared_dict_pinport.h")
@ -99,6 +229,7 @@ create_dict_tables( op_io, "../shared/shared_dict_io.h")
create_dict_tables( op_operation, "../shared/shared_dict_operation.h")
create_dict_tables( op_nes, "../shared/shared_dict_nes.h")
create_dict_tables( op_snes, "../shared/shared_dict_snes.h")
create_dict_tables( err_codes, "../shared/shared_errors.h")
main ()

View File

@ -14,7 +14,7 @@
//#include "shared_dictionaries.h"
#include "usb_operations.h"
#include "dictionary.h"
//#include "dictionary.h"
//#include "write_operations.h"
//#include "erase.h"
//#include "test.h"
@ -194,8 +194,9 @@ int main(int argc, char *argv[])
luaL_openlibs(L); //opens the standard libraries
//register C functions that can be called from Lua
lua_pushcfunction(L, lua_dictionary_call);
lua_setglobal(L, "dict_call");
// lua_pushcfunction(L, lua_dictionary_call);
lua_pushcfunction(L, lua_usb_vend_xfr);
lua_setglobal(L, "usb_vend_xfr");
/*
//flags about input files only used for writes
@ -253,7 +254,7 @@ int main(int argc, char *argv[])
//provide dictionary.c with pointer to transfer so it can update it's local pointer
init_dictionary( transfer );
//init_dictionary( transfer );
//usb device is open, pass args and control over to lua
if (s_value) {

View File

@ -1,5 +1,7 @@
#include "usb_operations.h"
static libusb_device_handle *lua_usb_handle = NULL;
//control transfer request types
//uint8_t libusb_control_setup::bmRequestType
//Request type.
@ -183,6 +185,10 @@ libusb_device_handle * open_usb_device( libusb_context *context, int log_level )
}
if (log_level>0) printf("Returning device handle to main\n");
//set this module's pointer to handle so it can be referenced by lua
lua_usb_handle = handle;
return handle;
error:
@ -247,7 +253,7 @@ void close_usb(libusb_context *context, libusb_device_handle *handle)
* ERROR if unable to transfer USBtransfer's wLength number of bytes
* prints libusb_error if there was usb problem
*/
int usb_transfer( USBtransfer *transfer )
int usb_vendor_transfer( USBtransfer *transfer )
{
check( transfer->wLength <= MAX_VUSB, "Can't transfer more than %d bytes!", MAX_VUSB);
//check( transfer->wLength <= MAX_VUSB_LONGXFR, "Can't transfer more than %d bytes!", MAX_VUSB_LONGXFR);
@ -263,13 +269,13 @@ int usb_transfer( USBtransfer *transfer )
//but all avr operations should have a return value success/error code
//one way to control whether those retrun values are read back is endpoint direction
uint16_t wValue = transfer->wValueMSB;
wValue = wValue << 8;
wValue |= transfer->wValueLSB;
uint16_t wValue = transfer->wValue;
// wValue = wValue << 8;
// wValue |= transfer->wValueLSB;
uint16_t wIndex = transfer->wIndexMSB;
wIndex = wIndex << 8;
wIndex |= transfer->wIndexLSB;
uint16_t wIndex = transfer->wIndex;
// wIndex = wIndex << 8;
// wIndex |= transfer->wIndexLSB;
debug("reqtype h: %x \n", ( LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | transfer->endpoint));
debug("request h: %x d: %d", transfer->request, transfer->request);
@ -304,3 +310,80 @@ int usb_transfer( USBtransfer *transfer )
error:
return -1;
}
// initialize usb transfer based on args passed in from lua and transfer setup packet over USB
int lua_usb_vend_xfr (lua_State *L) {
/*
typedef struct USBtransfer {
libusb_device_handle *handle;
uint8_t endpoint;
uint8_t request;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
unsigned char *data;
} USBtransfer;
*/
uint8_t data_buff[MAX_VUSB];
int i;
const char *lua_out_string;
int xfr_count = 0; //return count
int rv = 0; //number of return values
USBtransfer usb_xfr;
usb_xfr.handle = lua_usb_handle;
usb_xfr.endpoint = luaL_checknumber(L, 1); /* get endpoint argument */
usb_xfr.request = luaL_checknumber(L, 2); /* get request argument */
usb_xfr.wValue = luaL_checknumber(L, 3); /* get wValue argument */
usb_xfr.wIndex = luaL_checknumber(L, 4); /* get wIndex argument */
usb_xfr.wLength = luaL_checknumber(L, 5); /* get wLength argument */
check( (usb_xfr.wLength <= MAX_VUSB), "Can't transfer more than %d bytes!", MAX_VUSB);
if ( usb_xfr.endpoint == LIBUSB_ENDPOINT_OUT ) {
//OUT transfer sending data to device
lua_out_string = luaL_checkstring(L, 6); /* get data argument */
//2 rules for lua strings in C: don't pop it, and don't modify it!!!
//copy lua string over to data buffer
for( i=0; i<usb_xfr.wLength; i++) {
data_buff[i] = lua_out_string[i];
}
} else {
//IN transfer, zero out buffer
for( i=0; i<MAX_VUSB; i++) {
data_buff[i] = 0;
}
}
usb_xfr.data = data_buff;
printf("ep %d, req %d\n", usb_xfr.endpoint, usb_xfr.request);
printf("wValue %d, wIndex %d\n", usb_xfr.wValue, usb_xfr.wIndex);
printf("wLength %d, \n", usb_xfr.wLength);
printf("predata: %d, %d, %d, %d, %d, %d \n", usb_xfr.data[0], usb_xfr.data[1],usb_xfr.data[2],usb_xfr.data[3],usb_xfr.data[4],usb_xfr.data[5]);
check( lua_usb_handle != NULL, "usb device handle pointer not initialized.\n")
xfr_count = usb_vendor_transfer( &usb_xfr);
printf("postdata: %d, %d, %d, %d, %d, %d \n", usb_xfr.data[0], usb_xfr.data[1],usb_xfr.data[2],usb_xfr.data[3],usb_xfr.data[4],usb_xfr.data[5]);
printf("bytes xfrd: %d\n", xfr_count);
lua_pushnumber(L, xfr_count); /* push first result */
rv++;
if ( usb_xfr.endpoint == LIBUSB_ENDPOINT_IN ) {
//push second result if data was read from device
lua_pushlstring(L,(const char*) data_buff, xfr_count);
rv++;
}
return rv; /* number of results */
error:
printf("lua USB transfer went to error\n");
lua_pushstring(L, "ERROR"); /* push result */
return 1;
}

View File

@ -8,6 +8,10 @@
#include <errno.h>
#include <libusb.h>
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "lua/lualib.h"
//list of included dictionaries for defining request, wValue, and wIndex fields
#include "shared_dictionaries.h"
@ -89,10 +93,8 @@ typedef struct USBtransfer {
libusb_device_handle *handle;
uint8_t endpoint;
uint8_t request;
uint8_t wValueMSB;
uint8_t wValueLSB;
uint8_t wIndexMSB;
uint8_t wIndexLSB;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
unsigned char *data;
} USBtransfer;
@ -142,6 +144,7 @@ void close_usb(libusb_context *context, libusb_device_handle *handle);
// LIBUSB_ERROR_PIPE if the control request was not supported by the device
// LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
// another LIBUSB_ERROR code on other failures
int usb_transfer( USBtransfer *transfer );
int usb_vendor_transfer( USBtransfer *transfer );
int lua_usb_vend_xfr(lua_State *L);
#endif

View File

@ -157,8 +157,8 @@
#define LED_IP 65
#define LED_OP 66
#define LED_OFF 67
#define LED_ON 68
#define LED_OFF 67 // test outRL = 6whee!
#define LED_ON 68 // test outRL = 5whee!
#define IRQ_IP 69
#define IRQ_OP 70

View File

@ -4,10 +4,8 @@
#define SUCCESS 0
#define GEN_FAIL 0xFF
/*
#define FALSE 0
#define NILL 0
*/
//#define FALSE 0
//#define NILL 0
//greater than 128 are possible avr return codes
#define ERR_UNKN_DICTIONARY 128
@ -20,43 +18,41 @@
#define ERR_BAD_OPER_OP_MINMAX 135
#define ERR_UNKN_PP_OPCODE_ONLY 140
#define ERR_UNKN_PP_OPCODE_8BOP 141
#define ERR_UNKN_PP_OPCODE_16BOP 142
#define ERR_UNKN_PP_OPCODE_24BOP 143
#define ERR_UNKN_PP_OPCODE_8BRV 144
//#define ERR_UNKN_PP_OPCODE_ONLY 140
//#define ERR_UNKN_PP_OPCODE_8BOP 141
//#define ERR_UNKN_PP_OPCODE_16BOP 142
//#define ERR_UNKN_PP_OPCODE_24BOP 143
//#define ERR_UNKN_PP_OPCODE_8BRV 144
//
//#define ERR_UNKN_IO_OPCODE_ONLY 150
//#define ERR_UNKN_IO_OPCODE_RTN 151
//
//#define ERR_UNKN_NES_OPCODE_24BOP 160
//#define ERR_UNKN_NES_OPCODE_16BOP_8BRV 161
//
////reserved libusb erro 165
//
//#define ERR_UNKN_SNES_OPCODE_24BOP 170
//#define ERR_UNKN_SNES_OPCODE_24BOP_8BRV 171
//
//#define ERR_UNKN_BUFF_OPCODE_NRV 180
//#define ERR_UNKN_BUFF_OPCODE_RV 181
//#define ERR_UNKN_BUFF_OPCODE_BUFN_NRV 182
//
//#define ERR_BUFF_ALLOC_RANGE 190
//#define ERR_BUFF_STATUS_ALREADY_ALLOC 191
//#define ERR_BUFF_ID_ALREADY_ALLOC 192
//#define ERR_BUFF_RAW_ALREADY_ALLOC 193
//#define ERR_BUFF_ALLOC_SIZE_ZERO 194
//#define ERR_BUFF_UNSUP_MEM_TYPE 195
//
//#define ERR_OUT_CURLDBUF_STATUS 200
//#define ERR_OUT_CURLDBUF_TO_SMALL 201
//
//#define ERR_UNKN_OPER_OPCODE_NRV 210
//#define ERR_UNKN_OPER_OPCODE_RV 211
//
////max error number 255
/*
#define ERR_UNKN_IO_OPCODE_ONLY 150
#define ERR_UNKN_IO_OPCODE_RTN 151
#define ERR_UNKN_NES_OPCODE_24BOP 160
#define ERR_UNKN_NES_OPCODE_16BOP_8BRV 161
//reserved libusb erro 165
#define ERR_UNKN_SNES_OPCODE_24BOP 170
#define ERR_UNKN_SNES_OPCODE_24BOP_8BRV 171
#define ERR_UNKN_BUFF_OPCODE_NRV 180
#define ERR_UNKN_BUFF_OPCODE_RV 181
#define ERR_UNKN_BUFF_OPCODE_BUFN_NRV 182
#define ERR_BUFF_ALLOC_RANGE 190
#define ERR_BUFF_STATUS_ALREADY_ALLOC 191
#define ERR_BUFF_ID_ALREADY_ALLOC 192
#define ERR_BUFF_RAW_ALREADY_ALLOC 193
#define ERR_BUFF_ALLOC_SIZE_ZERO 194
#define ERR_BUFF_UNSUP_MEM_TYPE 195
#define ERR_OUT_CURLDBUF_STATUS 200
#define ERR_OUT_CURLDBUF_TO_SMALL 201
#define ERR_UNKN_OPER_OPCODE_NRV 210
#define ERR_UNKN_OPER_OPCODE_RV 211
//max error number 255
*/
#endif