Verison 1.0.3 Release
Based on Buildbotics 0.4.14
This commit is contained in:
162
src/py/bbctrl/AVR.py
Normal file
162
src/py/bbctrl/AVR.py
Normal file
@@ -0,0 +1,162 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import serial
|
||||
import time
|
||||
import traceback
|
||||
import ctypes
|
||||
|
||||
import bbctrl
|
||||
import bbctrl.Cmd as Cmd
|
||||
|
||||
|
||||
class serial_struct(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('type', ctypes.c_int),
|
||||
('line', ctypes.c_int),
|
||||
('port', ctypes.c_uint),
|
||||
('irq', ctypes.c_int),
|
||||
('flags', ctypes.c_int),
|
||||
('xmit_fifo_size', ctypes.c_int),
|
||||
('custom_divisor', ctypes.c_int),
|
||||
('baud_base', ctypes.c_int),
|
||||
('close_delay', ctypes.c_ushort),
|
||||
('io_type', ctypes.c_byte),
|
||||
('reserved', ctypes.c_byte),
|
||||
('hub6', ctypes.c_int),
|
||||
('closing_wait', ctypes.c_ushort),
|
||||
('closing_wait2', ctypes.c_ushort),
|
||||
('iomem_base', ctypes.c_char_p),
|
||||
('iomem_reg_shift', ctypes.c_ushort),
|
||||
('port_high', ctypes.c_uint),
|
||||
('iomap_base', ctypes.c_ulong),
|
||||
]
|
||||
|
||||
|
||||
def serial_set_low_latency(sp):
|
||||
import fcntl
|
||||
import termios
|
||||
|
||||
ASYNCB_LOW_LATENCY = 13
|
||||
|
||||
ss = serial_struct()
|
||||
fcntl.ioctl(sp, termios.TIOCGSERIAL, ss)
|
||||
ss.flags |= 1 << ASYNCB_LOW_LATENCY # pylint: disable=no-member
|
||||
fcntl.ioctl(sp, termios.TIOCSSERIAL, ss)
|
||||
|
||||
|
||||
class AVR(object):
|
||||
def __init__(self, ctrl):
|
||||
self.ctrl = ctrl
|
||||
self.log = ctrl.log.get('AVR')
|
||||
|
||||
self.sp = None
|
||||
self.i2c_addr = ctrl.args.avr_addr
|
||||
self.read_cb = None
|
||||
self.write_cb = None
|
||||
|
||||
|
||||
def close(self): pass
|
||||
|
||||
|
||||
def _start(self):
|
||||
try:
|
||||
self.sp = serial.Serial(self.ctrl.args.serial, self.ctrl.args.baud,
|
||||
rtscts = 1, timeout = 0, write_timeout = 0)
|
||||
self.sp.nonblocking()
|
||||
#serial_set_low_latency(self.sp)
|
||||
|
||||
except Exception as e:
|
||||
self.sp = None
|
||||
self.log.warning('Failed to open serial port: %s', e)
|
||||
|
||||
if self.sp is not None:
|
||||
self.ctrl.ioloop.add_handler(self.sp, self._serial_handler,
|
||||
self.ctrl.ioloop.READ)
|
||||
|
||||
|
||||
def set_handlers(self, read_cb, write_cb):
|
||||
if self.read_cb is not None or self.write_cb is not None:
|
||||
raise Exception('Handler already set')
|
||||
|
||||
self.read_cb = read_cb
|
||||
self.write_cb = write_cb
|
||||
self._start()
|
||||
|
||||
|
||||
def enable_write(self, enable):
|
||||
if self.sp is None: return
|
||||
|
||||
flags = self.ctrl.ioloop.READ
|
||||
if enable: flags |= self.ctrl.ioloop.WRITE
|
||||
self.ctrl.ioloop.update_handler(self.sp, flags)
|
||||
|
||||
|
||||
def _serial_write(self):
|
||||
self.write_cb(lambda data: self.sp.write(data))
|
||||
|
||||
|
||||
def _serial_read(self):
|
||||
try:
|
||||
data = ''
|
||||
data = self.sp.read(self.sp.in_waiting)
|
||||
self.read_cb(data)
|
||||
|
||||
except Exception as e:
|
||||
self.log.warning('%s: %s', e, data)
|
||||
|
||||
|
||||
def _serial_handler(self, fd, events):
|
||||
try:
|
||||
if self.ctrl.ioloop.READ & events: self._serial_read()
|
||||
if self.ctrl.ioloop.WRITE & events: self._serial_write()
|
||||
|
||||
except Exception as e:
|
||||
self.log.warning('Serial handler error: %s', traceback.format_exc())
|
||||
|
||||
|
||||
def i2c_command(self, cmd, byte = None, word = None, block = None):
|
||||
self.log.info('I2C: %s b=%s w=%s d=%s' % (cmd, byte, word, block))
|
||||
retry = 10
|
||||
cmd = ord(cmd[0])
|
||||
|
||||
while True:
|
||||
try:
|
||||
self.ctrl.i2c.write(self.i2c_addr, cmd, byte, word, block)
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
retry -= 1
|
||||
|
||||
if retry:
|
||||
self.log.warning('I2C failed, retrying: %s' % e)
|
||||
time.sleep(0.25)
|
||||
continue
|
||||
|
||||
else:
|
||||
self.log.error('I2C failed: %s' % e)
|
||||
raise
|
||||
Reference in New Issue
Block a user