#!/usr/bin/luajit -- --------------------------------------------- -- gpio_led.lua 2015/03/21 -- Copyright (c) 2015 Jun Mizutani, -- released under the MIT open source license. -- --------------------------------------------- local bit = require("bit") local ffi = require("ffi") local C = ffi.C ffi.cdef[[ void *mmap(void *addr, size_t len, int prot, int flags, int fd, int offset); int munmap(void *addr, size_t len); int open(const char *pathname, int flags, int mode); typedef unsigned long int nfds_t; int poll(struct pollfd *fds, nfds_t nfds, int timeout); ]] function sleep(sec) C.poll(nil, 0, sec * 1000) end -- 物理アドレス空間のデバイスファイルをオープン function mem_open() local O_RDONLY = 0 local O_WRONLY = 1 local O_RDWR = 2 local fd = C.open("/dev/mem", O_RDWR, 0) return fd end -- メモリをマッピング function mem_map(fd, addr, length, offset) local PROT_READ = 1 local PROT_WRITE = 2 local PROT_EXEC = 4 local MAP_SHARED = 1 local MAP_PRIVATE = 2 if fd > 0 then local p = C.mmap(addr, length, PROT_READ + PROT_WRITE, MAP_SHARED, fd, offset) local mem = ffi.cast("int32_t *", p) if mem > ffi.cast("int32_t *", 0) then return mem end end return nil end -- メモリのマッピングを解除 function mem_unmap(addr, length) local p = ffi.cast("int32_t *", addr) return C.munmap(p, length) end local gpio -- 初代 Raspberry Pi 用のベースアドレス -- local BCM_PEREIFERAL_ADDR = 0x20200000 -- Raspberry Pi2 用のベースアドレス local BCM_PEREIFERAL_ADDR = 0x3F200000 local GPSET0 = 7 local GPSET1 = 8 local GPCLR0 = 10 local GPCLR1 = 11 local GPLEV0 = 13 local GPLEV1 = 14 -- GPIO のレジスタを gpio 配列に設定 function gpioOpen() local fd = mem_open() local mem = mem_map(fd, nil, 256, BCM_PEREIFERAL_ADDR) if mem == nil then print("You must run 'sudo luajit gpio.lua'.") end gpio = mem end -- GPIO のレジスタのマッピングを解除 function gpioClose() mem_unmap(BCM_PEREIFERAL_ADDR, 256) end -- pinNo の GPIO のモードを設定 -- mode: 0/input, 1/output function gpioSetPinMode(pinNo, mode) if pinNo > 53 or pinNo < 0 then print("PinNo is out of range.") return elseif mode > 7 then print("Mode must be [0..7].") return else local reg = math.floor(pinNo / 10) local shift = (pinNo % 10) * 3 local mask = bit.bnot(bit.lshift(7, shift)) -- ~(7 << shift) local val = bit.lshift(mode, shift) local orig = gpio[reg] local new = bit.bor(bit.band(orig, mask), val) gpio[reg] = new end end -- pinNo の GPIO のモードを取得 function gpioGetPinMode(pinNo) if pinNo > 53 or pinNo < 0 then print("PinNo is out of range.") return nil else local reg = math.floor(pinNo / 10) local shift = (pinNo % 10) * 3 local mask = bit.lshift(7, shift) local val = bit.band(gpio[reg], mask) local mode = bit.rshift(val, shift) return mode end end -- pinNo の GPIO に 1 を出力 function gpioSet(pinNo) if pinNo < 32 then gpio[GPSET0] = bit.lshift(1, pinNo) elseif pinNo < 54 then gpio[GPSET1] = bit.lshift(1, pinNo - 32) end end -- pinNo の GPIO に 0 を出力 function gpioClear(pinNo) if pinNo < 32 then gpio[GPCLR0] = bit.lshift(1, pinNo) elseif pinNo < 54 then gpio[GPCLR1] = bit.lshift(1, pinNo - 32) end end -- pinNo の GPIO を読み出し function gpioRead(pinNo) local val if pinNo < 32 then val = bit.band(gpio[GPLEV0], bit.lshift(1, pinNo)) elseif pinNo < 54 then val = bit.band(gpio[GPLEV1], bit.lshift(1, pinNo - 32)) end if val ~= 0 then return 1 end return 0 end -- PWR(赤)と ACT(緑)を点滅させる gpioOpen() -- GPIO アクセス準備 gpioSetPinMode(35, 1) -- PWR : 出力モード gpioSetPinMode(47, 1) -- ACT : 出力モード for i = 1, 30 do gpioSet(35) -- PWR を 点灯 gpioSet(47) -- ACT を 点灯 sleep(0.5) -- 0.5秒間待つ gpioClear(35) -- PWR を 消灯 gpioClear(47) -- ACT を 消灯 sleep(0.3) -- 0.3秒間待つ end gpioClose()