opio 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. #!/usr/bin/python3
  2. """
  3. This is a clone of the 'gpio/WiringPi' project, written specifically for the
  4. OrangePi i96.
  5. Not all of gpio is re-implemented. The 'mode' command allows the user to
  6. select any pin a GPIO or its special-funtion (i2c, spi, uart, pcm, etc)
  7. Pat Beirne <patb@pbeirne.com>
  8. Implemented:
  9. gpio read <gpio pin number> => displays a value, returns 0 on success
  10. gpio write <gpio pin number> <value> # set a pin high or low
  11. gpio mode [in | out | alt] # set the pin for in/out or special-function
  12. gpio readall # display all current pin settings
  13. # and the pin assignments on the 40 pin i96
  14. gpio readallx # similar to above, but shows RDA pinout
  15. gpio exports # simply dump the state of all the exports
  16. # which exist
  17. gpio leds # like readall, but for LEDs, switches
  18. # and other on-board devices
  19. NOTE: pin numbers are always gpio numbers.
  20. use 'readall' to see the connector assignment
  21. By default, the 'mode' function will create/delete an export. By default,
  22. the 'read' and 'write' function will set the mode and create an export.
  23. To disable this default, use the '-d' option.
  24. Variable plan: functions which are "is_" or "has_" return boolean
  25. functions which involve 'in' 'out' 'alt' pass-&-return strings
  26. functions which involve values pass-&-return ints....-1 means invalid
  27. gpio is always a short int
  28. Attack plan:
  29. mode set: check iomux, then create-&-use export
  30. -d set: check iomux, then low-level set
  31. read: check iomux, then check export, then use export
  32. -d: check iomux, then low-level read
  33. write: check iomux, then check export then set mode=out then use export
  34. -d: check iomux, then set direction=out, tne low-level write
  35. NOTE: 'read' and 'write' will auto-set the GPIO mode and disable 'alt'
  36. NOTE: 'read' and 'write' will auto-set the GPIO mode and disable 'alt'
  37. Classes: GPIO to access a pin through the export-gpio methods
  38. GPIO_DIRECT to access only through low-level calls
  39. read/write/mode will use GPIO unless the -d flag is used
  40. exports will always use GPIO
  41. readall/readallx/leds will use GPIO_DIRECT
  42. """
  43. from mmap import mmap
  44. from struct import pack, unpack
  45. import os, sys, argparse, pathlib, re, logging
  46. VERSION = "2.2"
  47. ############ board specific
  48. class Board:
  49. def __init__(self,full_name,short_name,config_file):
  50. self.name = full_name
  51. self.short_name = short_name
  52. self.config_file = config_file
  53. def __repr__(self):
  54. return self.name
  55. board_i96 = Board("OrangePi i96", "OrangePi i96", "/etc/OrangePi-i96")
  56. board_2g = Board("OrangePi 2G-IOT","OrgPi 2G-iot", "/etc/OrangePi-2g-iot")
  57. # pins, arranged according to i96 connector
  58. # i96 label, rda_port number, pio number, rda special function
  59. board_i96.PINS = (
  60. ("GND", "", -1, "", ""), # 1
  61. ("GND", "", -1, "", ""),
  62. ("UART2.CTS", "B8", 40, "CTS", "ttyS1.cts"),
  63. ("PWR_BTN_N", "", -1, "", ""),
  64. ("UART2.TX", "C8", 104, "TX", "ttyS1.tx"),
  65. ("RST_BTN_N", "", -1, "1.4v", ""),
  66. ("UART2.RX", "C7", 103, "RX", "ttyS1.rx"),
  67. ("SPI2.CLK", "A2", 2, "CLK","spi2.clk"),
  68. ("UART2.RTS", "B9", 41, "RTS","ttyS1.rts"),
  69. ("SPI2.DI", "A4", 4, "DI", "spi2.di"), # 10
  70. ("UART1.TX", "A14", 14, "TX", "ttyS0.tx"),
  71. ("SPI2.CS", "A6", 6, "CS", "spi2.cs"),
  72. ("UART1.RX", "C6", 102, "RX", "ttyS0.rx"),
  73. ("SPI2.DO", "A3", 3, "DO", "spi2.do"),
  74. ("I2C2.SCL", "A0", 0, "SCL", "i2c-1.scl"),
  75. ("I2S.LRCK", "A10", 10, "LRCK", "pcm.fp"),
  76. ("I2C2.SDA", "A1", 1, "SDA", "i2c-1.sda"),
  77. ("I2S.BCK", "A9", 9, "BCK", "pcm.clk"),
  78. ("I2C3.SCL", "B6", 38, "SCL", "i2c-2.scl"),
  79. ("I2S.DO", "A13", 13, "DO", "pcm.do"), # 20
  80. ("I2C3.SDA", "B7", 39, "SDA", "i2c-2.sda"),
  81. ("I2S.DI", "A11", 11, "DI", "pcm.di"),
  82. ("GPIO.A", "A15", 15, "CTS", "ttyS0.cts"),
  83. ("GPIO.B", "A20", 20, "LCD", "lcd"),
  84. ("GPIO.C", "B24", 56, "ROM", "n/a"),
  85. ("GPIO.D", "D2", 66, "CTS", "ttyS2.cts"),
  86. ("GPIO.E", "D3", 67, "RTS", "ttyS2.rts"),
  87. ("GPIO.F", "A22", 22, "LCD", "lcd"),
  88. ("GPIO.G", "A30", 30, "LCD", "lcd"),
  89. ("GPIO.H", "A29", 29, "LCD", "lcd"), # 30
  90. ("GPIO.I", "A28", 28, "LCD", "lcd"),
  91. ("GPIO.J", "A27", 27, "LCD", "lcd"),
  92. ("GPIO.K", "A26", 26, "LCD", "lcd"),
  93. ("GPIO.L", "A25", 25, "LCD", "lcd"),
  94. ("V_PAD", "", -1, "1.8v", ""),
  95. ("SYS_DCIN", "", -1, "n/c", ""),
  96. ("VDD_IN", "", -1, "5V", ""),
  97. ("SYS_DCIN", "", -1, "n/c", ""),
  98. ("GND", "", -1, "", ""),
  99. ("GND", "", -1, "", "") # 40
  100. )
  101. deleted_board_2g_14_PINS = (
  102. ("VCC", "", -1,""),
  103. ("I2C1.SDA", "B31", 63, "SDA"),
  104. ("I2C1.SCL", "B30", 62, "SCL"),
  105. ("GPIO.B24", "B24", 56, ""),
  106. ("GND", "", -1, ""),
  107. ("UART1.RX", "C6", 102, "RX"),
  108. ("UART1.TX", "A14", 14, "TX"),
  109. ("UART1.CT", "A15", 15,"CTS"),
  110. ("VCC", "", -1,""),
  111. ("SPI2.DI", "A4", 4, "DI"), #10
  112. ("SPI2.DIO", "A3", 3, "DIO"),
  113. ("SPI2.CLK", "A2", 2, "CLK"),
  114. ("GND", "", -1, ""),
  115. ("I2C2.SDA", "A1", 1, ""),
  116. ("GPIO.C26", "C26", 122, "SIM"),
  117. ("GPIO.C27", "C27", 123, "SIM"),
  118. ("GPIO.C28", "C28", 124, "LCD"),
  119. ("GPIO.C29", "C29", 125, "LCD"),
  120. ("GPIO.C30", "C30", 126, "LCD"),
  121. ("GND", "", -1, ""), #20
  122. ("I2C3.SDA", "B7", 39, "SDA"),
  123. ("I2C3.SCL", "B6", 38, "SCL"),
  124. ("UART2.CT", "B8", 40, "CTS"),
  125. ("GND", "", -1, ""),
  126. ("UART2.RT", "B9", 41, "RTS"),
  127. ("GND", "", -1, ""),
  128. ("I2C2.SCL", "A0", 0, "SCL"),
  129. ("SPI2.CS0", "A5", 5, "CS0"),
  130. ("SPI2.CS1", "A6", 6, "CS1"),
  131. ("UART1.RT", "A16", 16, "RTS"), #30
  132. ("GND", "", -1, ""),
  133. ("GPIO.C25", "C25", 121, "SIM"),
  134. ("GPIO.C5", "C5", 101, ""),
  135. ("GND", "", -1, ""),
  136. ("GPIO.B5", "B5", 37, ""),
  137. ("UART2.RX", "C7", 103,""),
  138. ("UART2.TX", "C8", 104,""),
  139. ("GND", "", -1, ""),
  140. ("VCC", "", -1,""),
  141. ("VCC", "", -1,""), #40
  142. )
  143. board_2g.PINS = (
  144. ("V_PAD", "", -1, "2.8v", ""),
  145. ("VDD_IN", "", -1, "5V", ""),
  146. ("I2C1.SDA", "B31", 63, "SDA","i2c-0.sda"),
  147. ("VDD_IN", "", -1, "5V", ""),
  148. ("I2C1.SCL", "B30", 62, "SCL", "i2c-0.scl"),
  149. ("GND", "", -1, "", ""),
  150. ("GPIO.B24", "B24", 56, "", ""),
  151. ("UART2.TX", "C8", 104,"", "ttyS1.tx"),
  152. ("GND", "", -1, "", ""),
  153. ("UART2.RX", "C7", 103,"", "ttyS1.rx"), #10
  154. ("UART1.RX", "C6", 102, "RX", "ttyS0.rx"),
  155. ("GPIO.B5", "B5", 37, "", ""),
  156. ("UART1.TX", "A14", 14, "TX", "ttyS0.tx"),
  157. ("GND", "", -1, "", ""),
  158. ("UART1.CT", "A15", 15,"CTS", "ttyS0.cts"),
  159. ("GPIO.C5", "C5", 101, "", "",""),
  160. ("V_PAD", "", -1, "2.8v", ""),
  161. ("GPIO.C25", "C25", 121, "SIM", ""),
  162. ("SPI2.DI", "A4", 4, "DI", "spi-1.di"),
  163. ("GND", "", -1, "", ""), #20
  164. ("SPI2.DIO", "A3", 3, "DIO", "spi-1.do"),
  165. ("UART1.RT", "A16", 16, "RTS", "ttyS0.rts"),
  166. ("SPI2.CLK", "A2", 2, "CLK", "spi-1.clk"),
  167. ("SPI2.CS0", "A5", 5, "CS0", "spi-1.cs"),
  168. ("GND", "", -1, "", ""),
  169. ("SPI2.CS1", "A6", 6, "CS1", "spi-1.cs1"),
  170. ("I2C2.SDA", "A1", 1, "", "i2c-1.sda"),
  171. ("I2C2.SCL", "A0", 0, "SCL", "i2c-1.scl"),
  172. ("GPIO.C26", "C26", 122, "SIM", ""),
  173. ("GND", "", -1, "", ""), #30
  174. ("GPIO.C27", "C27", 123, "SIM", ""),
  175. ("UART2.RT", "B9", 41, "RTS", "ttyS1.rts"),
  176. ("GPIO.C28", "C28", 124, "LCD", "lcd"),
  177. ("GND", "", -1, "", ""),
  178. ("GPIO.C29", "C29", 125, "LCD", "lcd"),
  179. ("UART2.CT", "B8", 40, "CTS", "ttyS1.cts"),
  180. ("GPIO.C30", "C30", 126, "LCD", "lcd"),
  181. ("I2C3.SCL", "B6", 38, "SCL", "i2c2-scl"),
  182. ("GND", "", -1, "", ""),
  183. ("I2C3.SDA", "B7", 39, "SDA", "i2c2-sda"), #40
  184. )
  185. board_2g.other = (
  186. )
  187. board_i96.other = (
  188. ("LED2", "C30", 126, ""),
  189. ("LED3", "C29", 125, ""),
  190. ("LED5", "C5", 101, ""),
  191. ("J2", "C2", 98, "boot sd"),
  192. ("OTGPWR","A17",17,""),
  193. # ("DBG_TX","D1",65,"TX"),
  194. # ("DBG_RX","D0",64,"RX"),
  195. )
  196. ########################## cpu specific
  197. class Cpu:
  198. def __init__(self,name):
  199. self.name = name
  200. RDA_PORTC_IOMUX = 0x11a09008
  201. RDA_PORTA_IOMUX = 0x11a0900c
  202. RDA_PORTB_IOMUX = 0x11a09010
  203. RDA_PORTD_IOMUX = 0x11a09014
  204. cpu_rda = Cpu("RDA8810")
  205. cpu_rda.IOMUX_ADDRESSES = (RDA_PORTA_IOMUX, RDA_PORTB_IOMUX, RDA_PORTD_IOMUX, RDA_PORTC_IOMUX)
  206. cpu = cpu_rda
  207. GPIO_PER_PORT = 32
  208. PAGE_MASK = ~0xFFF
  209. PAGE_OFFSET = 0xFFF
  210. SYS_PATH = "/sys/class/gpio/"
  211. def pin_has_export(gpio):
  212. return pathlib.Path('/sys/class/gpio/gpio{}'.format(gpio)).exists()
  213. #################### memory access
  214. def mem_set(address, bitmask, value):
  215. try:
  216. with open("/dev/mem","w+b") as m:
  217. mem = mmap(m.fileno(), 32, offset = address & PAGE_MASK)
  218. address &= PAGE_OFFSET
  219. data = unpack("<L",mem[address:address+4])[0]
  220. logging.debug("mem_set: current data is {} mask is {} value is {}".format(hex(data),hex(bitmask),value))
  221. if value:
  222. data |= bitmask
  223. else:
  224. data &= ~bitmask
  225. logging.debug("mem_set: resulting data is {}".format(hex(data)))
  226. mem[address:address+4] = pack("<L",data)
  227. except PermissionError:
  228. print("failed to open /dev/mem.....you must execute this script as root")
  229. sys.exit(1)
  230. def mem_get(address, bitmask):
  231. try:
  232. with open("/dev/mem","r+b") as m:
  233. mem = mmap(m.fileno(), 32, offset = address & PAGE_MASK)
  234. address &= PAGE_OFFSET
  235. return unpack("<L",mem[address:address+4])[0] & bitmask
  236. except PermissionError:
  237. print("failed to open /dev/mem.....you must execute this script as root")
  238. sys.exit(1)
  239. ############################ pin access
  240. """ decide which kind of GPIO """
  241. def GPIO_factory(gpio,direct):
  242. if direct:
  243. return GPIO_DIRECT(gpio)
  244. else:
  245. return GPIO(gpio)
  246. """ via the gpio/export system """
  247. class GPIO:
  248. ''' this object owns a pin, assures it has an export and accesses it through the gpio-export mechanism'''
  249. def __init__(self, gpio):
  250. self.gpio = gpio
  251. self.set_iomux(True)
  252. create_export(gpio)
  253. def get(self):
  254. logging.debug("GPIO.get")
  255. # we don't care about the export/direction
  256. with open(SYS_PATH + "gpio{}/value".format(self.gpio)) as f:
  257. r = int(f.read())
  258. logging.debug("pin_read of {} returns {}".format(self.gpio,r))
  259. return r
  260. def set(self, value):
  261. logging.debug("GPIO.set {} {}".format(self.gpio, value))
  262. self.set_mode('out')
  263. with open(SYS_PATH + "gpio{}/value".format(self.gpio),"w+b") as f:
  264. f.write(bytes(str(value),"utf-8"))
  265. def set_mode(self,mode_string):
  266. with open('/sys/class/gpio/gpio{}/direction'.format(self.gpio),'w') as f:
  267. f.write(mode_string)
  268. def get_mode_value(self):
  269. with open('/sys/class/gpio/gpio{}/direction'.format(self.gpio)) as f:
  270. return f.read().strip(), self.get()
  271. def set_iomux(self, gpio_mode):
  272. ''' set value=True for this pin to be GPIO,
  273. False for this pin to be special function'''
  274. logging.debug("GPIO: set iomux for pin {} to {}".format(self.gpio,gpio_mode))
  275. port_group = self.gpio // GPIO_PER_PORT
  276. port_offset = self.gpio % GPIO_PER_PORT
  277. mem_set(cpu.IOMUX_ADDRESSES[port_group], 1 << port_offset, gpio_mode)
  278. if gpio_mode == False:
  279. logging.debug("GPIO.set_iomux with mode {}".format(gpio_mode))
  280. remove_export(self.gpio)
  281. def get_iomux(self):
  282. ''' returns 1 when it's in GPIO mode, 0 for alt mode '''
  283. logging.debug("GPIO check the IOMUX for gpio {}".format(self.gpio))
  284. port_group = self.gpio // GPIO_PER_PORT
  285. port_offset = self.gpio % GPIO_PER_PORT
  286. logging.debug("check IOMUX at address {}".format(hex(cpu.IOMUX_ADDRESSES[port_group])))
  287. return mem_get(cpu.IOMUX_ADDRESSES[port_group], 1 << port_offset)
  288. def __repr__(self):
  289. return("gpio"+str(self.gpio))
  290. class GPIO_DIRECT(GPIO):
  291. def __init__(self,gpio):
  292. self.gpio = gpio
  293. def set(self,value):
  294. logging.debug("GPIO_DIRECT.set {} value: {}".format(self.gpio,value))
  295. if self.get_iomux()==0:
  296. self.set_iomux(1)
  297. self.set_mode('out')
  298. low_level_write(self.gpio,IO_DATA,value)
  299. def get(self):
  300. if self.get_iomux() == 0:
  301. self.set_iomux(1)
  302. self.set_mode('in')
  303. return low_level_read(self.gpio,IO_DATA)
  304. def get_mode_value(self):
  305. iomux = self.get_iomux()
  306. if not iomux:
  307. return 'alt','?'
  308. d = low_level_read(self.gpio, IO_DIR)
  309. m = 'in' if d else 'out'
  310. if not pin_has_export(self.gpio):
  311. m = m+'*'
  312. return m, low_level_read(self.gpio,IO_DATA)
  313. def set_mode(self, mode_string):
  314. low_level_set_mode(self.gpio, mode_string);
  315. def set_iomux(self, gpio_mode):
  316. super().set_iomux(gpio_mode)
  317. def create_export(gpio):
  318. ''' make sure this gpio has an export set in the /sys/class/gpio dir '''
  319. if not pin_has_export(gpio):
  320. with open(SYS_PATH + 'export','w') as f:
  321. f.write(str(gpio))
  322. if not pin_has_export(gpio):
  323. print("could not create the gpio-export for pin {}".format(gpio))
  324. print("perhaps you should run this program as root")
  325. sys.exit(1)
  326. return
  327. def remove_export(gpio):
  328. if pin_has_export(gpio):
  329. with open(SYS_PATH + 'unexport','w') as f:
  330. f.write(str(gpio))
  331. return
  332. ################## low level pin control ################
  333. """ bypass the gpio/export system """
  334. PORTA_IOBASE = 0x20930000
  335. PORTB_IOBASE = 0x20931000
  336. PORTC_IOBASE = 0x11a08000
  337. PORTD_IOBASE = 0x20932000
  338. IOBASE_ADDRESSES = (PORTA_IOBASE, PORTB_IOBASE, PORTD_IOBASE, PORTC_IOBASE)
  339. IO_DIR = 0 # [0=out,1=in] +0 direct access, +4 = clr-reg(out), +8 = set-reg(in)
  340. IO_DATA = 0xc # +0 direct access, +4 for set-reg, +8 for clr-reg
  341. def low_level_read(gpio, address_offset):
  342. port_group = gpio // GPIO_PER_PORT
  343. port_offset = gpio % GPIO_PER_PORT
  344. address = IOBASE_ADDRESSES[port_group] + address_offset
  345. r = mem_get(address, 1 << port_offset)
  346. logging.debug("low_level_read of address {} and bit {} returns {}".format(hex(address),port_offset,hex(r)))
  347. return 1 if r else 0
  348. def low_level_write(gpio, address_offset, data):
  349. port_group = gpio // GPIO_PER_PORT
  350. port_offset = gpio % GPIO_PER_PORT
  351. address = IOBASE_ADDRESSES[port_group] + address_offset
  352. mem_set(address, 1 << port_offset, data)
  353. def low_level_set_mode(gpio, mode):
  354. if mode == 'alt':
  355. print("illegal call to low_level_set_mode")
  356. sys.exit(1)
  357. low_level_write(gpio, IO_DIR, 0 if mode=='out' else 1)
  358. def low_level_get_mode(gpio):
  359. return low_level_read(gpio, IO_DIR)
  360. ######################### detect board ###################
  361. # the 2gio has the B3 pin pulled up
  362. # the i96 board leaves the B3 pin floating
  363. B3 = 35
  364. board = board_i96
  365. def board_auto_sense(args):
  366. global board
  367. if args.cmd in {"readll","readallx","status","statusx","leds","exports"}:
  368. if pathlib.Path(board_2g.config_file).exists() or args.op2giot:
  369. board = board_2g
  370. elif pathlib.Path(board_i96.config_file).exists() or args.i96:
  371. board = board_i96
  372. else:
  373. low_level_set_mode(B3, "out")
  374. low_level_write(B3, IO_DATA, 1)
  375. low_level_set_mode(B3, "in")
  376. a = low_level_read(B3, IO_DATA)
  377. low_level_set_mode(B3, "out")
  378. low_level_write(B3, IO_DATA, 0)
  379. low_level_set_mode(B3, "in")
  380. b = low_level_read(B3, IO_DATA)
  381. board = board_2g if b else board_i96
  382. print("Board auto-detect found {}. To skip auto-detect, create a file named {}".format(board.short_name,board.config_file))
  383. ########################### actions #######################
  384. def do_readall():
  385. exports_dirty = False
  386. print("""
  387. +-----+-----+----------+------+-+ {} +-+------+----------+-----+-----+
  388. | gpio| alt | i96 Name | Mode | V | Physical | V | Mode | i96 Name | alt | gpio|
  389. +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+""".format(
  390. board.short_name))
  391. for i in range(20):
  392. left_gpio = board.PINS[2*i][2]
  393. if left_gpio != -1:
  394. left_g = GPIO_DIRECT(left_gpio)
  395. left_mode, left_value = left_g.get_mode_value()
  396. left_gpio_str = str(left_gpio)
  397. if '*' in left_mode: exports_dirty = True
  398. else:
  399. left_gpio_str = left_mode = left_value = ""
  400. right_gpio = board.PINS[2*i+1][2]
  401. if right_gpio != -1:
  402. right_g = GPIO_DIRECT(right_gpio)
  403. right_mode, right_value = right_g.get_mode_value()
  404. right_gpio_str = str(right_gpio)
  405. if '*' in right_mode: exports_dirty = True
  406. else:
  407. right_gpio_str = right_mode = right_value = ""
  408. left_value,right_value = str(left_value),str(right_value)
  409. print("| {:3s} | {:4s}| {:9s}| {:4s} | {:1s} | {:2d} || {:2d} | {:1s} | {:4s} | {:9s}| {:4s}| {:3s} |".format(
  410. left_gpio_str,board.PINS[2*i][3],board.PINS[2*i][0],
  411. left_mode,left_value,2*i+1,
  412. 2*i+2,right_value,right_mode,board.PINS[2*i+1][0],
  413. board.PINS[2*i+1][3],right_gpio_str))
  414. print("+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+")
  415. if exports_dirty:
  416. print("Note: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpio")
  417. def do_exports():
  418. print("GPIO Pins Mode Value Located")
  419. for f in os.listdir(SYS_PATH):
  420. if re.match('gpio\d',f):
  421. gpio = GPIO(int(f[4:]))
  422. m,v = gpio.get_mode_value()
  423. iop = ""
  424. for i in range(len(board.PINS)):
  425. if board.PINS[i][2]==gpio.gpio:
  426. iop = (board.short_name + " I/O: {}").format(i+1)
  427. break
  428. for i in range(len(board.other)):
  429. if board.other[i][2]==gpio:
  430. iop = board.other[i][0]
  431. break
  432. print("{:>9s} {:3} {:<6} {}".format(f,m,v,iop))
  433. def do_leds():
  434. print("+------+-------+------+-----+")
  435. print("| gpio | func | mode |value|")
  436. print("+------+-------+------+-----+")
  437. for p in board.other:
  438. #print("led function:", p)
  439. g = GPIO_DIRECT(p[2])
  440. m,v = g.get_mode_value()
  441. print("| {:3} | {:6}| {:4} | {:1} |".format(
  442. p[2],p[0],m,v))
  443. print("+------+-------+------+-----+")
  444. def check_gpio_valid():
  445. if args.gpio == None or args.gpio<0 or args.gpio>127:
  446. print("the {} command requires a gpio pin number".format(args.cmd))
  447. sys.exit(1)
  448. def do_read():
  449. logging.debug("do_read: %d",args.gpio)
  450. check_gpio_valid()
  451. gpio = args.gpio
  452. g = GPIO_factory(gpio,args.direct)
  453. print(g.get())
  454. def do_write():
  455. logging.debug("do_write: %d %s",args.gpio, args.extra)
  456. check_gpio_valid()
  457. gpio = args.gpio
  458. g = GPIO_factory(gpio, args.direct)
  459. if args.extra in ('1', 'on', 'ON'):
  460. v = 1
  461. elif args.extra in ('0', 'off', 'OFF'):
  462. v = 0
  463. else:
  464. print("the 'write' command requires a 2nd argument, either 0 or 1")
  465. sys.exit(1)
  466. g.set(v)
  467. def do_mode():
  468. logging.info("do_mode %d %s", args.gpio, args.extra)
  469. logging.info("the -d flag is {}".format(args.direct))
  470. check_gpio_valid()
  471. if args.extra == None:
  472. m,v = GPIO_DIRECT(args.gpio).get_mode_value()
  473. print(m)
  474. return
  475. if args.extra == "alt":
  476. args.direct = True
  477. gpio = GPIO_factory(args.gpio,args.direct)
  478. if args.extra in ('in','out'):
  479. logging.info("set mode: %s",args.extra)
  480. gpio.set_iomux(True)
  481. gpio.set_mode(args.extra)
  482. elif args.extra=='alt':
  483. logging.info("set alt mode")
  484. gpio.set_iomux(False)
  485. def do_readallx():
  486. exports_dirty = False
  487. print("""
  488. +-----+-----+----------+------+-+ {} +-+------+----------+-----+-----+
  489. | gpio| RDA | alt name | Mode | V | Physical | V | Mode | alt name | RDA | gpio|
  490. +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+""".format(
  491. board.short_name))
  492. for i in range(20):
  493. left_gpio = board.PINS[2*i][2]
  494. if left_gpio != -1:
  495. left_g = GPIO_DIRECT(left_gpio)
  496. left_mode, left_value = left_g.get_mode_value()
  497. left_gpio_str = str(left_gpio)
  498. if '*' in left_mode: exports_dirty = True
  499. else:
  500. left_gpio_str = left_mode = left_value = ""
  501. right_gpio = board.PINS[2*i+1][2]
  502. if right_gpio != -1:
  503. right_g = GPIO_DIRECT(right_gpio)
  504. right_mode, right_value = right_g.get_mode_value()
  505. right_gpio_str = str(right_gpio)
  506. if '*' in right_mode: exports_dirty = True
  507. else:
  508. right_gpio_str = right_mode = right_value = ""
  509. left_value,right_value = str(left_value),str(right_value)
  510. print("| {:3s} | {:4s}| {:9s}| {:4s} | {:1s} | {:2d} || {:2d} | {:1s} | {:4s} | {:9s}| {:4s}| {:3s} |".format(
  511. left_gpio_str,board.PINS[2*i][1],board.PINS[2*i][4],
  512. left_mode,left_value,2*i+1,
  513. 2*i+2,right_value,right_mode,board.PINS[2*i+1][4],
  514. board.PINS[2*i+1][1],right_gpio_str))
  515. print("+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+")
  516. if exports_dirty:
  517. print("Note: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpio")
  518. print("Note: the alt names are based on the Linux naming scheme")
  519. args = None
  520. if __name__ == "__main__":
  521. #logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
  522. #logging.basicConfig(stream=sys.stderr, level=logging.INFO)
  523. parser = argparse.ArgumentParser(description = "Access GPIO on the OrangePi RDA boards")
  524. parser.add_argument('-v','--version', action='version',
  525. version="opio "+VERSION+" -- python rewrite of gpio; by Pat Beirne")
  526. parser.add_argument('cmd',help="one of: read/in, write/out, mode, readall/status, readallx/statusx, leds, exports")
  527. parser.add_argument('gpio',nargs='?',type=int,help="gpio number 0...126")
  528. parser.add_argument('extra',nargs='?')
  529. parser.add_argument('-d',"--direct",help="use low-level access",action="store_true")
  530. parser.add_argument('-2',"--op2giot",help="configure for OrangePi 2G-iot [disable auto-detect]",action="store_true")
  531. parser.add_argument('-9',"--i96",help="configure for OrangePi i96 [disable auto-detect]",action="store_true")
  532. args = parser.parse_args()
  533. board_auto_sense(args)
  534. switcher = {"readall":do_readall,
  535. "readallx":do_readallx,
  536. "status":do_readall,
  537. "statusx":do_readallx,
  538. "leds":do_leds,
  539. "mode":do_mode,
  540. "read":do_read,
  541. "write":do_write,
  542. "in":do_read,
  543. "out":do_write,
  544. "exports":do_exports}
  545. f = switcher.get(args.cmd)
  546. if not f:
  547. print("the available commands are:", ", ".join(sorted(list(switcher.keys()))))
  548. print("function",args.cmd,"not found")
  549. sys.exit(1)
  550. f()