opio 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  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.1"
  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. def mem_get(address, bitmask):
  230. try:
  231. with open("/dev/mem","r+b") as m:
  232. mem = mmap(m.fileno(), 32, offset = address & PAGE_MASK)
  233. address &= PAGE_OFFSET
  234. return unpack("<L",mem[address:address+4])[0] & bitmask
  235. except PermissionError:
  236. print("failed to open /dev/mem.....you must execute this script as root")
  237. ############################ pin access
  238. """ decide which kind of GPIO """
  239. def GPIO_factory(gpio,direct):
  240. if direct:
  241. return GPIO_DIRECT(gpio)
  242. else:
  243. return GPIO(gpio)
  244. """ via the gpio/export system """
  245. class GPIO:
  246. ''' this object owns a pin, assures it has an export and accesses it through the gpio-export mechanism'''
  247. def __init__(self, gpio):
  248. self.gpio = gpio
  249. self.set_iomux(True)
  250. create_export(gpio)
  251. def get(self):
  252. logging.debug("GPIO.get")
  253. # we don't care about the export/direction
  254. with open(SYS_PATH + "gpio{}/value".format(self.gpio)) as f:
  255. r = int(f.read())
  256. logging.debug("pin_read of {} returns {}".format(self.gpio,r))
  257. return r
  258. def set(self, value):
  259. logging.debug("GPIO.set {} {}".format(self.gpio, value))
  260. self.set_mode('out')
  261. with open(SYS_PATH + "gpio{}/value".format(self.gpio),"w+b") as f:
  262. f.write(bytes(str(value),"utf-8"))
  263. def set_mode(self,mode_string):
  264. with open('/sys/class/gpio/gpio{}/direction'.format(self.gpio),'w') as f:
  265. f.write(mode_string)
  266. def get_mode_value(self):
  267. with open('/sys/class/gpio/gpio{}/direction'.format(self.gpio)) as f:
  268. return f.read().strip(), self.get()
  269. def set_iomux(self, gpio_mode):
  270. ''' set value=True for this pin to be GPIO,
  271. False for this pin to be special function'''
  272. logging.debug("GPIO: set iomux for pin {} to {}".format(self.gpio,gpio_mode))
  273. port_group = self.gpio // GPIO_PER_PORT
  274. port_offset = self.gpio % GPIO_PER_PORT
  275. mem_set(cpu.IOMUX_ADDRESSES[port_group], 1 << port_offset, gpio_mode)
  276. if gpio_mode == False:
  277. logging.debug("GPIO.set_iomux with mode {}".format(gpio_mode))
  278. remove_export(self.gpio)
  279. def get_iomux(self):
  280. ''' returns 1 when it's in GPIO mode, 0 for alt mode '''
  281. logging.debug("GPIO check the IOMUX for gpio {}".format(self.gpio))
  282. port_group = self.gpio // GPIO_PER_PORT
  283. port_offset = self.gpio % GPIO_PER_PORT
  284. logging.debug("check IOMUX at address {}".format(hex(cpu.IOMUX_ADDRESSES[port_group])))
  285. return mem_get(cpu.IOMUX_ADDRESSES[port_group], 1 << port_offset)
  286. def __repr__(self):
  287. return("gpio"+str(self.gpio))
  288. class GPIO_DIRECT(GPIO):
  289. def __init__(self,gpio):
  290. self.gpio = gpio
  291. def set(self,value):
  292. logging.debug("GPIO_DIRECT.set {} value: {}".format(self.gpio,value))
  293. if self.get_iomux()==0:
  294. self.set_iomux(1)
  295. self.set_mode('out')
  296. low_level_write(self.gpio,IO_DATA,value)
  297. def get(self):
  298. if self.get_iomux() == 0:
  299. self.set_iomux(1)
  300. self.set_mode('in')
  301. return low_level_read(self.gpio,IO_DATA)
  302. def get_mode_value(self):
  303. iomux = self.get_iomux()
  304. if not iomux:
  305. return 'alt','?'
  306. d = low_level_read(self.gpio, IO_DIR)
  307. m = 'in' if d else 'out'
  308. if not pin_has_export(self.gpio):
  309. m = m+'*'
  310. return m, low_level_read(self.gpio,IO_DATA)
  311. def set_mode(self, mode_string):
  312. low_level_set_mode(self.gpio, mode_string);
  313. def set_iomux(self, gpio_mode):
  314. super().set_iomux(gpio_mode)
  315. def create_export(gpio):
  316. ''' make sure this gpio has an export set in the /sys/class/gpio dir '''
  317. if not pin_has_export(gpio):
  318. with open(SYS_PATH + 'export','w') as f:
  319. f.write(str(gpio))
  320. if not pin_has_export(gpio):
  321. print("could not create the gpio-export for pin {}".format(gpio))
  322. print("perhaps you should run this program as root")
  323. sys.exit(1)
  324. return
  325. def remove_export(gpio):
  326. if pin_has_export(gpio):
  327. with open(SYS_PATH + 'unexport','w') as f:
  328. f.write(str(gpio))
  329. return
  330. ################## low level pin control ################
  331. """ bypass the gpio/export system """
  332. PORTA_IOBASE = 0x20930000
  333. PORTB_IOBASE = 0x20931000
  334. PORTC_IOBASE = 0x11a08000
  335. PORTD_IOBASE = 0x20932000
  336. IOBASE_ADDRESSES = (PORTA_IOBASE, PORTB_IOBASE, PORTD_IOBASE, PORTC_IOBASE)
  337. IO_DIR = 0 # [0=out,1=in] +0 direct access, +4 = clr-reg(out), +8 = set-reg(in)
  338. IO_DATA = 0xc # +0 direct access, +4 for set-reg, +8 for clr-reg
  339. def low_level_read(gpio, address_offset):
  340. port_group = gpio // GPIO_PER_PORT
  341. port_offset = gpio % GPIO_PER_PORT
  342. address = IOBASE_ADDRESSES[port_group] + address_offset
  343. r = mem_get(address, 1 << port_offset)
  344. logging.debug("low_level_read of address {} and bit {} returns {}".format(hex(address),port_offset,hex(r)))
  345. return 1 if r else 0
  346. def low_level_write(gpio, address_offset, data):
  347. port_group = gpio // GPIO_PER_PORT
  348. port_offset = gpio % GPIO_PER_PORT
  349. address = IOBASE_ADDRESSES[port_group] + address_offset
  350. mem_set(address, 1 << port_offset, data)
  351. def low_level_set_mode(gpio, mode):
  352. if mode == 'alt':
  353. print("illegal call to low_level_set_mode")
  354. sys.exit(1)
  355. low_level_write(gpio, IO_DIR, 0 if mode=='out' else 1)
  356. def low_level_get_mode(gpio):
  357. return low_level_read(gpio, IO_DIR)
  358. ######################### detect board ###################
  359. # the 2gio has the B3 pin pulled up
  360. # the i96 board leaves the B3 pin floating
  361. B3 = 35
  362. def board_auto_sense():
  363. low_level_set_mode(B3, "out")
  364. low_level_write(B3, IO_DATA, 1)
  365. low_level_set_mode(B3, "in")
  366. a = low_level_read(B3, IO_DATA)
  367. low_level_set_mode(B3, "out")
  368. low_level_write(B3, IO_DATA, 0)
  369. low_level_set_mode(B3, "in")
  370. b = low_level_read(B3, IO_DATA)
  371. board = board_2g if b else board_i96
  372. print("Board auto-detect found {}. To skip auto-detect, create a file named {}".format(board.short_name,board.config_file))
  373. return board
  374. ########################### actions #######################
  375. def do_readall():
  376. exports_dirty = False
  377. print("""
  378. +-----+-----+----------+------+-+ {} +-+------+----------+-----+-----+
  379. | gpio| alt | i96 Name | Mode | V | Physical | V | Mode | i96 Name | alt | gpio|
  380. +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+""".format(
  381. board.short_name))
  382. for i in range(20):
  383. left_gpio = board.PINS[2*i][2]
  384. if left_gpio != -1:
  385. left_g = GPIO_DIRECT(left_gpio)
  386. left_mode, left_value = left_g.get_mode_value()
  387. left_gpio_str = str(left_gpio)
  388. if '*' in left_mode: exports_dirty = True
  389. else:
  390. left_gpio_str = left_mode = left_value = ""
  391. right_gpio = board.PINS[2*i+1][2]
  392. if right_gpio != -1:
  393. right_g = GPIO_DIRECT(right_gpio)
  394. right_mode, right_value = right_g.get_mode_value()
  395. right_gpio_str = str(right_gpio)
  396. if '*' in right_mode: exports_dirty = True
  397. else:
  398. right_gpio_str = right_mode = right_value = ""
  399. left_value,right_value = str(left_value),str(right_value)
  400. print("| {:3s} | {:4s}| {:9s}| {:4s} | {:1s} | {:2d} || {:2d} | {:1s} | {:4s} | {:9s}| {:4s}| {:3s} |".format(
  401. left_gpio_str,board.PINS[2*i][3],board.PINS[2*i][0],
  402. left_mode,left_value,2*i+1,
  403. 2*i+2,right_value,right_mode,board.PINS[2*i+1][0],
  404. board.PINS[2*i+1][3],right_gpio_str))
  405. print("+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+")
  406. if exports_dirty:
  407. print("Note: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpio")
  408. def do_exports():
  409. print("GPIO Pins Mode Value Located")
  410. for f in os.listdir(SYS_PATH):
  411. if re.match('gpio\d',f):
  412. gpio = GPIO(int(f[4:]))
  413. m,v = gpio.get_mode_value()
  414. iop = ""
  415. for i in range(len(board.PINS)):
  416. if board.PINS[i][2]==gpio.gpio:
  417. iop = (board.short_name + " I/O: {}").format(i+1)
  418. break
  419. for i in range(len(board.other)):
  420. if board.other[i][2]==gpio:
  421. iop = board.other[i][0]
  422. break
  423. print("{:>9s} {:3} {:<6} {}".format(f,m,v,iop))
  424. def do_leds():
  425. print("+------+-------+------+-----+")
  426. print("| gpio | func | mode |value|")
  427. print("+------+-------+------+-----+")
  428. for p in board.other:
  429. #print("led function:", p)
  430. g = GPIO_DIRECT(p[2])
  431. m,v = g.get_mode_value()
  432. print("| {:3} | {:6}| {:4} | {:1} |".format(
  433. p[2],p[0],m,v))
  434. print("+------+-------+------+-----+")
  435. def do_read():
  436. logging.debug("do_read: %d",args.gpio)
  437. gpio = args.gpio
  438. g = GPIO_factory(gpio,args.direct)
  439. print(g.get())
  440. def do_write():
  441. logging.debug("do_write: %d %s",args.gpio, args.extra)
  442. gpio = args.gpio
  443. g = GPIO_factory(gpio, args.direct)
  444. if args.extra in ('1', 'on', 'ON'):
  445. v = 1
  446. elif args.extra in ('0', 'off', 'OFF'):
  447. v = 0
  448. else:
  449. print("the 'write' command requires a 2nd argument, either 0 or 1")
  450. sys.exit(1)
  451. g.set(v)
  452. def do_mode():
  453. logging.info("do_mode %d %s", args.gpio, args.extra)
  454. logging.info("the -d flag is {}".format(args.direct))
  455. if not args.gpio or args.gpio<0 or args.gpio>127:
  456. print("the {} command requires a gpio number".format(args.cmd))
  457. sys.exit(1)
  458. if args.extra == None:
  459. m,v = GPIO_DIRECT(args.gpio).get_mode_value()
  460. print(m)
  461. return
  462. if args.extra == "alt":
  463. args.direct = True
  464. gpio = GPIO_factory(args.gpio,args.direct)
  465. if args.extra in ('in','out'):
  466. logging.info("set mode: %s",args.extra)
  467. gpio.set_iomux(True)
  468. gpio.set_mode(args.extra)
  469. elif args.extra=='alt':
  470. logging.info("set alt mode")
  471. gpio.set_iomux(False)
  472. def do_readallx():
  473. exports_dirty = False
  474. print("""
  475. +-----+-----+----------+------+-+ {} +-+------+----------+-----+-----+
  476. | gpio| RDA | alt name | Mode | V | Physical | V | Mode | alt name | RDA | gpio|
  477. +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+""".format(
  478. board.short_name))
  479. for i in range(20):
  480. left_gpio = board.PINS[2*i][2]
  481. if left_gpio != -1:
  482. left_g = GPIO_DIRECT(left_gpio)
  483. left_mode, left_value = left_g.get_mode_value()
  484. left_gpio_str = str(left_gpio)
  485. if '*' in left_mode: exports_dirty = True
  486. else:
  487. left_gpio_str = left_mode = left_value = ""
  488. right_gpio = board.PINS[2*i+1][2]
  489. if right_gpio != -1:
  490. right_g = GPIO_DIRECT(right_gpio)
  491. right_mode, right_value = right_g.get_mode_value()
  492. right_gpio_str = str(right_gpio)
  493. if '*' in right_mode: exports_dirty = True
  494. else:
  495. right_gpio_str = right_mode = right_value = ""
  496. left_value,right_value = str(left_value),str(right_value)
  497. print("| {:3s} | {:4s}| {:9s}| {:4s} | {:1s} | {:2d} || {:2d} | {:1s} | {:4s} | {:9s}| {:4s}| {:3s} |".format(
  498. left_gpio_str,board.PINS[2*i][1],board.PINS[2*i][4],
  499. left_mode,left_value,2*i+1,
  500. 2*i+2,right_value,right_mode,board.PINS[2*i+1][4],
  501. board.PINS[2*i+1][1],right_gpio_str))
  502. print("+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+")
  503. if exports_dirty:
  504. print("Note: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpio")
  505. print("Note: the alt names are based on the Linux naming scheme")
  506. args = None
  507. if __name__ == "__main__":
  508. #logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
  509. #logging.basicConfig(stream=sys.stderr, level=logging.INFO)
  510. parser = argparse.ArgumentParser(description = "Access GPIO on the OrangePi RDA boards")
  511. parser.add_argument('-v','--version', action='version',
  512. version="opio "+VERSION+" -- python rewrite of gpio; by Pat Beirne")
  513. parser.add_argument('cmd',help="one of: read, write, mode, readall, readallx")
  514. parser.add_argument('gpio',nargs='?',type=int,help="gpio number 0...126")
  515. parser.add_argument('extra',nargs='?')
  516. parser.add_argument('-d',"--direct",help="use low-level access",action="store_true")
  517. parser.add_argument('-2',"--op2giot",help="configure for OrangePi 2G-iot [disable auto-detect]",action="store_true")
  518. parser.add_argument('-9',"--i96",help="configure for OrangePi i96 [disable auto-detect]",action="store_true")
  519. args = parser.parse_args()
  520. if args.cmd in {"readll","readallx","status","statusx","leds","exports"}:
  521. if pathlib.Path(board_2g.config_file).exists() or args.op2giot:
  522. board = board_2g
  523. elif pathlib.Path(board_i96.config_file).exists() or args.i96:
  524. board = board_i96
  525. else:
  526. board = board_auto_sense()
  527. switcher = {"readall":do_readall,
  528. "readallx":do_readallx,
  529. "status":do_readall,
  530. "statusx":do_readallx,
  531. "leds":do_leds,
  532. "mode":do_mode,
  533. "read":do_read,
  534. "write":do_write,
  535. "in":do_read,
  536. "out":do_write,
  537. "exports":do_exports}
  538. f = switcher.get(args.cmd)
  539. if not f:
  540. print("the available commands are:", ", ".join(sorted(list(switcher.keys()))))
  541. print("function",args.cmd,"not found")
  542. sys.exit(1)
  543. f()