|
@@ -0,0 +1,459 @@
|
|
|
|
|
+--本文件中的主机是指I2C主机,具体指Air8000
|
|
|
|
|
+--本文件中的从机是指I2C从机,具体指AirGPIO_1000配件板上的IO扩展芯片
|
|
|
|
|
+
|
|
|
|
|
+local AirGPIO_1000 =
|
|
|
|
|
+{
|
|
|
|
|
+ -- i2c_id:主机的i2c id;
|
|
|
|
|
+ -- gpio_int_id:主机的GPIO中断引脚id;
|
|
|
|
|
+ -- slave_address:从机地址;
|
|
|
|
|
+ -- ints = --从机各个扩展IO配置为中断时的处理函数以及上一次的输入电平
|
|
|
|
|
+ -- {
|
|
|
|
|
+ -- [0x00] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x01] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x02] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x03] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x04] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x05] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x06] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x07] = {cb_func=, old_level=},
|
|
|
|
|
+
|
|
|
|
|
+ -- [0x10] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x11] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x12] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x13] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x14] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x15] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x16] = {cb_func=, old_level=},
|
|
|
|
|
+ -- [0x17] = {cb_func=, old_level=},
|
|
|
|
|
+ -- }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+-- 从机硬件上有三个引脚A0 A1 A2可以配置I2C从设备的地址
|
|
|
|
|
+-- 当A0 A1 A2都接地时的从设备基地址为(0x40 >> 1)
|
|
|
|
|
+-- A0 A1 A2有0到7一共八种排序组合,基地址+0/1/2/3/4/5/6/7即为八种从设备的地址
|
|
|
|
|
+-- AirGPIO_1000默认A0 A1 A2都接地,所以AirGPIO_1000的从设备地址默认也为(0x40 >> 1)
|
|
|
|
|
+local SALVE_ADDRESS_HIGH_4BIT = (0x40 >> 1)
|
|
|
|
|
+
|
|
|
|
|
+-- 寄存器地址
|
|
|
|
|
+local REG_INPUT_PORT_0 = 0x00 -- 输入端口0
|
|
|
|
|
+local REG_INPUT_PORT_1 = 0x01 -- 输入端口1
|
|
|
|
|
+local REG_OUTPUT_PORT_0 = 0x02 -- 输出端口0
|
|
|
|
|
+local REG_OUTPUT_PORT_1 = 0x03 -- 输出端口1
|
|
|
|
|
+local REG_POL_INV_0 = 0x04 -- 极性反转端口0
|
|
|
|
|
+local REG_POL_INV_1 = 0x05 -- 极性反转端口1
|
|
|
|
|
+local REG_CONFIG_0 = 0x06 -- 配置端口0
|
|
|
|
|
+local REG_CONFIG_1 = 0x07 -- 配置端口1
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+-- 写入AirGPIO_1000的寄存器
|
|
|
|
|
+
|
|
|
|
|
+--reg:number类型;
|
|
|
|
|
+-- 表示AirGPIO_1000上的寄存器地址;
|
|
|
|
|
+-- 取值范围:0x00到0x07,参考本文件上方的寄存器地址列表;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--value:number类型;
|
|
|
|
|
+-- 表示要写入到AirGPIO_1000寄存器中的数据;
|
|
|
|
|
+-- 取值范围:0x00到0xFF,1个字节的长度;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:成功返回true,失败返回false
|
|
|
|
|
+local function write_register(reg, value)
|
|
|
|
|
+ local data = {reg, value}
|
|
|
|
|
+ local result = i2c.send(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, data)
|
|
|
|
|
+ return result
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+-- 读取AirGPIO_1000的寄存器
|
|
|
|
|
+
|
|
|
|
|
+--reg:number类型;
|
|
|
|
|
+-- 表示AirGPIO_1000上的寄存器地址;
|
|
|
|
|
+-- 取值范围:0x00到0x07,参考本文件上方的寄存器地址列表;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:成功返回1个字节的number类型,失败返回nil
|
|
|
|
|
+local function read_register(reg)
|
|
|
|
|
+ i2c.send(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, reg)
|
|
|
|
|
+ local data = i2c.recv(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, 1)
|
|
|
|
|
+ if data and #data == 1 then
|
|
|
|
|
+ return string.byte(data, 1)
|
|
|
|
|
+ end
|
|
|
|
|
+ return nil
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+--主机上的中断引脚处理函数
|
|
|
|
|
+local function gpio_int_callback()
|
|
|
|
|
+ log.info("gpio_int_callback")
|
|
|
|
|
+ --在中断处理函数中不能直接执行耗时较长的动作
|
|
|
|
|
+ --所以在此处publish一个"AirGPIO_1000_INT"消息
|
|
|
|
|
+ --在其他位置订阅这个消息,进行异步处理
|
|
|
|
|
+ --异步处理这个消息的函数可以直接执行耗时较长的动作
|
|
|
|
|
+ sys.publish("AirGPIO_1000_INT")
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+--遍历用户扩展GPIO中断函数表,进行处理
|
|
|
|
|
+local function user_gpio_int_callback()
|
|
|
|
|
+ if AirGPIO_1000.ints then
|
|
|
|
|
+ --遍历用户扩展GPIO中断函数表
|
|
|
|
|
+ for k,v in pairs(AirGPIO_1000.ints) do
|
|
|
|
|
+ if v then
|
|
|
|
|
+ --读取扩展GPIO的输入电平
|
|
|
|
|
+ local cur_level = AirGPIO_1000.get(k)
|
|
|
|
|
+ --如果输入电平和上一次输入电平不一致
|
|
|
|
|
+ --则执行用户扩展GPIO中断函数
|
|
|
|
|
+ if v.old_level~=cur_level then
|
|
|
|
|
+ v.old_level = cur_level
|
|
|
|
|
+ if v.cb_func then v.cb_func(k, cur_level) end
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+--订阅"AirGPIO_1000_INT"消息的处理函数user_gpio_int_callback
|
|
|
|
|
+--当其他位置publish "AirGPIO_1000_INT"消息时,会执行user_gpio_int_callback
|
|
|
|
|
+sys.subscribe("AirGPIO_1000_INT", user_gpio_int_callback)
|
|
|
|
|
+
|
|
|
|
|
+--检查AirGPIO_1000上的扩展GPIO ID是否有效
|
|
|
|
|
+
|
|
|
|
|
+--gpio_id:number类型;
|
|
|
|
|
+-- 表示AirGPIO_1000上的扩展GPIO ID;
|
|
|
|
|
+-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:有效返回true,无效返回false
|
|
|
|
|
+local function check_gpio_id_valid(gpio_id)
|
|
|
|
|
+ return (gpio_id>=0x00 and gpio_id<=0x07 or gpio_id>=0x10 and gpio_id<=0x17)
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+--配置主机和AirGPIO_1000之间的通信参数;
|
|
|
|
|
+
|
|
|
|
|
+--i2c_id:number类型;
|
|
|
|
|
+-- 主机使用的I2C ID,用来控制AirGPIO_1000;
|
|
|
|
|
+-- 取值范围:仅支持0和1;
|
|
|
|
|
+-- 如果没有传入此参数,则默认为0;
|
|
|
|
|
+--int_id:number类型;
|
|
|
|
|
+-- 主机使用的中断引脚GPIO ID,和AirGPIO_1000上的INT引脚相连;
|
|
|
|
|
+-- AirGPIO_1000可以扩展出来16个GPIO,这些GPIO支持配置为输入;
|
|
|
|
|
+-- AirGPIO_1000上的任意一个输入GPIO的状态发生上升沿或者下降沿变化时,会通过INT引脚通知到主机的int_id中断引脚;
|
|
|
|
|
+-- 此时主机可以通过I2C接口立即读取AirGPIO_1000上配置为输入模式的扩展GPIO的电平状态,从而判断是哪些扩展GPIO的输入电平发生了变化;
|
|
|
|
|
+-- 取值范围:nil或者空,或者0到9,或者12到55,注意不要使用已经复用为其他功能的引脚;nil或者空时,表示不使用中断通知功能;
|
|
|
|
|
+-- 如果没有传入此参数,则默认为空,表示不使用中断通知功能;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:成功返回true,失败返回false
|
|
|
|
|
+function AirGPIO_1000.init(i2c_id, gpio_int_id)
|
|
|
|
|
+ --检查参数的合法性
|
|
|
|
|
+ if not (i2c_id == 0 or i2c_id == 1) then
|
|
|
|
|
+ log.error("AirGPIO_1000.init", "invalid i2c_id", i2c_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ if not (gpio_int_id==nil or gpio_int_id>=0 and gpio_int_id<=9 or gpio_int_id>=12 and gpio_int_id<=55) then
|
|
|
|
|
+ log.error("AirGPIO_1000.init", "invalid gpio_int_id", gpio_int_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ AirGPIO_1000.i2c_id = i2c_id
|
|
|
|
|
+ AirGPIO_1000.gpio_int_id = gpio_int_id
|
|
|
|
|
+
|
|
|
|
|
+ --初始化I2C
|
|
|
|
|
+ if i2c.setup(i2c_id, i2c.FAST) ~= 1 then
|
|
|
|
|
+ log.error("AirGPIO_1000.init", "i2c.setup error", i2c_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --自动识别从设备地址
|
|
|
|
|
+ --AirGPIO_1000上使用的TCA9555芯片有三个引脚,A2 A1 A0,可以配置三个bit的I2C从设备地址
|
|
|
|
|
+ --从 0 0 0 到 1 1 1,也就是十进制的0到7,一共可以配置8种;
|
|
|
|
|
+ --依次读取这8个从设备地址上的一个寄存器地址数据
|
|
|
|
|
+ --如果返回应答数据,则从设备地址自动识别成功
|
|
|
|
|
+ for i=0,7 do
|
|
|
|
|
+ i2c.send(i2c_id, SALVE_ADDRESS_HIGH_4BIT+i, REG_INPUT_PORT_0)
|
|
|
|
|
+ local data = i2c.recv(i2c_id, SALVE_ADDRESS_HIGH_4BIT+i, 1)
|
|
|
|
|
+ if data~=nil then
|
|
|
|
|
+ AirGPIO_1000.slave_address = SALVE_ADDRESS_HIGH_4BIT+i
|
|
|
|
|
+ log.error("AirGPIO_1000.init", "slave_address", SALVE_ADDRESS_HIGH_4BIT+i, data:byte())
|
|
|
|
|
+ break
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --自动识别从设备地址失败
|
|
|
|
|
+ if not AirGPIO_1000.slave_address then
|
|
|
|
|
+ log.error("AirGPIO_1000.init", "slave_address unknown")
|
|
|
|
|
+ i2c.close(i2c_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ --配置主机上的中断GPIO,用来实时检测从机上扩展GPIO的输入电平变化
|
|
|
|
|
+ if gpio_int_id then
|
|
|
|
|
+ gpio.setup(gpio_int_id, gpio_int_callback, gpio.PULLUP, gpio.FALLING)
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ return true
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+--关闭主机和AirGPIO_1000之间的通信;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:成功返回true,失败返回false
|
|
|
|
|
+function AirGPIO_1000.deinit()
|
|
|
|
|
+ --关闭主机I2C
|
|
|
|
|
+ if AirGPIO_1000.i2c_id then
|
|
|
|
|
+ i2c.close(AirGPIO_1000.i2c_id)
|
|
|
|
|
+ AirGPIO_1000.i2c_id = nil
|
|
|
|
|
+ AirGPIO_1000.slave_address = nil
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --关闭主机中断GPIO
|
|
|
|
|
+ if AirGPIO_1000.gpio_int_id then
|
|
|
|
|
+ gpio.close(AirGPIO_1000.gpio_int_id)
|
|
|
|
|
+ AirGPIO_1000.gpio_int_id = nil
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --清空用户注册的扩展GPIO中断处理表
|
|
|
|
|
+ if type(AirGPIO_1000.ints)=="table" then
|
|
|
|
|
+ for k,v in pairs(AirGPIO_1000.ints) do
|
|
|
|
|
+ AirGPIO_1000.ints[k] = nil
|
|
|
|
|
+ end
|
|
|
|
|
+ AirGPIO_1000.ints = nil
|
|
|
|
|
+ end
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+--[[
|
|
|
|
|
+配置AirGPIO_1000上的扩展GPIO管脚功能;
|
|
|
|
|
+支持配置为输出,输入和中断三种模式;
|
|
|
|
|
+
|
|
|
|
|
+@api AirGPIO_1000.setup(gpio_id, gpio_mode)
|
|
|
|
|
+
|
|
|
|
|
+@number
|
|
|
|
|
+gpio_id
|
|
|
|
|
+表示AirGPIO_1000上的扩展GPIO ID;
|
|
|
|
|
+取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
|
|
|
|
|
+必须传入,不允许为空或者nil;
|
|
|
|
|
+
|
|
|
|
|
+@number or function or nil or 空
|
|
|
|
|
+gpio_mode
|
|
|
|
|
+number类型时,表示输出模式,取值范围为0和1,0表示默认输出低电平,1表示默认输出高电平;
|
|
|
|
|
+nil或者空类型时,表示输入模式;
|
|
|
|
|
+function类型时,表示中断模式,此function为中断回调函数,函数的定义格式如下:
|
|
|
|
|
+function cb_func(id, level)
|
|
|
|
|
+ --id:表示触发中断的AirGPIO_1000上的扩展GPIO ID,取值范围为0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
|
|
|
|
|
+ --level:触发中断后,某一时刻,扩展GPIO输入的电平状态,高电平为1, 低电平为0;并不是指触发中断的电平状态;
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+@return bool
|
|
|
|
|
+成功返回true,失败返回false
|
|
|
|
|
+
|
|
|
|
|
+@usage
|
|
|
|
|
+-- GPIO ID 0x00配置为输出模式,默认输出低电平
|
|
|
|
|
+AirGPIO_1000.setup(0x00, 0)
|
|
|
|
|
+
|
|
|
|
|
+-- GPIO ID 0x11配置为输入模式
|
|
|
|
|
+AirGPIO_1000.setup(0x11)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+--P04引脚中断处理函数
|
|
|
|
|
+--id:0x04
|
|
|
|
|
+--level:触发中断后,某一时刻,扩展GPIO输入的电平状态,高电平为1, 低电平为0
|
|
|
|
|
+local function P04_int_cbfunc(id, level)
|
|
|
|
|
+ log.info("P04_int_cbfunc", id, level)
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+-- GPIO ID 0x04配置为中断模式,中断处理函数为P04_int_cbfunc
|
|
|
|
|
+AirGPIO_1000.setup(0x04, P04_int_cbfunc)
|
|
|
|
|
+]]
|
|
|
|
|
+function AirGPIO_1000.setup(gpio_id, gpio_mode)
|
|
|
|
|
+ --检查参数的合法性
|
|
|
|
|
+ if not check_gpio_id_valid(gpio_id) then
|
|
|
|
|
+ log.error("AirGPIO_1000.setup", "invalid gpio_id", gpio_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ if not (gpio_mode==0 or gpio_mode==1 or gpio_mode==nil or type(gpio_mode)=="function") then
|
|
|
|
|
+ log.error("AirGPIO_1000.setup", "invalid gpio_mode", type(gpio_mode), gpio_mode)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ log.info("AirGPIO_1000.setup", "enter", gpio_id, type(gpio_mode), gpio_mode)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ --根据扩展GPIO ID识别当前扩展GPIO使用的配置寄存器地址
|
|
|
|
|
+ --0x0x开头的ID为REG_CONFIG_0,0x01开头的ID为REG_CONFIG_1
|
|
|
|
|
+ local reg_addr = ((gpio_id>>4) == 0) and REG_CONFIG_0 or REG_CONFIG_1
|
|
|
|
|
+ --读取从机中输出寄存器当前的值
|
|
|
|
|
+ local reg_data = read_register(reg_addr)
|
|
|
|
|
+
|
|
|
|
|
+ if reg_data==nil then
|
|
|
|
|
+ log.error("AirGPIO_1000.setup", "read config register error", reg_addr)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ local mask = 1<<(gpio_id&0x0F)
|
|
|
|
|
+ local value
|
|
|
|
|
+ --GPIO配置为输出模式
|
|
|
|
|
+ if gpio_mode==0 or gpio_mode==1 then
|
|
|
|
|
+ value = reg_data & (~mask)
|
|
|
|
|
+ --GPIO配置为输入模式
|
|
|
|
|
+ elseif gpio_mode==nil or type(gpio_mode)=="function" then
|
|
|
|
|
+ value = reg_data | mask
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --如果寄存器新值和旧值相比,发生变化
|
|
|
|
|
+ --写新值到从机的配置寄存器中
|
|
|
|
|
+ if reg_data~=value then
|
|
|
|
|
+ if not write_register(reg_addr, value) then
|
|
|
|
|
+ log.error("AirGPIO_1000.setup", "config write error", reg_addr, value)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ log.info("AirGPIO_1000.setup", "config", reg_addr, reg_data, value)
|
|
|
|
|
+
|
|
|
|
|
+ --如果是中断模式,并且用户注册了中断处理函数
|
|
|
|
|
+ if type(gpio_mode)=="function" then
|
|
|
|
|
+ if AirGPIO_1000.ints==nil then
|
|
|
|
|
+ AirGPIO_1000.ints = {}
|
|
|
|
|
+ end
|
|
|
|
|
+ if AirGPIO_1000.ints[gpio_id]==nil then
|
|
|
|
|
+ AirGPIO_1000.ints[gpio_id] = {}
|
|
|
|
|
+ end
|
|
|
|
|
+ --存储中断处理函数
|
|
|
|
|
+ AirGPIO_1000.ints[gpio_id].cb_func = gpio_mode
|
|
|
|
|
+ --读取当前时刻GPIO的输入电平状态
|
|
|
|
|
+ AirGPIO_1000.ints[gpio_id].old_level = AirGPIO_1000.get(gpio_id)
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --如果配置的是输入模式或者中断模式,可以直接返回了
|
|
|
|
|
+ if gpio_mode~=0 and gpio_mode~=1 then return true end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ --如果配置的输出模式,初始化输出的电平为gpio_mode
|
|
|
|
|
+ if not AirGPIO_1000.set(gpio_id, gpio_mode) then
|
|
|
|
|
+ log.error("AirGPIO_1000.setup", "output set error")
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ log.info("AirGPIO_1000.setup", "output", reg_addr, reg_data, value)
|
|
|
|
|
+
|
|
|
|
|
+ return true
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+--设置AirGPIO_1000上配置为输出模式的扩展GPIO的输出电平
|
|
|
|
|
+
|
|
|
|
|
+--gpio_id:number类型;
|
|
|
|
|
+-- 表示AirGPIO_1000上的扩展GPIO ID;
|
|
|
|
|
+-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+--output_level:number类型;
|
|
|
|
|
+-- 表示配置为输出模式的扩展GPIO对外输出的电平;
|
|
|
|
|
+-- 取值范围:0和1,0表示输出低电平,1表示输出高电平;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:成功返回true,失败返回false
|
|
|
|
|
+function AirGPIO_1000.set(gpio_id, output_level)
|
|
|
|
|
+ --检查参数的合法性
|
|
|
|
|
+ if not check_gpio_id_valid(gpio_id) then
|
|
|
|
|
+ log.error("AirGPIO_1000.set", "invalid gpio_id", gpio_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ if not (output_level==0 or output_level==1) then
|
|
|
|
|
+ log.error("AirGPIO_1000.set", "invalid output_level", type(output_level), output_level)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ log.info("AirGPIO_1000.set", "enter", gpio_id, output_level)
|
|
|
|
|
+
|
|
|
|
|
+ --根据扩展GPIO ID识别当前扩展GPIO使用的输出寄存器地址
|
|
|
|
|
+ --0x0x开头的ID为REG_OUTPUT_PORT_0,0x01开头的ID为REG_OUTPUT_PORT_1
|
|
|
|
|
+ local reg_addr = ((gpio_id>>4) == 0) and REG_OUTPUT_PORT_0 or REG_OUTPUT_PORT_1
|
|
|
|
|
+ --读取从机中输出寄存器当前的值
|
|
|
|
|
+ local reg_data = read_register(reg_addr)
|
|
|
|
|
+
|
|
|
|
|
+ if reg_data==nil then
|
|
|
|
|
+ log.error("AirGPIO_1000.set", "read output register error", reg_addr)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ local mask = 1<<(gpio_id&0x0F)
|
|
|
|
|
+ local value
|
|
|
|
|
+
|
|
|
|
|
+ --输出低电平
|
|
|
|
|
+ if output_level==0 then
|
|
|
|
|
+ value = reg_data & (~mask)
|
|
|
|
|
+ --输出高电平
|
|
|
|
|
+ elseif output_level==1 then
|
|
|
|
|
+ value = reg_data | mask
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --如果寄存器新值和旧值相比,发生变化
|
|
|
|
|
+ --写新值到从机的输出寄存器中
|
|
|
|
|
+ if reg_data~=value then
|
|
|
|
|
+ if not write_register(reg_addr, value) then
|
|
|
|
|
+ log.error("AirGPIO_1000.set", "output write error", reg_addr, value)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ log.info("AirGPIO_1000.set", "output", reg_addr, reg_data, value)
|
|
|
|
|
+
|
|
|
|
|
+ return true
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+--读取AirGPIO_1000上配置为输入或者中断模式的扩展GPIO的输入电平
|
|
|
|
|
+
|
|
|
|
|
+--gpio_id:number类型;
|
|
|
|
|
+-- 表示AirGPIO_1000上的扩展GPIO ID;
|
|
|
|
|
+-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:number类型,表示输入的电平,0表示低电平,1表示高电平;如果读取失败,返回false
|
|
|
|
|
+function AirGPIO_1000.get(gpio_id)
|
|
|
|
|
+ --检查参数的合法性
|
|
|
|
|
+ if not check_gpio_id_valid(gpio_id) then
|
|
|
|
|
+ log.error("AirGPIO_1000.get", "invalid gpio_id", gpio_id)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --根据扩展GPIO ID识别当前扩展GPIO使用的输入寄存器地址
|
|
|
|
|
+ --0x0x开头的ID为REG_INPUT_PORT_0,0x01开头的ID为REG_INPUT_PORT_1
|
|
|
|
|
+ local reg_addr = ((gpio_id>>4) == 0) and REG_INPUT_PORT_0 or REG_INPUT_PORT_1
|
|
|
|
|
+ --读取从机中输入寄存器当前的值
|
|
|
|
|
+ local value = read_register(reg_addr)
|
|
|
|
|
+
|
|
|
|
|
+ if not value then
|
|
|
|
|
+ log.error("AirGPIO_1000.get", "read_register error", reg_addr)
|
|
|
|
|
+ return false
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ --返回输入寄存器的值和GPIO对应的bit位的值
|
|
|
|
|
+ return ((value>>(gpio_id&0x0F)) & 0x01)
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+--关闭AirGPIO_1000上的扩展GPIO功能
|
|
|
|
|
+--实际上是恢复为默认状态(配置为输入)
|
|
|
|
|
+
|
|
|
|
|
+--gpio_id:number类型;
|
|
|
|
|
+-- 表示AirGPIO_1000上的扩展GPIO ID;
|
|
|
|
|
+-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
|
|
|
|
|
+-- 必须传入,不允许为空;
|
|
|
|
|
+
|
|
|
|
|
+--返回值:成功返回true,失败返回false
|
|
|
|
|
+function AirGPIO_1000.close(gpio_id)
|
|
|
|
|
+ local result = AirGPIO_1000.setup(gpio_id)
|
|
|
|
|
+
|
|
|
|
|
+ if not result then
|
|
|
|
|
+ log.error("AirGPIO_1000.close", "error", gpio_id)
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ return result
|
|
|
|
|
+end
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+return AirGPIO_1000
|