From 38d67df9abc5fdf000a09662c40484a3c1f9ad9e Mon Sep 17 00:00:00 2001 From: Guy Carver Date: Sat, 4 Nov 2017 17:43:37 -0400 Subject: [PATCH] moving. --- lib/GY521.py | 562 ++++++++++++++++++++++++++++++++ lib/IRDistance.py | 33 ++ lib/JYMCU.py | 69 ++++ lib/L298N.py | 43 +++ lib/OLED.py | 347 ++++++++++++++++++++ lib/PIR.py | 72 +++++ lib/PWM.py | 81 +++++ lib/Relay.py | 30 ++ lib/SR04Distance.py | 71 +++++ lib/ST7735.py | 763 ++++++++++++++++++++++++++++++++++++++++++++ lib/seriffont.py | 99 ++++++ lib/sevenseg.py | 170 ++++++++++ lib/sysfont.py | 265 +++++++++++++++ lib/terminalfont.py | 100 ++++++ 14 files changed, 2705 insertions(+) create mode 100644 lib/GY521.py create mode 100644 lib/IRDistance.py create mode 100644 lib/JYMCU.py create mode 100644 lib/L298N.py create mode 100644 lib/OLED.py create mode 100644 lib/PIR.py create mode 100644 lib/PWM.py create mode 100644 lib/Relay.py create mode 100644 lib/SR04Distance.py create mode 100644 lib/ST7735.py create mode 100644 lib/seriffont.py create mode 100644 lib/sevenseg.py create mode 100644 lib/sysfont.py create mode 100644 lib/terminalfont.py diff --git a/lib/GY521.py b/lib/GY521.py new file mode 100644 index 0000000..38524d1 --- /dev/null +++ b/lib/GY521.py @@ -0,0 +1,562 @@ + +#driver for GY-521 Accelerometer +#Translated by Guy Carver from the MPU6050 sample code. + +import pyb + +ADDRESS_LOW = 0x68 #address pin low (GND), default for InvenSense evaluation board +ADDRESS_HIGH = 0x69 #address pin high (VCC) + +RA_XG_OFFS_TC = 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +RA_YG_OFFS_TC = 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +RA_ZG_OFFS_TC = 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +RA_X_FINE_GAIN = 0x03 //[7:0] X_FINE_GAIN +RA_Y_FINE_GAIN = 0x04 //[7:0] Y_FINE_GAIN +RA_Z_FINE_GAIN = 0x05 //[7:0] Z_FINE_GAIN +RA_XA_OFFS_H = 0x06 //[15:0] XA_OFFS +RA_XA_OFFS_L_TC = 0x07 +RA_YA_OFFS_H = 0x08 //[15:0] YA_OFFS +RA_YA_OFFS_L_TC = 0x09 +RA_ZA_OFFS_H = 0x0A //[15:0] ZA_OFFS +RA_ZA_OFFS_L_TC = 0x0B +RA_XG_OFFS_USRH = 0x13 //[15:0] XG_OFFS_USR +RA_XG_OFFS_USRL = 0x14 +RA_YG_OFFS_USRH = 0x15 //[15:0] YG_OFFS_USR +RA_YG_OFFS_USRL = 0x16 +RA_ZG_OFFS_USRH = 0x17 //[15:0] ZG_OFFS_USR +RA_ZG_OFFS_USRL = 0x18 +RA_SMPLRT_DIV = 0x19 +RA_CONFIG = 0x1A +RA_GYRO_CONFIG = 0x1B +RA_ACCEL_CONFIG = 0x1C +RA_FF_THR = 0x1D +RA_FF_DUR = 0x1E +RA_MOT_THR = 0x1F +RA_MOT_DUR = 0x20 +RA_ZRMOT_THR = 0x21 +RA_ZRMOT_DUR = 0x22 +RA_FIFO_EN = 0x23 +RA_I2C_MST_CTRL = 0x24 +RA_I2C_SLV0_ADDR = 0x25 +RA_I2C_SLV0_REG = 0x26 +RA_I2C_SLV0_CTRL = 0x27 +RA_I2C_SLV1_ADDR = 0x28 +RA_I2C_SLV1_REG = 0x29 +RA_I2C_SLV1_CTRL = 0x2A +RA_I2C_SLV2_ADDR = 0x2B +RA_I2C_SLV2_REG = 0x2C +RA_I2C_SLV2_CTRL = 0x2D +RA_I2C_SLV3_ADDR = 0x2E +RA_I2C_SLV3_REG = 0x2F +RA_I2C_SLV3_CTRL = 0x30 +RA_I2C_SLV4_ADDR = 0x31 +RA_I2C_SLV4_REG = 0x32 +RA_I2C_SLV4_DO = 0x33 +RA_I2C_SLV4_CTRL = 0x34 +RA_I2C_SLV4_DI = 0x35 +RA_I2C_MST_STATUS = 0x36 +RA_INT_PIN_CFG = 0x37 +RA_INT_ENABLE = 0x38 +RA_DMP_INT_STATUS = 0x39 +RA_INT_STATUS = 0x3A +RA_ACCEL_XOUT_H = 0x3B +RA_ACCEL_XOUT_L = 0x3C +RA_ACCEL_YOUT_H = 0x3D +RA_ACCEL_YOUT_L = 0x3E +RA_ACCEL_ZOUT_H = 0x3F +RA_ACCEL_ZOUT_L = 0x40 +RA_TEMP_OUT_H = 0x41 +RA_TEMP_OUT_L = 0x42 +RA_GYRO_XOUT_H = 0x43 +RA_GYRO_XOUT_L = 0x44 +RA_GYRO_YOUT_H = 0x45 +RA_GYRO_YOUT_L = 0x46 +RA_GYRO_ZOUT_H = 0x47 +RA_GYRO_ZOUT_L = 0x48 +RA_EXT_SENS_DATA_00 = 0x49 +RA_EXT_SENS_DATA_01 = 0x4A +RA_EXT_SENS_DATA_02 = 0x4B +RA_EXT_SENS_DATA_03 = 0x4C +RA_EXT_SENS_DATA_04 = 0x4D +RA_EXT_SENS_DATA_05 = 0x4E +RA_EXT_SENS_DATA_06 = 0x4F +RA_EXT_SENS_DATA_07 = 0x50 +RA_EXT_SENS_DATA_08 = 0x51 +RA_EXT_SENS_DATA_09 = 0x52 +RA_EXT_SENS_DATA_10 = 0x53 +RA_EXT_SENS_DATA_11 = 0x54 +RA_EXT_SENS_DATA_12 = 0x55 +RA_EXT_SENS_DATA_13 = 0x56 +RA_EXT_SENS_DATA_14 = 0x57 +RA_EXT_SENS_DATA_15 = 0x58 +RA_EXT_SENS_DATA_16 = 0x59 +RA_EXT_SENS_DATA_17 = 0x5A +RA_EXT_SENS_DATA_18 = 0x5B +RA_EXT_SENS_DATA_19 = 0x5C +RA_EXT_SENS_DATA_20 = 0x5D +RA_EXT_SENS_DATA_21 = 0x5E +RA_EXT_SENS_DATA_22 = 0x5F +RA_EXT_SENS_DATA_23 = 0x60 +RA_MOT_DETECT_STATUS = 0x61 +RA_I2C_SLV0_DO = 0x63 +RA_I2C_SLV1_DO = 0x64 +RA_I2C_SLV2_DO = 0x65 +RA_I2C_SLV3_DO = 0x66 +RA_I2C_MST_DELAY_CTRL = 0x67 +RA_SIGNAL_PATH_RESET = 0x68 +RA_MOT_DETECT_CTRL = 0x69 +RA_USER_CTRL = 0x6A +RA_PWR_MGMT_1 = 0x6B +RA_PWR_MGMT_2 = 0x6C +RA_BANK_SEL = 0x6D +RA_MEM_START_ADDR = 0x6E +RA_MEM_R_W = 0x6F +RA_DMP_CFG_1 = 0x70 +RA_DMP_CFG_2 = 0x71 +RA_FIFO_COUNTH = 0x72 +RA_FIFO_COUNTL = 0x73 +RA_FIFO_R_W = 0x74 +RA_WHO_AM_I = 0x75 + +TC_PWR_MODE_BIT = 7 +TC_OFFSET_BIT = 6 +TC_OFFSET_LENGTH = 6 +TC_OTP_BNK_VLD_BIT = 0 + +VDDIO_LEVEL_VLOGIC = 0 +VDDIO_LEVEL_VDD = 1 + +CFG_EXT_SYNC_SET_BIT = 5 +CFG_EXT_SYNC_SET_LENGTH = 3 +CFG_DLPF_CFG_BIT = 2 +CFG_DLPF_CFG_LENGTH = 3 + +EXT_SYNC_DISABLED = 0x0 +EXT_SYNC_TEMP_OUT_L = 0x1 +EXT_SYNC_GYRO_XOUT_L = 0x2 +EXT_SYNC_GYRO_YOUT_L = 0x3 +EXT_SYNC_GYRO_ZOUT_L = 0x4 +EXT_SYNC_ACCEL_XOUT_L = 0x5 +EXT_SYNC_ACCEL_YOUT_L = 0x6 +EXT_SYNC_ACCEL_ZOUT_L = 0x7 + +DLPF_BW_256 = 0x00 +DLPF_BW_188 = 0x01 +DLPF_BW_98 = 0x02 +DLPF_BW_42 = 0x03 +DLPF_BW_20 = 0x04 +DLPF_BW_10 = 0x05 +DLPF_BW_5 = 0x06 + +GCONFIG_FS_SEL_BIT = 4 +GCONFIG_FS_SEL_LENGTH = 2 + +GYRO_FS_250 = 0x00 +GYRO_FS_500 = 0x01 +GYRO_FS_1000 = 0x02 +GYRO_FS_2000 = 0x03 + +ACONFIG_XA_ST_BIT = 7 +ACONFIG_YA_ST_BIT = 6 +ACONFIG_ZA_ST_BIT = 5 +ACONFIG_AFS_SEL_BIT = 4 +ACONFIG_AFS_SEL_LENGTH = 2 +ACONFIG_ACCEL_HPF_BIT = 2 +ACONFIG_ACCEL_HPF_LENGTH = 3 + +ACCEL_FS_2 = 0x00 +ACCEL_FS_4 = 0x01 +ACCEL_FS_8 = 0x02 +ACCEL_FS_16 = 0x03 + +DHPF_RESET = 0x00 +DHPF_5 = 0x01 +DHPF_2P5 = 0x02 +DHPF_1P25 = 0x03 +DHPF_0P63 = 0x04 +DHPF_HOLD = 0x07 + +TEMP_FIFO_EN_BIT = 7 +XG_FIFO_EN_BIT = 6 +YG_FIFO_EN_BIT = 5 +ZG_FIFO_EN_BIT = 4 +ACCEL_FIFO_EN_BIT = 3 +SLV2_FIFO_EN_BIT = 2 +SLV1_FIFO_EN_BIT = 1 +SLV0_FIFO_EN_BIT = 0 + +MULT_MST_EN_BIT = 7 +WAIT_FOR_ES_BIT = 6 +SLV_3_FIFO_EN_BIT = 5 +I2C_MST_P_NSR_BIT = 4 +I2C_MST_CLK_BIT = 3 +I2C_MST_CLK_LENGTH = 4 + +CLOCK_DIV_348 = 0x0 +CLOCK_DIV_333 = 0x1 +CLOCK_DIV_320 = 0x2 +CLOCK_DIV_308 = 0x3 +CLOCK_DIV_296 = 0x4 +CLOCK_DIV_286 = 0x5 +CLOCK_DIV_276 = 0x6 +CLOCK_DIV_267 = 0x7 +CLOCK_DIV_258 = 0x8 +CLOCK_DIV_500 = 0x9 +CLOCK_DIV_471 = 0xA +CLOCK_DIV_444 = 0xB +CLOCK_DIV_421 = 0xC +CLOCK_DIV_400 = 0xD +CLOCK_DIV_381 = 0xE +CLOCK_DIV_364 = 0xF + +I2C_SLV_RW_BIT = 7 +I2C_SLV_ADDR_BIT = 6 +I2C_SLV_ADDR_LENGTH = 7 +I2C_SLV_EN_BIT = 7 +I2C_SLV_BYTE_SW_BIT = 6 +I2C_SLV_REG_DIS_BIT = 5 +I2C_SLV_GRP_BIT = 4 +I2C_SLV_LEN_BIT = 3 +I2C_SLV_LEN_LENGTH = 4 + +I2C_SLV4_RW_BIT = 7 +I2C_SLV4_ADDR_BIT = 6 +I2C_SLV4_ADDR_LENGTH = 7 +I2C_SLV4_EN_BIT = 7 +I2C_SLV4_INT_EN_BIT = 6 +I2C_SLV4_REG_DIS_BIT = 5 +I2C_SLV4_MST_DLY_BIT = 4 +I2C_SLV4_MST_DLY_LENGTH = 5 + +MST_PASS_THROUGH_BIT = 7 +MST_I2C_SLV4_DONE_BIT = 6 +MST_I2C_LOST_ARB_BIT = 5 +MST_I2C_SLV4_NACK_BIT = 4 +MST_I2C_SLV3_NACK_BIT = 3 +MST_I2C_SLV2_NACK_BIT = 2 +MST_I2C_SLV1_NACK_BIT = 1 +MST_I2C_SLV0_NACK_BIT = 0 + +INTCFG_INT_LEVEL_BIT = 7 +INTCFG_INT_OPEN_BIT = 6 +INTCFG_LATCH_INT_EN_BIT = 5 +INTCFG_INT_RD_CLEAR_BIT = 4 +INTCFG_FSYNC_INT_LEVEL_BIT = 3 +INTCFG_FSYNC_INT_EN_BIT = 2 +INTCFG_I2C_BYPASS_EN_BIT = 1 +INTCFG_CLKOUT_EN_BIT = 0 + +INTMODE_ACTIVEHIGH = 0x00 +INTMODE_ACTIVELOW = 0x01 + +INTDRV_PUSHPULL = 0x00 +INTDRV_OPENDRAIN = 0x01 + +INTLATCH_50USPULSE = 0x00 +INTLATCH_WAITCLEAR = 0x01 + +INTCLEAR_STATUSREAD = 0x00 +INTCLEAR_ANYREAD = 0x01 + +INTERRUPT_FF_BIT = 7 +INTERRUPT_MOT_BIT = 6 +INTERRUPT_ZMOT_BIT = 5 +INTERRUPT_FIFO_OFLOW_BIT = 4 +INTERRUPT_I2C_MST_INT_BIT = 3 +INTERRUPT_PLL_RDY_INT_BIT = 2 +INTERRUPT_DMP_INT_BIT = 1 +INTERRUPT_DATA_RDY_BIT = 0 + +# TODO: figure out what these actually do +# UMPL source code is not very obivous +DMPINT_5_BIT = 5 +DMPINT_4_BIT = 4 +DMPINT_3_BIT = 3 +DMPINT_2_BIT = 2 +DMPINT_1_BIT = 1 +DMPINT_0_BIT = 0 + +MOTION_MOT_XNEG_BIT = 7 +MOTION_MOT_XPOS_BIT = 6 +MOTION_MOT_YNEG_BIT = 5 +MOTION_MOT_YPOS_BIT = 4 +MOTION_MOT_ZNEG_BIT = 3 +MOTION_MOT_ZPOS_BIT = 2 +MOTION_MOT_ZRMOT_BIT = 0 + +DELAYCTRL_DELAY_ES_SHADOW_BIT = 7 +DELAYCTRL_I2C_SLV4_DLY_EN_BIT = 4 +DELAYCTRL_I2C_SLV3_DLY_EN_BIT = 3 +DELAYCTRL_I2C_SLV2_DLY_EN_BIT = 2 +DELAYCTRL_I2C_SLV1_DLY_EN_BIT = 1 +DELAYCTRL_I2C_SLV0_DLY_EN_BIT = 0 + +PATHRESET_GYRO_RESET_BIT = 2 +PATHRESET_ACCEL_RESET_BIT = 1 +PATHRESET_TEMP_RESET_BIT = 0 + +DETECT_ACCEL_ON_DELAY_BIT = 5 +DETECT_ACCEL_ON_DELAY_LENGTH = 2 +DETECT_FF_COUNT_BIT = 3 +DETECT_FF_COUNT_LENGTH = 2 +DETECT_MOT_COUNT_BIT = 1 +DETECT_MOT_COUNT_LENGTH = 2 + +DETECT_DECREMENT_RESET = 0x0 +DETECT_DECREMENT_1 = 0x1 +DETECT_DECREMENT_2 = 0x2 +DETECT_DECREMENT_4 = 0x3 + +USERCTRL_DMP_EN_BIT = 7 +USERCTRL_FIFO_EN_BIT = 6 +USERCTRL_I2C_MST_EN_BIT = 5 +USERCTRL_I2C_IF_DIS_BIT = 4 +USERCTRL_DMP_RESET_BIT = 3 +USERCTRL_FIFO_RESET_BIT = 2 +USERCTRL_I2C_MST_RESET_BIT = 1 +USERCTRL_SIG_COND_RESET_BIT = 0 + +PWR1_DEVICE_RESET_BIT = 7 +PWR1_SLEEP_BIT = 6 +PWR1_CYCLE_BIT = 5 +PWR1_TEMP_DIS_BIT = 3 +PWR1_CLKSEL_BIT = 2 +PWR1_CLKSEL_LENGTH = 3 + +CLOCK_INTERNAL = 0x00 +CLOCK_PLL_XGYRO = 0x01 +CLOCK_PLL_YGYRO = 0x02 +CLOCK_PLL_ZGYRO = 0x03 +CLOCK_PLL_EXT32K = 0x04 +CLOCK_PLL_EXT19M = 0x05 +CLOCK_KEEP_RESET = 0x07 + +PWR2_LP_WAKE_CTRL_BIT = 7 +PWR2_LP_WAKE_CTRL_LENGTH = 2 +PWR2_STBY_XA_BIT = 5 +PWR2_STBY_YA_BIT = 4 +PWR2_STBY_ZA_BIT = 3 +PWR2_STBY_XG_BIT = 2 +PWR2_STBY_YG_BIT = 1 +PWR2_STBY_ZG_BIT = 0 + +WAKE_FREQ_1P25 = 0x0 +WAKE_FREQ_2P5 = 0x1 +WAKE_FREQ_5 = 0x2 +WAKE_FREQ_10 = 0x3 + +BANKSEL_PRFTCH_EN_BIT = 6 +BANKSEL_CFG_USER_BANK_BIT = 5 +BANKSEL_MEM_SEL_BIT = 4 +BANKSEL_MEM_SEL_LENGTH = 5 + +WHO_AM_I_BIT = 6 +WHO_AM_I_LENGTH = 6 + +DMP_MEMORY_BANKS = 8 +DMP_MEMORY_BANK_SIZE = 256 +DMP_MEMORY_CHUNK_SIZE = 16 + +class Accel(object) : + """GY-521 Accelerometer.""" + + @staticmethod + def color( aR, aG, aB ) : + '''Create a 565 rgb TFTColor value''' + return TFTColor(aR, aG, aB) + + def __init__( self, aLoc, aAddress = ADDRESS_LOW ) : + """aLoc I2C pin location is either 1 for 'X' or 2 for 'Y'. + aAddress is either ADDRESS_LOW or ADDRESS_HIGH.""" + + if 1 > aLoc > 2 : + raise Exception("aLoc must be 1 or 2.") + + self._data = bytearray(1) + self._data6 = bytearray(6) + self._data14 = bytearray(14) + self._address = aAddress + self._i2c = pyb.I2C(aLoc, pyb.I2C.MASTER, baudrate = 400000) + + self.setclocksource(CLOCK_PLL_XGYRO) + self.setfullscalegyrorange(GYRO_FS_250) + self.setfulscaleaccelrange(ACCEL_FS_2) + self.setsleepenabled(False) + + def getrate( self ) : + self._readdata(RA_SMPLRT_DIV, self._data) + return self._data[0] + + def setrate( self, aRate ) : + self._writedata(RA_SMPLRT_DIV, aRate) + + def getDLPF( self ) : + return self._readbits(RA_CONFIG, CFG_DLPF_CFG_BIT, CFG_DLPF_CFG_LENGTH) + + def setDLPF( self, aMode ) : + self._writebits(RA_CONFIG, CFG_DLPF_CFG_BIT, CFG_DLPF_CFG_LENGTH, aMode) + + def setclocksource( self, aSource ) : + self._writebits(RA_PWR_MGMT_1, PWR1_CLKSEL_BIT, PWR1_CLKSEL_LENGTH, aSource) + + def getfullscalegyrorange( self ) : + return self._readbits(RA_GYRO_CONFIG, GCONFIG_FS_SEL_BIT, GCONFIG_FS_SEL_LENGTH) + + def setfullscalegyrorange( self, aRange ) : + self._writebits(RA_GYRO_CONFIG, GCONFIG_FS_SEL_BIT, GCONFIG_FS_SEL_LENGTH, aRange) + + def getfullscaleaccelrange( self ) : + self._readbits(RA_ACCEL_CONFIG, ACONFIG_AFS_SEL_BIT, ACONFIG_AFS_SEL_LENGTH) + + def setfullscaleaccelrange( self, aRange ) : + self._writebits(RA_ACCEL_CONFIG, ACONFIG_AFS_SEL_BIT, ACONFIG_AFS_SEL_LENGTH, aRange) + + def getsleepenabled( self ) : + self._readbits(RA_PWR_MGMT_1, PWR1_SLEEP_BIT, 1) + + def setsleepenabled( self, aTF ) : + self._writebits(RA_PWR_MGMT_1, PWR1_SLEEP_BIT, 1, aTF) + + def getfreefalldetectionthreshold( self ) : + self._readdata(RA_FF_THR, self._data) + return self._data[0] + + def setfreefalldetectionthreshold( self, aValue ) : + self._writedata(RA_FF_THR, aValue) + + def getfreefalldetectionduration( self ) : + self._readdata(RA_FF_DUR, self._data) + return self._data[0] + + def setfreefalldetectionduration( self, aValue ) : + self._writedata(RA_FF_DUR, aValue) + + def getmotiondetectionthreshold( self ) : + self._readdata(RA_MOT_THR, self._data) + return self._data[0] + + def setmotiondetectionthreshold( self, aValue ) : + self._writedata(RA_MOT_THR, aValue) + + def getmotiondetectionduration( self ) : + self._readdata(RA_MOT_DUR, self._data) + return self._data[0] + + def setmotiondetectionduration( self, aValue ) : + self._writedata(RA_MOT_DUR, aValue) + + def getzeromotiondetectionthreshold( self ) : + self._readdata(RA_ZRMOT_THR, self._data) + return self._data[0] + + def setzeromotiondetectionthreshold( self, aValue ) : + self._writedata(RA_ZRMOT_THR, aValue) + + def getzeromotiondetectionduration( self ) : + self._readdata(RA_ZRMOT_DUR, self._data) + return self._data[0] + + def setzeromotiondetectionduration( self, aValue ) : + self._writedata(RA_ZRMOT_DUR, aValue) + + def getFIFOenabled( self ) : + return self._readbits(RA_USER_CTRL, USERCTRL_FIFO_EN_BIT, 1) + + def setFIFFOenabled( self, aTF ) : + self._writebits(RA_USER_CTRL, USERCTRL_FIFO_EN_BIT, 1, aTF) + + def gettempFIFOenabled( self ) : + return self._readbits(RA_FIFO_EN, TEMP_FIFO_EN_BIT, 1) + + def settempFIFFOenabled( self, aTF ) : + self._writebits(RA_FIFO_EN, TEMP_FIFO_EN_BIT, 1, aTF) + + def getxgyroFIFOenabled( self ) : + return self._readbits(RA_FIFO_EN, XG_FIFO_EN_BIT, 1) + + def setxgyroFIFOenabled( self, aTF ) : + self._writebits(RA_FIFO_EN, XG_FIFO_EN_BIT, 1, aTF) + + def getygyroFIFOenabled( self ) : + return self._readbits(RA_FIFO_EN, YG_FIFO_EN_BIT, 1) + + def setygyroFIFOenabled( self, aTF ) : + self._writebits(RA_FIFO_EN, YG_FIFO_EN_BIT, 1, aTF) + + def getzgyroFIFOenabled( self ) : + return self._readbits(RA_FIFO_EN, ZG_FIFO_EN_BIT, 1) + + def setzgyroFIFOenabled( self, aTF ) : + self._writebits(RA_FIFO_EN, ZG_FIFO_EN_BIT, 1, aTF) + + def getaccelFIFOenabled( self ) : + return self._readbits(RA_FIFO_EN, ACCEL_FIFO_EN_BIT, 1) + + def setaccelFIFOenabled( self, aTF ) : + self._writebits(RA_FIFO_EN, ACCEL_FIFO_EN_BIT, 1, aTF) + + def getmasterclockspeed( self ) : + return self._readbits(RA_I2C_MST_CTRL, I2C_MST_CLK_BIT, I2C_MST_CLK_LENGTH) + + def setmasterclockspeed( self, aValue ) : + self._writebits(RA_I2C_MST_CTRL, I2C_MST_CLK_BIT, I2C_MST_CLK_LENGTH, aValue) + + def getinterruptmode( self ) : + return self._readbits(RA_INT_PIN_CFG, INTCFG_INT_LEVEL_BIT, 1) + + def setinterruptmode( self, aValue ) : + self._writebits(RA_INT_PIN_CFG, INTCFG_INT_LEVEL_BIT, 1, aValue) + + def getinterruptdrive( self ) : + return self._readbits(RA_INT_PIN_CFG, INTCFG_INT_OPEN_BIT, 1) + + def setinterruptdrive( self, aValue ) : + self._writebits(RA_INT_PIN_CFG, INTCFG_INT_OPEN_BIT, 1, aValue) + + def getinterruptlatch( self ) : + return self._readbits(RA_INT_PIN_CFG, INTCFG_LATCH_INT_EN_BIT, 1) + + def setinterruptlatch( self, aValue ) : + self._writebits(RA_INT_PIN_CFG, INTCFG_LATCH_INT_EN_BIT, 1, aValue) + + def getinterruptlatchclear( self ) : + return self._readbits(RA_INT_PIN_CFG, INTCFG_INT_RD_CLEAR_BIT, 1) + + def setinterruptlatchclear( self, aValue ) : + self._writebits(RA_INT_PIN_CFG, INTCFG_INT_RD_CLEAR_BIT, 1, aValue) + + def getacceltemprot( self ) : + self._readdata(RA_ACCEL_XOUT_H, self._data14) + return [(self._data14[i] << 8) | self._data14[i + 1] for i in range(0, len(self._data14), 2)] + + def getacceleration( self ) : + self._readdata(RA_ACCEL_XOUT_H, self._data6) + return [(self._data6[i] << 8) | self._data6[i + 1] for i in range(0, len(self._data6), 2)] + + def getrotation( self ) : + self._readdata(RA_GYRO_XOUT_H, self.data6) + return [(self._data6[i] << 8) | self._data6[i + 1] for i in range(0, len(self._data6), 2)] + + def reset( self ) : + self._writebits(RA_PWR_MGMT_1, PWR1_DEVICE_RESET_BIT, 1, True) + + def _writedata( self, aAddress, aData ) : + self._i2c.mem_write(aData, self._address, aAddress) + + def _readdata( self, aAddress, aData ) : + self._i2c.mem_read(aData, self._address, aAddress) + +# @micropython.native + def _readbits( self, aAddress, aStart, aLen ) : + self._readdata(aAddress, self._data) + b = (self._data[0] >> (aStart - aLen + 1)) & ((1 << aLen) - 1) + +# @micropython.native + def _writebits( self, aAddress, aStart, aLen, aValue ) : + self._readdata(aAddress, self._data) + mask = ((1 << aLen) - 1) << (aStart - aLen + 1) + aValue = (buffer[0] << (aStart - aLen + 1)) & mask #shift data into correct position + val &= ~mask + self._data[0] |= aValue + self._writedata(aAddress, self._data) + diff --git a/lib/IRDistance.py b/lib/IRDistance.py new file mode 100644 index 0000000..98a4984 --- /dev/null +++ b/lib/IRDistance.py @@ -0,0 +1,33 @@ + +from pyb import Pin, ADC + +class IRDistance(object): + """ Driver for Sharp Gp2y0a IR distance sensor. The distance + range is around 3 to 40 inches. """ + + maxinches = 31.5 #Maximun range of IR board in inches. + _v2i = -1.02 #Voltage to inches power. + + def __init__( self, pin ) : + """pin may be name or pin object. It must be able to handle ADC input.""" + + if type(pin) == str: + p = Pin(pin) + elif type(pin) == Pin: + p = pin + else: + raise Exception("pin must be pin name or pyb.Pin able to support ADC") + + self._adc = ADC(p) + + @property + def distance( self ) : return self._adc.read() + + @property + def inches( self ) : + volts = self.distance * 0.0048828125 + return 65.0 * pow(volts, IRDistance._v2i) + + @property + def centimeters( self ) : return self.inches * 2.54 + diff --git a/lib/JYMCU.py b/lib/JYMCU.py new file mode 100644 index 0000000..0146d7d --- /dev/null +++ b/lib/JYMCU.py @@ -0,0 +1,69 @@ + +from pyb import UART, repl_uart, udelay + +# JY-MCU Bluetooth board ---------------------------------------- + +# This opens connection with Bluetooth module connected to Y1, Y2 (UART 6) +# Then it sets the repl output to this UART. +#COMMANDS AT - does nothing but get an ok. +# The posible baudrates are: +# AT+BAUD1-------1200 +# AT+BAUD2-------2400 +# AT+BAUD3-------4800 +# AT+BAUD4-------9600 - Default for hc-06 +# AT+BAUD5------19200 +# AT+BAUD6------38400 +# AT+BAUD7------57600 - Johnny-five speed +# AT+BAUD8-----115200 +# AT+BAUD9-----230400 +# AT+BAUDA-----460800 +# AT+BAUDB-----921600 +# AT+BAUDC----1382400 +# AT+VERSION +# AT+NAMEnewname This is the name that will show up in windows. +# AT+PIN???? set 4 digit pairing pin. + +class JYMCU(object): + """JY-MCU Bluetooth serial device driver. This is simply a light UART wrapper + with addition AT command methods to customize the device.""" + + def __init__( self, uart, baudrate ): + """ uart = uart #1-6, baudrate must match what is set on the JY-MCU. + Needs to be a #1-C. """ + self._uart = UART(uart, baudrate) + + def __del__( self ) : self._uart.deinit() + + def any( self ) : return self._uart.any() + + def write( self, astring ) : return self._uart.write(astring) + def writechar( self, achar ) : self._uart.writechar(achar) + + def read( self, num = None ) : return self._uart.read(num) + def readline( self ) : return self._uart.readline() + def readchar( self ) : return self._uart.readchar() + def readall( self ) : return self._uart.readall() + def readinto( self, buf, count = None ) : return self._uart.readinto(buf, count) + + def _cmd( self, cmd ) : + """ Send AT command, wait a bit then return result string. """ + self._uart.write("AT+" + cmd) + udelay(500) + return self.readline() + + def baudrate( self, rate ) : + """ Set the baud rate. Needs to be #1-C. """ + return self._cmd("BAUD" + str(rate)) + + def name( self, name ) : + """ Set the name to show up on the connecting device. """ + return self._cmd("NAME" + name) + + def pin( self, pin ) : + """ Set the given 4 digit numeric pin. """ + return self._cmd("PIN" + str(pin)) + + def version( self ) : return self._cmd("VERSION") + + def setrepl( self ) : repl_uart(self._uart) + diff --git a/lib/L298N.py b/lib/L298N.py new file mode 100644 index 0000000..de8c78b --- /dev/null +++ b/lib/L298N.py @@ -0,0 +1,43 @@ +#Driver for the L298N Dual HBridge motor controller. + +from PWM import PWM +from pyb import Pin, delay + +class Motor( ): + """Control a motor connected to the L298N Dual motor controller.""" + + def __init__( self, forward, backward, speed ) : + """forward pin name, backward pin name, speed = (pin name, timer#) + Need to make sure the given timer # is associated with the speed + pin or an exception will be raised. The speed pin must support + PWM.""" + self._forward = Pin(forward, Pin.OUT_PP) + self._backward = Pin(backward, Pin.OUT_PP) + self._speedControl = PWM(speed[0], speed[1]) + self._speed = 0 + + @property + def speed( self ) : return self._speed + + @speed.setter + def speed( self, value ) : + self._speed = value + if (value == 0): + self._forward.low() + self._backward.low() + elif (value < 0): + self._forward.low() + self._backward.high() + else: + self._forward.high() + self._backward.low() + + self._speedControl.pulse_width_percent = min(100, abs(value)) + + def brake( self ) : + """ Brake the motor by sending power both directions. """ + self._forward.high() + self._backward.high() + self._speedControl.pulse_width_percent = 100 + delay(1000) + self.speed = 0 diff --git a/lib/OLED.py b/lib/OLED.py new file mode 100644 index 0000000..2e47c1a --- /dev/null +++ b/lib/OLED.py @@ -0,0 +1,347 @@ +#driver for Sainsmart 1.8" TFT display ST7735 +#Translated by Guy Carver from the ST7735 sample code. + +#NOTE: This current code will set the pixel at 0,0 but the scrolling will not scroll it. Don't know if it's software causing it or not. + +import pyb + +_I2C_ADDRESS = const(0x3C) # 011110+SA0+RW - 0x3C or 0x3D + +_SETCONTRAST = const(0x81) +_DISPLAYALLON_RESUME = const(0xA4) +_DISPLAYALLON = const(0xA5) +_NORMALDISPLAY = const(0xA6) +_INVERTDISPLAY = const(0xA7) +_DISPLAYOFF = const(0xAE) +_DISPLAYON = const(0xAF) + +_SETDISPLAYOFFSET = const(0xD3) +_SETCOMPINS = const(0xDA) + +_SETVCOMDETECT = const(0xDB) + +_SETDISPLAYCLOCKDIV = const(0xD5) +_SETPRECHARGE = const(0xD9) + +_SETMULTIPLEX = const(0xA8) + +_SETLOWCOLUMN = const(0x00) +_SETHIGHCOLUMN = const(0x10) + +_SETSTARTLINE = const(0x40) + +_MEMORYMODE = const(0x20) + +_COMSCANINC = const(0xC0) +_COMSCANDEC = const(0xC8) + +_SEGREMAP = const(0xA0) + +_CHARGEPUMP = const(0x8D) + +_EXTRNALVCC = const(0x1) +_SWITCHAPVCC = const(0x2) + +_ACTIVATE_SCROLL = const(0x2F) +_DEACTIVATE_SCROLL = const(0x2E) +_SET_VERTICAL_SCROLL_AREA = const(0xA3) +_RIGHT_HORIZONTAL_SCROLL = const(0x26) +_LEFT_HORIZONTAL_SCROLL = const(0x27) +_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = const(0x29) +_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = const(0x2A) + +#Buffer layout in bits. 128 columns by 64 rows. +#Each byte represents 8 pixels in a row. +# Column +# R 0 8 10 ... 3F8 +# O 1 9 11 ... 3F9 +# W 2 A 12 ... 3FA +# 3 B 13 ... 3FB +# 4 C 14 ... 3FC +# 5 D 15 ... 3FD +# 6 E 16 ... 3FE +# 7 F 17 ... 3FF +# 400 408 +# 401 409 +# 402 40A +# 403 40B +# 404 40C +# 405 40D +# 406 40E +# 407 40F + +class OLED(object) : + """diyMall OLED 9.6 128x64 pixel display driver.""" + + def __init__( self, aLoc ) : + """aLoc I2C pin location is either 1 for 'X' or 2 for 'Y'.""" + self._size = (128, 64) + self._rotation = 0 + self._inverted = False + self._on = False + self.i2c = pyb.I2C(aLoc, pyb.I2C.MASTER, baudrate = 200000) + self.bytes = self.size[0] * self.size[1] // 8 + self.buffer = bytearray(self.bytes + 1) + self.buffer[0] = 0x40 #data write start command at very start of buffer. + + self.data = bytearray(2) + self.data[0] = 0 + + self.command = _DISPLAYOFF + self.command = _SETDISPLAYCLOCKDIV + self.command = 0x80 #suggested ratio. + self.command = _SETMULTIPLEX + self.command = 0x3F + self.command = _SETDISPLAYOFFSET + self.command = 0x0 + self.command = _SETSTARTLINE #| 0x0 + self.command = _CHARGEPUMP + self.command = 0x14 #No external power. + self.command = _MEMORYMODE + self.command = 0x00 #Act like ks0108 + self.command = _SEGREMAP + 0x01 + self.command = _COMSCANDEC + self.command = _SETCOMPINS + self.command = 0x12 + self.command = _SETCONTRAST + self.command = 0xCF + self.command = _SETPRECHARGE + self.command = 0xF1 + self.command = _SETVCOMDETECT + self.command = 0x40 + self.command = _DISPLAYALLON_RESUME + self.command = _NORMALDISPLAY + self.command = 0XB0 + self.command = 0x10 + self.command = 0x01 #Set original position to 0,0. + + self.on = True + + self.display() + + @property + def size( self ) : return self._size + + @property + def rotation( self ) : return self._rotation + + @rotation.setter + def rotation( self, aValue ) : + self._rotation = aValue & 3 + + def write( self, aValue ) : + self.i2c.send(aValue, _I2C_ADDRESS) + + @property + def command( self ) : return 0 + + @command.setter + def command( self, aValue ) : + self.data[1] = aValue + self.write(self.data) + + @property + def on( self ) : return self._on + + @on.setter + def on( self, aTF ) : + if aTF != self._on : + self._on = aTF + '''Turn display on or off.''' + self.command = _DISPLAYON if aTF else _DISPLAYOFF + + @property + def invert( self ) : return self._inverted + + @invert.setter + def invert( self, aTF ) : + if aTF != self._inverted : + self._inverted = aTF + self.command = _INVERTDISPLAY if aTF else _NORMALDISPLAY + + @micropython.native + def fill( self, aValue ) : + for x in range(1, self.bytes + 1): + self.buffer[x] = aValue; + + def clear( self ) : + self.fill(0) + + @micropython.native + def pixel( self, aPos, aOn ) : + '''Draw a pixel at the given position''' + x, y = aPos + w, h = self.size + if 0 <= x < w and 0 <= y < h: + if self._rotation == 1: + aPos = (w - y - 1, x) + elif self._rotation == 2: + aPos = (w - x - 1, h - y - 1) + elif self._rotation == 3: + aPos = (y, h - x - 1) + + bit = 1 << (aPos[1] % 8) + index = (aPos[0] + (aPos[1] // 8) * w) + 1 + + if aOn : + self.buffer[index] |= bit + else : + self.buffer[index] &= not bit + + @micropython.native + def line( self, aStart, aEnd, aOn ) : + '''Draws a line from aStart to aEnd in the given color. Vertical or horizontal + lines are forwarded to vline and hline.''' + px, py = aStart + ex, ey = aEnd + dx = ex - px + dy = ey - py + inx = 1 if dx > 0 else -1 + iny = 1 if dy > 0 else -1 + + dx = abs(dx) + dy = abs(dy) + if (dx >= dy): + dy <<= 1 + e = dy - dx + dx <<= 1 + while (px != ex): + self.pixel((px, py), aOn) + if (e >= 0): + py += iny + e -= dx + e += dy + px += inx + else: + dx <<= 1 + e = dx - dy + dy <<= 1 + while (py != ey): + self.pixel((px, py), aOn) + if (e >= 0): + px += inx + e -= dy + e += dx + py += iny + +# @micropython.native + def fillrect( self, aStart, aSize, aOn ) : + '''Draw a filled rectangle. aStart is the smallest coordinate corner + and aSize is a tuple indicating width, height.''' + x, y = aStart + w, h = aSize + ex = x + w + for i in range(y, y + h): + self.line((x, i), (ex, i), aOn) + + @micropython.native + def text( self, aPos, aString, aColor, aFont, aSize = 1 ) : + '''Draw a text at the given position. If the string reaches the end of the + display it is wrapped to aPos[0] on the next line. aSize may be an integer + which will size the font uniformly on w,h or a or any type that may be + indexed with [0] or [1].''' + + if aFont == None: + return + + #Make a size either from single value or 2 elements. + if (type(aSize) == int) or (type(aSize) == float): + wh = (aSize, aSize) + else: + wh = aSize + + px, py = aPos + width = wh[0] * aFont["Width"] + 1 + for c in aString: + self.char((px, py), c, aColor, aFont, wh) + px += width + #We check > rather than >= to let the right (blank) edge of the + # character print off the right of the screen. + if px + width > self._size[0]: + py += aFont["Height"] * wh[1] + 1 + px = aPos[0] + + @micropython.native + def char( self, aPos, aChar, aOn, aFont, aSizes ) : + '''Draw a character at the given position using the given font and color. + aSizes is a tuple with x, y as integer scales indicating the + # of pixels to draw for each pixel in the character.''' + + if aFont == None: + return + + startchar = aFont['Start'] + endchar = aFont['End'] + + ci = ord(aChar) + if (startchar <= ci <= endchar): + fontw = aFont['Width'] + fonth = aFont['Height'] + ci = (ci - startchar) * fontw + + charA = aFont["Data"][ci:ci + fontw] + px = aPos[0] + if aSizes[0] <= 1 and aSizes[1] <= 1 : + for c in charA : + py = aPos[1] + for r in range(fonth) : + if c & 0x01 : + self.pixel((px, py), aOn) + py += 1 + c >>= 1 + px += 1 + else: + for c in charA : + py = aPos[1] + for r in range(fonth) : + if c & 0x01 : + self.fillrect((px, py), aSizes, aOn) + py += aSizes[1] + c >>= 1 + px += aSizes[0] + + def doscrollLR( self, start, stop, aDir ) : + self.command = aDir + self.command = 0x00 + self.command = start + self.command = 0x00 + self.command = stop + self.command = 0x01 + self.command = 0xFF + self.command = _ACTIVATE_SCROLL + + def startscrollright( self, start, stop ) : + self.doscrollLR(start, stop, _RIGHT_HORIZONTAL_SCROLL) + + def startscrollleft( self, start, stop ) : + self.doscrollLR(start, stop, _LEFT_HORIZONTAL_SCROLL) + + def doscrollDiag( self, start, stop, aDir ) : + self.command = _SET_VERTICAL_SCROLL_AREA + self.command = 0x00 + self.command = self.size()[1] + self.command = aDir + self.command = 0x00 + self.command = start + self.command = 0x00 + self.command = stop + self.command = 0x01 + self.command = _ACTIVATE_SCROLL + + def startscrolldiagright( self, start, stop ) : + self.doscrollDiag(start, stop, _VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL) + + def startscrolldiagleft( self, start, stop ) : + self.doscrollDiag(start, stop, _VERTICAL_AND_LEFT_HORIZONTAL_SCROLL) + + def stopscroll( self ) : + self.command = _DEACTIVATE_SCROLL + + def display( self ) : + self.command = _SETLOWCOLUMN #| 0x00 + self.command = _SETHIGHCOLUMN #| 0x00 + self.command = _SETSTARTLINE #| 0x00 + #buffer starts with 0x40 in 1st byte which is the command to start the buffer write. + self.write(self.buffer) + + diff --git a/lib/PIR.py b/lib/PIR.py new file mode 100644 index 0000000..d83a6fa --- /dev/null +++ b/lib/PIR.py @@ -0,0 +1,72 @@ +#Passive infrared motipower sensor. + +import pyb + +class PIR(object): + """Passive Infrared Motion Sensor driver. Supports on/off through an output pin + trigger reading as well as an interrupt callback on trigger high/low changes.""" + + def __init__(self, power, trigger, callback = None): + """Power and trigger pins, optional interrupt callback in the format + of fun( bOnOff ). This will be called whenever the trigger state + changes.""" + if power != None: + self._power = pyb.Pin(power, pyb.Pin.OUT_PP) + self._power.low() + else: + self._power = None + self._trigger = pyb.Pin(trigger, pyb.Pin.IN, pyb.Pin.PULL_DOWN) + self.interrupt = callback + + def _onoff( self, aTF ) : + """Turn device on/off""" + if (self._power != None): + if (aTF): + oldon = self.inton + self.inton = False #Make sure interrupt is off while turning on power to avoid false callbacks. + self._power.high() + if (oldon): + pyb.delay(200) #Need to wait a bit after turning on to make sure we don't get false values. + self.inton = oldon + else: + self._power.low() + + @property + def power( self ) : return True if (self._power == None) else self._power.value() + + @power.setter + def power( self, value ) : self._onoff(value) + + def on( self ) : self.power = True + def off( self ) : self.power = False + + @property + def trigger( self ) : return self._trigger.value() + + @property + def interrupt( self ) : return self._interrupt + + @interrupt.setter + def interrupt( self, func ) : + self._interrupt = None; + self._func = func + if (func != None): + self._interrupt = pyb.ExtInt(self._trigger, pyb.ExtInt.IRQ_RISING_FALLING, pyb.Pin.PULL_DOWN, self._inthandler) + self._inton = True + + def _inthandler( self, line ) : + '''Function to handle interrupts and pass on to callback with on/off trigger state.''' + if (self._func != None): + self._func(self.trigger) + + @property + def inton( self ) : return self._inton + + @inton.setter + def inton( self, value ) : + self._inton = value + if self._interrupt != None: + if value : + self._interrupt.enable() + else: + self._interrupt.disable() diff --git a/lib/PWM.py b/lib/PWM.py new file mode 100644 index 0000000..da0d542 --- /dev/null +++ b/lib/PWM.py @@ -0,0 +1,81 @@ +# PWM driver. + +from pyb import Timer, Pin + +class PWM(object): + """docstring for PWMM""" + + #Dict pin name: timer #, channel #. + PinChannels = { + 'X1': [(2,1), (5,1)], + 'X2': [(2,2), (5,2)], + 'X3': [(2,3), (5,3), (9,1)], + 'X4': [(2,4), (5,4), (9,2)], + 'X6': [(2,1), (8,1)], + 'X7': [(13, 1)], + 'X8': [(1,1), (8,1), (14,1)], + 'X9': [(4,1)], + 'X10': [(4,2)], + 'Y1': [(8,1)], + 'Y2': [(8,2)], + 'Y3': [(4,3), (10,1)], + 'Y4': [(4,4), (11,1)], + 'Y6': [(1,1)], + 'Y7': [(1,2), (8,2), (12,1)], + 'Y8': [(1,3), (8,3), (12,2)], + 'Y9': [(2,3)], + 'Y10': [(2,4)], + 'Y11': [(1,2), (8,2)], + 'Y12': [(1,3), (8,3)] + } + + class PWMException(Exception): + def __init__( self, msg ) : + self.msg = msg + + @staticmethod + def timerandchannel( pinname, timernum ) : + try: + a = PWM.PinChannels[pinname] + if timernum <= 0: + return a[0] + else: + for v in a: + if v[0] == timernum: + return v + except Exception as e : + raise PWM.PWMException("Pin {} cannot be used for PWM".format(pinname)) + + raise PWM.PWMException("Pin {} cannot use timer {}".format(pinname, timernum)) + + def __init__( self, p, timernum, afreq = 100 ) : + isname = type(p) == str + pinname = p if isname else p.name() + timernum, channel = PWM.timerandchannel(pinname, timernum) + if isname: + p = Pin(pinname) + + self._timer = Timer(timernum, freq = afreq) + self._channel = self._timer.channel(channel, Timer.PWM, pin = p) + + @property + def pulse_width( self ) : return self._channel.pulse_width() + + @pulse_width.setter + def pulse_width( self, value ) : self._channel.pulse_width(value) + + @property + def pulse_width_percent( self ) : return self._channel.pulse_width_percent() + + @pulse_width_percent.setter + def pulse_width_percent( self, value ) : self._channel.pulse_width_percent(value) + + @property + def freq( self ) : return self._timer.freq() + + @freq.setter + def freq( self, value ) : self._timer.freq(value) + + def callback( self, value ) : + self._channel.callback(value) + diff --git a/lib/Relay.py b/lib/Relay.py new file mode 100644 index 0000000..aba705e --- /dev/null +++ b/lib/Relay.py @@ -0,0 +1,30 @@ +#Control a relay board. + +from pyb import Pin + +class Relay(object): + """Control a relay board with an output pin. Set on to True to drive the relay pin low + which turns the relay on.""" + + def __init__( self, pin ) : + """Pin may be a pin name or pyb.Pin object set for output.""" + + if type(pin) == str: + self._pin = Pin(pin, Pin.OUT_PP, Pin.PULL_DOWN) + elif type(pin) == Pin: + self._pin = pin + else: + raise Exception("pin must be pin name or pyb.Pin") + + self.on = False + + @property + def on( self ) : return self._pin.value() + + @on.setter + def on( self, value ) : + if value: + self._pin.low() + else: + self._pin.high() + diff --git a/lib/SR04Distance.py b/lib/SR04Distance.py new file mode 100644 index 0000000..05448bf --- /dev/null +++ b/lib/SR04Distance.py @@ -0,0 +1,71 @@ + +from pyb import Pin, Timer, udelay + +# WARNING: Do not use PA4-X5 or PA5-X6 as the echo pin without a 1k resistor. + +class SR04Distance(object): + """ """ + + maxinches = 20 #maximum range of SR04. + + def __init__( self, tpin, epin, timer=2 ) : + """ """ + + if type(tpin) == str: + self._tpin = Pin(tpin, Pin.OUT_PP, Pin.PULL_NONE) + elif type(tpin) == Pin: + self._tpin = tpin + else: + raise Exception("trigger pin must be pin name or pyb.Pin configured for output.") + + self._tpin.low() + + if type(epin) == str: + self._epin = Pin(epin, Pin.IN, Pin.PULL_NONE) + elif type(epin) == Pin: + self._epin = epin + else: + raise Exception("echo pin must be pin name or pyb.Pin configured for input.") + + # Create a microseconds counter. + self._micros = Timer(timer, prescaler=83, period=0x3fffffff) + + def __del__( self ) : + self._micros.deinit() + + @property + def counter( self ) : return self._micros.counter() + + @counter.setter + def counter( self, value ) : self._micros.counter(value) + + @property + def centimeters( self ) : + start = 0 + end = 0 + + self.counter = 0 + + #Send 10us pulse. + self._tpin.high() + udelay(10) + self._tpin.low() + + while not self._epin.value(): + start = self.counter + + j = 0 + + # Wait 'till the pulse is gone. + while self._epin.value() and j < 1000: + j += 1 + end = self.counter + + # Calc the duration of the recieved pulse, divide the result by + # 2 (round-trip) and divide it by 29 (the speed of sound is + # 340 m/s and that is 29 us/cm). + return (end - start) / 58 + + @property + def inches( self ) : return self.centimeters * 0.3937 + diff --git a/lib/ST7735.py b/lib/ST7735.py new file mode 100644 index 0000000..e894340 --- /dev/null +++ b/lib/ST7735.py @@ -0,0 +1,763 @@ +#driver for Sainsmart 1.8" TFT display ST7735 +#Translated by Guy Carver from the ST7735 sample code. + +import pyb +from math import sqrt + +#TFTRotations and TFTRGB are bits to set +# on MADCTL to control display rotation/color layout +#Looking at display with pins on top. +#00 = upper left printing right +#10 = does nothing (MADCTL_ML) +#20 = upper left printing down (backwards) (Vertical flip) +#40 = upper right printing left (backwards) (X Flip) +#80 = lower left printing right (backwards) (Y Flip) +#04 = (MADCTL_MH) + +#60 = 90 right rotation +#C0 = 180 right rotation +#A0 = 270 right rotation +TFTRotations = [0x00, 0x60, 0xC0, 0xA0] +TFTBGR = 0x08 #When set color is bgr else rgb. +TFTRGB = 0x00 + +@micropython.native +def clamp( aValue, aMin, aMax ) : + return max(aMin, min(aMax, aValue)) + +@micropython.native +def TFTColor( aR, aG, aB ) : + '''Create a 16 bit rgb value from the given R,G,B from 0-255. + This assumes rgb 565 layout and will be incorrect for bgr.''' + return ((aR & 0xF8) << 8) | ((aG & 0xFC) << 3) | (aB >> 3) + +ScreenSize = (128, 160) + +class TFT(object) : + """Sainsmart TFT 7735 display driver.""" + + NOP = 0x0 + SWRESET = 0x01 + RDDID = 0x04 + RDDST = 0x09 + + SLPIN = 0x10 + SLPOUT = 0x11 + PTLON = 0x12 + NORON = 0x13 + + INVOFF = 0x20 + INVON = 0x21 + DISPOFF = 0x28 + DISPON = 0x29 + CASET = 0x2A + RASET = 0x2B + RAMWR = 0x2C + RAMRD = 0x2E + + COLMOD = 0x3A + MADCTL = 0x36 + + FRMCTR1 = 0xB1 + FRMCTR2 = 0xB2 + FRMCTR3 = 0xB3 + INVCTR = 0xB4 + DISSET5 = 0xB6 + + PWCTR1 = 0xC0 + PWCTR2 = 0xC1 + PWCTR3 = 0xC2 + PWCTR4 = 0xC3 + PWCTR5 = 0xC4 + VMCTR1 = 0xC5 + + RDID1 = 0xDA + RDID2 = 0xDB + RDID3 = 0xDC + RDID4 = 0xDD + + PWCTR6 = 0xFC + + GMCTRP1 = 0xE0 + GMCTRN1 = 0xE1 + + BLACK = 0 + RED = TFTColor(0xFF, 0x00, 0x00) + MAROON = TFTColor(0x80, 0x00, 0x00) + GREEN = TFTColor(0x00, 0xFF, 0x00) + FOREST = TFTColor(0x00, 0x80, 0x80) + BLUE = TFTColor(0x00, 0x00, 0xFF) + NAVY = TFTColor(0x00, 0x00, 0x80) + CYAN = TFTColor(0x00, 0xFF, 0xFF) + YELLOW = TFTColor(0xFF, 0xFF, 0x00) + PURPLE = TFTColor(0xFF, 0x00, 0xFF) + WHITE = TFTColor(0xFF, 0xFF, 0xFF) + GRAY = TFTColor(0x80, 0x80, 0x80) + + @staticmethod + def color( aR, aG, aB ) : + '''Create a 565 rgb TFTColor value''' + return TFTColor(aR, aG, aB) + + def __init__( self, aLoc, aDC, aReset ) : + """aLoc SPI pin location is either 1 for 'X' or 2 for 'Y'. + aDC is the DC pin and aReset is the reset pin.""" + self._size = ScreenSize + self.rotate = 0 #Vertical with top toward pins. + self._rgb = True #color order of rgb. + self.dc = pyb.Pin(aDC, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN) + self.reset = pyb.Pin(aReset, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN) + rate = 200000 #100000000 #Set way high but will be clamped to a maximum in SPI constructor. + cs = "X5" if aLoc == 1 else "Y5" + self.cs = pyb.Pin(cs, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN) + self.cs.high() + self.spi = pyb.SPI(aLoc, pyb.SPI.MASTER, baudrate = rate, polarity = 1, phase = 0, crc=None) + self.colorData = bytearray(2) + self.windowLocData = bytearray(4) + + def size( self ) : + return self._size + +# @micropython.native + def on( self, aTF = True ) : + '''Turn display on or off.''' + self._writecommand(TFT.DISPON if aTF else TFT.DISPOFF) + +# @micropython.native + def invertcolor( self, aBool ) : + '''Invert the color data IE: Black = White.''' + self._writecommand(TFT.INVON if aBool else TFT.INVOFF) + +# @micropython.native + def rgb( self, aTF = True ) : + '''True = rgb else bgr''' + self._rgb = aTF + self._setMADCTL() + +# @micropython.native + def rotation( self, aRot ) : + '''0 - 3. Starts vertical with top toward pins and rotates 90 deg + clockwise each step.''' + if (0 <= aRot < 4): + rotchange = self.rotate ^ aRot + self.rotate = aRot + #If switching from vertical to horizontal swap x,y + # (indicated by bit 0 changing). + if (rotchange & 1): + self._size =(self._size[1], self._size[0]) + self._setMADCTL() + + @micropython.native + def pixel( self, aPos, aColor ) : + '''Draw a pixel at the given position''' + if 0 <= aPos[0] < self._size[0] and 0 <= aPos[1] < self._size[1]: + self._setwindowpoint(aPos) + self._pushcolor(aColor) + +# @micropython.native + def text( self, aPos, aString, aColor, aFont, aSize = 1 ) : + '''Draw a text at the given position. If the string reaches the end of the + display it is wrapped to aPos[0] on the next line. aSize may be an integer + which will size the font uniformly on w,h or a or any type that may be + indexed with [0] or [1].''' + + if aFont == None: + return + + #Make a size either from single value or 2 elements. + if (type(aSize) == int) or (type(aSize) == float): + wh = (aSize, aSize) + else: + wh = aSize + + px, py = aPos + width = wh[0] * aFont["Width"] + 1 + for c in aString: + self.char((px, py), c, aColor, aFont, wh) + px += width + #We check > rather than >= to let the right (blank) edge of the + # character print off the right of the screen. + if px + width > self._size[0]: + py += aFont["Height"] * wh[1] + 1 + px = aPos[0] + +# @micropython.native + def char( self, aPos, aChar, aColor, aFont, aSizes ) : + '''Draw a character at the given position using the given font and color. + aSizes is a tuple with x, y as integer scales indicating the + # of pixels to draw for each pixel in the character.''' + + if aFont == None: + return + + startchar = aFont['Start'] + endchar = aFont['End'] + + ci = ord(aChar) + if (startchar <= ci <= endchar): + fontw = aFont['Width'] + fonth = aFont['Height'] + ci = (ci - startchar) * fontw + + charA = aFont["Data"][ci:ci + fontw] + px = aPos[0] + if aSizes[0] <= 1 and aSizes[1] <= 1 : + for c in charA : + py = aPos[1] + for r in range(fonth) : + if c & 0x01 : + self.pixel((px, py), aColor) + py += 1 + c >>= 1 + px += 1 + else: + for c in charA : + py = aPos[1] + for r in range(fonth) : + if c & 0x01 : + self.fillrect((px, py), aSizes, aColor) + py += aSizes[1] + c >>= 1 + px += aSizes[0] + +# @micropython.native + def line( self, aStart, aEnd, aColor ) : + '''Draws a line from aStart to aEnd in the given color. Vertical or horizontal + lines are forwarded to vline and hline.''' + if aStart[0] == aEnd[0]: + #Make sure we use the smallest y. + pnt = aEnd if (aEnd[1] < aStart[1]) else aStart + self.vline(pnt, abs(aEnd[1] - aStart[1]) + 1, aColor) + elif aStart[1] == aEnd[1]: + #Make sure we use the smallest x. + pnt = aEnd if aEnd[0] < aStart[0] else aStart + self.hline(pnt, abs(aEnd[0] - aStart[0]) + 1, aColor) + else: + px, py = aStart + ex, ey = aEnd + dx = ex - px + dy = ey - py + inx = 1 if dx > 0 else -1 + iny = 1 if dy > 0 else -1 + + dx = abs(dx) + dy = abs(dy) + if (dx >= dy): + dy <<= 1 + e = dy - dx + dx <<= 1 + while (px != ex): + self.pixel((px, py), aColor) + if (e >= 0): + py += iny + e -= dx + e += dy + px += inx + else: + dx <<= 1 + e = dx - dy + dy <<= 1 + while (py != ey): + self.pixel((px, py), aColor) + if (e >= 0): + px += inx + e -= dy + e += dx + py += iny + +# @micropython.native + def vline( self, aStart, aLen, aColor ) : + '''Draw a vertical line from aStart for aLen. aLen may be negative.''' + start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1])) + stop = (start[0], clamp(start[1] + aLen, 0, self._size[1])) + #Make sure smallest y 1st. + if (stop[1] < start[1]): + start, stop = stop, start + self._setwindowloc(start, stop) + self._draw(aLen, aColor) + +# @micropython.native + def hline( self, aStart, aLen, aColor ) : + '''Draw a horizontal line from aStart for aLen. aLen may be negative.''' + start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1])) + stop = (clamp(start[0] + aLen, 0, self._size[0]), start[1]) + #Make sure smallest x 1st. + if (stop[0] < start[0]): + start, stop = stop, start + self._setwindowloc(start, stop) + self._draw(aLen, aColor) + +# @micropython.native + def rect( self, aStart, aSize, aColor ) : + '''Draw a hollow rectangle. aStart is the smallest coordinate corner + and aSize is a tuple indicating width, height.''' + self.hline(aStart, aSize[0], aColor) + self.hline((aStart[0], aStart[1] + aSize[1] - 1), aSize[0], aColor) + self.vline(aStart, aSize[1], aColor) + self.vline((aStart[0] + aSize[0] - 1, aStart[1]), aSize[1], aColor) + +# @micropython.native + def fillrect( self, aStart, aSize, aColor ) : + '''Draw a filled rectangle. aStart is the smallest coordinate corner + and aSize is a tuple indicating width, height.''' + start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1])) + end = (clamp(start[0] + aSize[0] - 1, 0, self._size[0]), clamp(start[1] + aSize[1] - 1, 0, self._size[1])) + + if (end[0] < start[0]): + tmp = end[0] + end = (start[0], end[1]) + start = (tmp, start[1]) + if (end[1] < start[1]): + tmp = end[1] + end = (end[0], start[1]) + start = (start[0], tmp) + + self._setwindowloc(start, end) + numPixels = (end[0] - start[0] + 1) * (end[1] - start[1] + 1) + self._draw(numPixels, aColor) + +# @micropython.native + def circle( self, aPos, aRadius, aColor ) : + '''Draw a hollow circle with the given radius and color with aPos as center.''' + self.colorData[0] = aColor >> 8 + self.colorData[1] = aColor + xend = int(0.7071 * aRadius) + 1 + rsq = aRadius * aRadius + for x in range(xend) : + y = int(sqrt(rsq - x * x)) + xp = aPos[0] + x + yp = aPos[1] + y + xn = aPos[0] - x + yn = aPos[1] - y + xyp = aPos[0] + y + yxp = aPos[1] + x + xyn = aPos[0] - y + yxn = aPos[1] - x + + self._setwindowpoint((xp, yp)) + self._writedata(self.colorData) + self._setwindowpoint((xp, yn)) + self._writedata(self.colorData) + self._setwindowpoint((xn, yp)) + self._writedata(self.colorData) + self._setwindowpoint((xn, yn)) + self._writedata(self.colorData) + self._setwindowpoint((xyp, yxp)) + self._writedata(self.colorData) + self._setwindowpoint((xyp, yxn)) + self._writedata(self.colorData) + self._setwindowpoint((xyn, yxp)) + self._writedata(self.colorData) + self._setwindowpoint((xyn, yxn)) + self._writedata(self.colorData) + +# @micropython.native + def fillcircle( self, aPos, aRadius, aColor ) : + '''Draw a filled circle with given radius and color with aPos as center''' + rsq = aRadius * aRadius + for x in range(aRadius) : + y = int(sqrt(rsq - x * x)) + y0 = aPos[1] - y + ey = y0 + y * 2 + y0 = clamp(y0, 0, self._size[1]) + ln = abs(ey - y0) + 1; + + self.vline((aPos[0] + x, y0), ln, aColor) + self.vline((aPos[0] - x, y0), ln, aColor) + + def fill( self, aColor = BLACK ) : + '''Fill screen with the given color.''' + self.fillrect((0, 0), self._size, aColor) + +# @micropython.native + def _draw( self, aPixels, aColor ) : + '''Send given color to the device aPixels times.''' + self.colorData[0] = aColor >> 8 + self.colorData[1] = aColor + + self.dc.high() + self.cs.low() + for i in range(aPixels): + self.spi.send(self.colorData) + self.cs.high() + +# @micropython.native + def _setwindowpoint( self, aPos ) : + '''Set a single point for drawing a color to.''' + x = int(aPos[0]) + y = int(aPos[1]) + self._writecommand(TFT.CASET) #Column address set. + self.windowLocData[0] = 0x00 + self.windowLocData[1] = x + self.windowLocData[2] = 0x00 + self.windowLocData[3] = x + self._writedata(self.windowLocData) + + self._writecommand(TFT.RASET) #Row address set. + self.windowLocData[1] = y + self.windowLocData[3] = y + self._writedata(self.windowLocData) + self._writecommand(TFT.RAMWR) #Write to RAM. + +# @micropython.native + def _setwindowloc( self, aPos0, aPos1 ) : + '''Set a rectangular area for drawing a color to.''' + self._writecommand(TFT.CASET) #Column address set. + self.windowLocData[0] = 0x00 + self.windowLocData[1] = int(aPos0[0]) + self.windowLocData[2] = 0x00 + self.windowLocData[3] = int(aPos1[0]) + self._writedata(self.windowLocData) + + self._writecommand(TFT.RASET) #Row address set. + self.windowLocData[1] = int(aPos0[1]) + self.windowLocData[3] = int(aPos1[1]) + self._writedata(self.windowLocData) + + self._writecommand(TFT.RAMWR) #Write to RAM. + + @micropython.native + def _writecommand( self, aCommand ) : + '''Write given command to the device.''' + self.dc.low() + self.cs.low() + self.spi.send(aCommand) + self.cs.high() + + @micropython.native + def _writedata( self, aData ) : + '''Write given data to the device. This may be + either a single int or a bytearray of values.''' + self.dc.high() + self.cs.low() + self.spi.send(aData) + self.cs.high() + + @micropython.native + def _pushcolor( self, aColor ) : + '''Push given color to the device.''' + self.colorData[0] = aColor >> 8 + self.colorData[1] = aColor + self._writedata(self.colorData) + + @micropython.native + def _setMADCTL( self ) : + '''Set screen rotation and RGB/BGR format.''' + self._writecommand(TFT.MADCTL) + rgb = TFTRGB if self._rgb else TFTBGR + self._writedata(TFTRotations[self.rotate] | rgb) + + @micropython.native + def _reset( self ) : + '''Reset the device.''' + self.dc.low() + self.reset.high() + pyb.delay(500) + self.reset.low() + pyb.delay(500) + self.reset.high() + pyb.delay(500) + + def initb( self ) : + '''Initialize blue tab version.''' + self._size = (ScreenSize[0] + 2, ScreenSize[1] + 1) + self._reset() + self._writecommand(TFT.SWRESET) #Software reset. + pyb.delay(50) + self._writecommand(TFT.SLPOUT) #out of sleep mode. + pyb.delay(500) + + data1 = bytearray(1) + self._writecommand(TFT.COLMOD) #Set color mode. + data1[0] = 0x05 #16 bit color. + self._writedata(data1) + pyb.delay(10) + + data3 = bytearray([0x00, 0x06, 0x03]) #fastest refresh, 6 lines front, 3 lines back. + self._writecommand(TFT.FRMCTR1) #Frame rate control. + self._writedata(data3) + pyb.delay(10) + + self._writecommand(TFT.MADCTL) + data1[0] = 0x08 #row address/col address, bottom to top refresh + self._writedata(data1) + + data2 = bytearray(2) + self._writecommand(TFT.DISSET5) #Display settings + data2[0] = 0x15 #1 clock cycle nonoverlap, 2 cycle gate rise, 3 cycle oscil, equalize + data2[1] = 0x02 #fix on VTL + self._writedata(data2) + + self._writecommand(TFT.INVCTR) #Display inversion control + data1[0] = 0x00 #Line inversion. + self._writedata(data1) + + self._writecommand(TFT.PWCTR1) #Power control + data2[0] = 0x02 #GVDD = 4.7V + data2[1] = 0x70 #1.0uA + self._writedata(data2) + pyb.delay(10) + + self._writecommand(TFT.PWCTR2) #Power control + data1[0] = 0x05 #VGH = 14.7V, VGL = -7.35V + self._writedata(data1) + + self._writecommand(TFT.PWCTR3) #Power control + data2[0] = 0x01 #Opamp current small + data2[1] = 0x02 #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.VMCTR1) #Power control + data2[0] = 0x3C #VCOMH = 4V + data2[1] = 0x38 #VCOML = -1.1V + self._writedata(data2) + pyb.delay(10) + + self._writecommand(TFT.PWCTR6) #Power control + data2[0] = 0x11 + data2[1] = 0x15 + self._writedata(data2) + + #These different values don't seem to make a difference. +# dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f, +# 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10]) + dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, + 0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10]) + self._writecommand(TFT.GMCTRP1) + self._writedata(dataGMCTRP) + +# dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30, +# 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10]) + dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e, + 0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10]) + self._writecommand(TFT.GMCTRN1) + self._writedata(dataGMCTRN) + pyb.delay(10) + + self._writecommand(TFT.CASET) #Column address set. + self.windowLocData[0] = 0x00 + self.windowLocData[1] = 2 #Start at column 2 + self.windowLocData[2] = 0x00 + self.windowLocData[3] = self._size[0] - 1 + self._writedata(self.windowLocData) + + self._writecommand(TFT.RASET) #Row address set. + self.windowLocData[1] = 1 #Start at row 2. + self.windowLocData[3] = self._size[1] - 1 + self._writedata(self.windowLocData) + + self._writecommand(TFT.NORON) #Normal display on. + pyb.delay(10) + + self._writecommand(TFT.RAMWR) + pyb.delay(500) + + self._writecommand(TFT.DISPON) + self.cs.high() + pyb.delay(500) + + def initr( self ) : + '''Initialize a red tab version.''' + self._reset() + + self._writecommand(TFT.SWRESET) #Software reset. + pyb.delay(150) + self._writecommand(TFT.SLPOUT) #out of sleep mode. + pyb.delay(500) + + data3 = bytearray([0x01, 0x2C, 0x2D]) #fastest refresh, 6 lines front, 3 lines back. + self._writecommand(TFT.FRMCTR1) #Frame rate control. + self._writedata(data3) + + self._writecommand(TFT.FRMCTR2) #Frame rate control. + self._writedata(data3) + + data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d]) + self._writecommand(TFT.FRMCTR3) #Frame rate control. + self._writedata(data6) + pyb.delay(10) + + data1 = bytearray(1) + self._writecommand(TFT.INVCTR) #Display inversion control + data1[0] = 0x07 #Line inversion. + self._writedata(data1) + + self._writecommand(TFT.PWCTR1) #Power control + data3[0] = 0xA2 + data3[1] = 0x02 + data3[2] = 0x84 + self._writedata(data3) + + self._writecommand(TFT.PWCTR2) #Power control + data1[0] = 0xC5 #VGH = 14.7V, VGL = -7.35V + self._writedata(data1) + + data2 = bytearray(2) + self._writecommand(TFT.PWCTR3) #Power control + data2[0] = 0x0A #Opamp current small + data2[1] = 0x00 #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.PWCTR4) #Power control + data2[0] = 0x8A #Opamp current small + data2[1] = 0x2A #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.PWCTR5) #Power control + data2[0] = 0x8A #Opamp current small + data2[1] = 0xEE #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.VMCTR1) #Power control + data1[0] = 0x0E + self._writedata(data1) + + self._writecommand(TFT.INVOFF) + + self._writecommand(TFT.MADCTL) #Power control + data1[0] = 0xC8 + self._writedata(data1) + + self._writecommand(TFT.COLMOD) + data1[0] = 0x05 + self._writedata(data1) + + self._writecommand(TFT.CASET) #Column address set. + self.windowLocData[0] = 0x00 + self.windowLocData[1] = 0x00 + self.windowLocData[2] = 0x00 + self.windowLocData[3] = self._size[0] - 1 + self._writedata(self.windowLocData) + + self._writecommand(TFT.RASET) #Row address set. + self.windowLocData[3] = self._size[1] - 1 + self._writedata(self.windowLocData) + + dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f, + 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10]) + self._writecommand(TFT.GMCTRP1) + self._writedata(dataGMCTRP) + + dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30, + 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10]) + self._writecommand(TFT.GMCTRN1) + self._writedata(dataGMCTRN) + pyb.delay(10) + + self._writecommand(TFT.DISPON) + pyb.delay(100) + + self._writecommand(TFT.NORON) #Normal display on. + pyb.delay(10) + + self.cs.high() + + @micropython.native + def initg( self ) : + '''Initialize a green tab version.''' + self._reset() + + self._writecommand(TFT.SWRESET) #Software reset. + pyb.delay(150) + self._writecommand(TFT.SLPOUT) #out of sleep mode. + pyb.delay(255) + + data3 = bytearray([0x01, 0x2C, 0x2D]) #fastest refresh, 6 lines front, 3 lines back. + self._writecommand(TFT.FRMCTR1) #Frame rate control. + self._writedata(data3) + + self._writecommand(TFT.FRMCTR2) #Frame rate control. + self._writedata(data3) + + data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d]) + self._writecommand(TFT.FRMCTR3) #Frame rate control. + self._writedata(data6) + pyb.delay(10) + + self._writecommand(TFT.INVCTR) #Display inversion control + self._writedata(0x07) + + self._writecommand(TFT.PWCTR1) #Power control + data3[0] = 0xA2 + data3[1] = 0x02 + data3[2] = 0x84 + self._writedata(data3) + + self._writecommand(TFT.PWCTR2) #Power control + self._writedata(0xC5) + + data2 = bytearray(2) + self._writecommand(TFT.PWCTR3) #Power control + data2[0] = 0x0A #Opamp current small + data2[1] = 0x00 #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.PWCTR4) #Power control + data2[0] = 0x8A #Opamp current small + data2[1] = 0x2A #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.PWCTR5) #Power control + data2[0] = 0x8A #Opamp current small + data2[1] = 0xEE #Boost frequency + self._writedata(data2) + + self._writecommand(TFT.VMCTR1) #Power control + self._writedata(0x0E) + + self._writecommand(TFT.INVOFF) + + self._setMADCTL() + + self._writecommand(TFT.COLMOD) + self._writedata(0x05) + + self._writecommand(TFT.CASET) #Column address set. + self.windowLocData[0] = 0x00 + self.windowLocData[1] = 0x01 #Start at row/column 1. + self.windowLocData[2] = 0x00 + self.windowLocData[3] = self._size[0] - 1 + self._writedata(self.windowLocData) + + self._writecommand(TFT.RASET) #Row address set. + self.windowLocData[3] = self._size[1] - 1 + self._writedata(self.windowLocData) + + dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, + 0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10]) + self._writecommand(TFT.GMCTRP1) + self._writedata(dataGMCTRP) + + dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e, + 0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10]) + self._writecommand(TFT.GMCTRN1) + self._writedata(dataGMCTRN) + + self._writecommand(TFT.NORON) #Normal display on. + pyb.delay(10) + + self._writecommand(TFT.DISPON) + pyb.delay(100) + + self.cs.high() + +def maker( ) : + t = TFT(1, "X1", "X2") + print("Initializing") + t.initr() + t.fill(0) + return t + +def makeb( ) : + t = TFT(1, "X1", "X2") + print("Initializing") + t.initb() + t.fill(0) + return t + +def makeg( ) : + t = TFT(1, "X1", "X2") + print("Initializing") + t.initg() + t.fill(0) + return t diff --git a/lib/seriffont.py b/lib/seriffont.py new file mode 100644 index 0000000..836d863 --- /dev/null +++ b/lib/seriffont.py @@ -0,0 +1,99 @@ + +seriffont = {"Width": 6, "Height": 8, "Start": 32, "End": 127, "Data": bytearray([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, #0x00, + 0x12, 0x3F, 0x12, 0x3F, 0x12, 0x00, #0x00, + 0x26, 0x7F, 0x32, 0x00, 0x00, 0x00, #0x00, + 0x13, 0x0B, 0x34, 0x32, 0x00, 0x00, #0x00, + 0x1A, 0x25, 0x1A, 0x28, 0x00, 0x00, #0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x7E, 0x81, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x08, 0x1C, 0x08, 0x00, 0x00, 0x00, #0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x38, 0x07, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x1E, 0x21, 0x21, 0x1E, 0x00, 0x00, #0x00, + 0x02, 0x3F, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x32, 0x29, 0x29, 0x36, 0x00, 0x00, #0x00, + 0x12, 0x21, 0x25, 0x1A, 0x00, 0x00, #0x00, + 0x18, 0x16, 0x3F, 0x10, 0x00, 0x00, #0x00, + 0x27, 0x25, 0x19, 0x00, 0x00, 0x00, #0x00, + 0x1E, 0x25, 0x25, 0x18, 0x00, 0x00, #0x00, + 0x03, 0x39, 0x07, 0x00, 0x00, 0x00, #0x00, + 0x1A, 0x25, 0x25, 0x1A, 0x00, 0x00, #0x00, + 0x06, 0x29, 0x29, 0x1E, 0x00, 0x00, #0x00, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, #0x00, + 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, #0x00, + 0x22, 0x14, 0x08, 0x00, 0x00, 0x00, #0x00, + 0x02, 0x29, 0x05, 0x02, 0x00, 0x00, #0x00, + 0x1C, 0x22, 0x49, 0x55, 0x59, 0x12, #0x0C, + 0x30, 0x2C, 0x0B, 0x0B, 0x2C, 0x30, #0x00, + 0x21, 0x3F, 0x25, 0x25, 0x1A, 0x00, #0x00, + 0x1E, 0x21, 0x21, 0x21, 0x13, 0x00, #0x00, + 0x21, 0x3F, 0x21, 0x21, 0x1E, 0x00, #0x00, + 0x21, 0x3F, 0x25, 0x33, 0x00, 0x00, #0x00, + 0x21, 0x3F, 0x25, 0x03, 0x00, 0x00, #0x00, + 0x1E, 0x21, 0x21, 0x29, 0x3B, 0x00, #0x00, + 0x3F, 0x04, 0x04, 0x3F, 0x00, 0x00, #0x00, + 0x3F, 0x21, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x21, 0x1F, 0x01, 0x00, 0x00, 0x00, #0x00, + 0x21, 0x3F, 0x0C, 0x33, 0x21, 0x00, #0x00, + 0x3F, 0x21, 0x30, 0x00, 0x00, 0x00, #0x00, + 0x21, 0x3F, 0x0C, 0x30, 0x0C, 0x3F, #0x21, + 0x3F, 0x03, 0x0C, 0x3F, 0x01, 0x00, #0x00, + 0x1E, 0x21, 0x21, 0x21, 0x1E, 0x00, #0x00, + 0x3F, 0x29, 0x06, 0x00, 0x00, 0x00, #0x00, + 0x1E, 0x21, 0x21, 0x61, 0x1E, 0x00, #0x00, + 0x21, 0x3F, 0x09, 0x36, 0x00, 0x00, #0x00, + 0x32, 0x25, 0x25, 0x1B, 0x00, 0x00, #0x00, + 0x01, 0x3F, 0x01, 0x00, 0x00, 0x00, #0x00, + 0x1F, 0x21, 0x20, 0x21, 0x1F, 0x00, #0x00, + 0x03, 0x0D, 0x30, 0x30, 0x0D, 0x03, #0x00, + 0x0F, 0x31, 0x0C, 0x0C, 0x31, 0x0F, #0x00, + 0x21, 0x33, 0x0C, 0x0C, 0x33, 0x21, #0x00, + 0x03, 0x24, 0x38, 0x24, 0x03, 0x01, #0x00, + 0x29, 0x25, 0x33, 0x00, 0x00, 0x00, #0x00, + 0x7F, 0x41, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x07, 0x38, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x41, 0x7F, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, #0x00, + 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, #0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x14, 0x24, 0x38, 0x00, 0x00, 0x00, #0x00, + 0x3F, 0x28, 0x24, 0x18, 0x00, 0x00, #0x00, + 0x18, 0x24, 0x24, 0x00, 0x00, 0x00, #0x00, + 0x18, 0x24, 0x25, 0x3F, 0x00, 0x00, #0x00, + 0x18, 0x24, 0x28, 0x00, 0x00, 0x00, #0x00, + 0x3E, 0x25, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x18, 0xA4, 0xA4, 0x7C, 0x00, 0x00, #0x00, + 0x3F, 0x04, 0x38, 0x00, 0x00, 0x00, #0x00, + 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0xFD, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x3F, 0x18, 0x24, 0x00, 0x00, 0x00, #0x00, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x3C, 0x04, 0x38, 0x04, 0x38, 0x00, #0x00, + 0x3C, 0x04, 0x38, 0x00, 0x00, 0x00, #0x00, + 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, #0x00, + 0xFC, 0xA4, 0x24, 0x18, 0x00, 0x00, #0x00, + 0x18, 0x24, 0xA4, 0xFC, 0x00, 0x00, #0x00, + 0x3C, 0x04, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, #0x00, + 0x1E, 0x24, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x1C, 0x20, 0x3C, 0x00, 0x00, 0x00, #0x00, + 0x0C, 0x30, 0x0C, 0x00, 0x00, 0x00, #0x00, + 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x00, #0x00, + 0x24, 0x18, 0x24, 0x00, 0x00, 0x00, #0x00, + 0x9C, 0x60, 0x1C, 0x00, 0x00, 0x00, #0x00, + 0x34, 0x24, 0x2C, 0x00, 0x00, 0x00, #0x00, + 0x08, 0x77, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x77, 0x08, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, #0x00, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, #0x00 +])} diff --git a/lib/sevenseg.py b/lib/sevenseg.py new file mode 100644 index 0000000..df3c190 --- /dev/null +++ b/lib/sevenseg.py @@ -0,0 +1,170 @@ + +from machine import Pin +from time import sleep_us, time, localtime +import pyb + + +class sevenseg(object): + """docstring for 7seg""" + + _CMD1 = const(0x40) + _CMD2 = const(0xC0) + _CMD3 = const(0x80) + + # A + # --- + # F | | B + # -G- + # E | | C + # --- + # D + # XGFEDCBA + _numbertable = [ + 0b00111111, #0 + 0b00000110, #1 + 0b01011011, #2 + 0b01001111, #3 + 0b01100110, #4 + 0b01101101, #5 + 0b01111101, #6 + 0b00000111, #7 + 0b01111111, #8 + 0b01101111, #9 + 0b01110111, #A + 0b01111100, #B + 0b00111001, #C + 0b01011110, #D + 0b01111001, #E + 0b01110001, #F + 0b00000000, #space + 0b01000000 #dash + ] + + def __init__(self, clk, dio ): + self._clk = pyb.Pin(clk, pyb.Pin.IN) + self._dio = pyb.Pin(dio, pyb.Pin.IN) + self._brightness = 0 + self._colon = False + self._buffer = bytearray(4) + + self._clk.init(Pin.IN) + self._dio.init(Pin.IN) + self._clk(0) + self._dio(0) + self.brightness = 7 + + @property + def colon( self ) : return self._colon + + @colon.setter + def colon( self, aValue ) : + self._colon = aValue + + @property + def brightness( self ) : return self._brightness + + @brightness.setter + def brightness( self, aValue ) : + self._brightness = aValue & 0xF + self._write_comm1() + self._write_comm3() + + def _start(self): + self._dio.init(Pin.OUT) + sleep_us(50) + + def _stop(self): + self._dio.init(Pin.OUT) + sleep_us(50) + self._clk.init(Pin.IN) + sleep_us(50) + self._dio.init(Pin.IN) + sleep_us(50) + + def _write_comm1(self): + self._start() + self._write_byte(_CMD1) + self._stop() + + def _write_comm3(self): + self._start() + self._write_byte(_CMD3 + self._brightness + 7) + self._stop() + + def _write_byte(self, b): + # send each bit + for i in range(8): + self._clk.init(Pin.OUT) + sleep_us(50) + self._dio.init(Pin.IN if b & 1 else Pin.OUT) + sleep_us(50) + self._clk.init(Pin.IN) + sleep_us(50) + b >>= 1 + self._clk.init(Pin.OUT) + sleep_us(50) + self._clk.init(Pin.IN) + sleep_us(50) + self._clk.init(Pin.OUT) + sleep_us(50) + + def clear( self ) : + for v in self._buffer: + v = 0 + + def display( self ) : + if self.colon : + self._buffer[1] |= 0x80 + else: + self._buffer[1] &= ~0x80 + + self._write_comm1() + self._start() + self._write_byte(_CMD2) + for b in self._buffer: + self._write_byte(b) + self._stop() + self._write_comm3() + + def data( self, aIndex, aValue ) : + self._buffer[aIndex] = aValue + + def digit( self, aIndex, aValue ) : + if 0 <= aValue < len(self._numbertable) : + self.data(aIndex, self._numbertable[aValue]) + + def char(self, aIndex, char): + """Display a character 0-9, a-f, space or dash.""" + o = ord(char) + c = -1 + # space + if o == 32: + c = 16 + # dash + if o == 45: + c = 17 + # uppercase A-F + if 65 <= o <= 70: + c = o - 55 + # lowercase a-f + if 97 <= o <= 102: + c = o - 87 + # 0-9 + if 48 <= o <= 57: + c = o - 48 + + self.digit(aIndex, c) + +def clock(tm) : + rtc = pyb.RTC() + while True: + t = rtc.datetime() + tm.colon = t[6] & 1 + tm.digit(0, t[4] // 10) + tm.digit(1, t[4] % 10) + tm.digit(2, t[5] // 10) + tm.digit(3, t[5] % 10) + tm.display() + +# sleep(1 - time() % 1) + diff --git a/lib/sysfont.py b/lib/sysfont.py new file mode 100644 index 0000000..b1fa2d6 --- /dev/null +++ b/lib/sysfont.py @@ -0,0 +1,265 @@ + +#Font used for ST7735 display. + +#Each character uses 5 bytes. +#index using ASCII value * 5. +#Each byte contains a column of pixels. +#The character may be 8 pixels high and 5 wide. + +sysfont = {"Width": 5, "Height": 8, "Start": 0, "End": 254, "Data": bytearray([ + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x21, 0x54, 0x54, 0x78, 0x41, + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0xF0, 0x29, 0x24, 0x29, 0xF0, + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x32, 0x48, 0x48, 0x48, 0x32, + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x39, 0x44, 0x44, 0x44, 0x39, + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0xAA, 0x00, 0x55, 0x00, 0xAA, + 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0x7C, 0x2A, 0x2A, 0x3E, 0x14, + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C +])} + diff --git a/lib/terminalfont.py b/lib/terminalfont.py new file mode 100644 index 0000000..0ba22f7 --- /dev/null +++ b/lib/terminalfont.py @@ -0,0 +1,100 @@ + +terminalfont = {"Width": 6, "Height": 8, "Start": 32, "End": 127, "Data": bytearray([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x5F, 0x06, 0x00, + 0x00, 0x07, 0x03, 0x00, 0x07, 0x03, + 0x00, 0x24, 0x7E, 0x24, 0x7E, 0x24, + 0x00, 0x24, 0x2B, 0x6A, 0x12, 0x00, + 0x00, 0x63, 0x13, 0x08, 0x64, 0x63, + 0x00, 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x3E, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x41, 0x3E, 0x00, 0x00, + 0x00, 0x08, 0x3E, 0x1C, 0x3E, 0x08, + 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x00, 0xE0, 0x60, 0x00, 0x00, + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, + 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, + 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x00, 0x62, 0x51, 0x49, 0x49, 0x46, + 0x00, 0x22, 0x49, 0x49, 0x49, 0x36, + 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x00, 0x2F, 0x49, 0x49, 0x49, 0x31, + 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, + 0x00, 0x01, 0x71, 0x09, 0x05, 0x03, + 0x00, 0x36, 0x49, 0x49, 0x49, 0x36, + 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00, + 0x00, 0x00, 0xEC, 0x6C, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, + 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, + 0x00, 0x00, 0x41, 0x22, 0x14, 0x08, + 0x00, 0x02, 0x01, 0x59, 0x09, 0x06, + 0x00, 0x3E, 0x41, 0x5D, 0x55, 0x1E, + 0x00, 0x7E, 0x11, 0x11, 0x11, 0x7E, + 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x00, 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, + 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x00, 0x30, 0x40, 0x40, 0x40, 0x3F, + 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x7F, 0x02, 0x04, 0x02, 0x7F, + 0x00, 0x7F, 0x02, 0x04, 0x08, 0x7F, + 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x00, 0x7F, 0x09, 0x09, 0x19, 0x66, + 0x00, 0x26, 0x49, 0x49, 0x49, 0x32, + 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, + 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x00, 0x3F, 0x40, 0x3C, 0x40, 0x3F, + 0x00, 0x63, 0x14, 0x08, 0x14, 0x63, + 0x00, 0x07, 0x08, 0x70, 0x08, 0x07, + 0x00, 0x71, 0x49, 0x45, 0x43, 0x00, + 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, + 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, + 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, + 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, + 0x00, 0x7F, 0x44, 0x44, 0x44, 0x38, + 0x00, 0x38, 0x44, 0x44, 0x44, 0x28, + 0x00, 0x38, 0x44, 0x44, 0x44, 0x7F, + 0x00, 0x38, 0x54, 0x54, 0x54, 0x08, + 0x00, 0x08, 0x7E, 0x09, 0x09, 0x00, + 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, + 0x00, 0x7F, 0x04, 0x04, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x7D, 0x40, 0x00, + 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, + 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x7F, 0x40, 0x00, + 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, + 0x00, 0x7C, 0x04, 0x04, 0x78, 0x00, + 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, + 0x00, 0xFC, 0x44, 0x44, 0x44, 0x38, + 0x00, 0x38, 0x44, 0x44, 0x44, 0xFC, + 0x00, 0x44, 0x78, 0x44, 0x04, 0x08, + 0x00, 0x08, 0x54, 0x54, 0x54, 0x20, + 0x00, 0x04, 0x3E, 0x44, 0x24, 0x00, + 0x00, 0x3C, 0x40, 0x20, 0x7C, 0x00, + 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x00, 0x3C, 0x60, 0x30, 0x60, 0x3C, + 0x00, 0x6C, 0x10, 0x10, 0x6C, 0x00, + 0x00, 0x9C, 0xA0, 0x60, 0x3C, 0x00, + 0x00, 0x64, 0x54, 0x54, 0x4C, 0x00, + 0x00, 0x08, 0x3E, 0x41, 0x41, 0x00, + 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x00, 0x41, 0x41, 0x3E, 0x08, + 0x00, 0x02, 0x01, 0x02, 0x01, 0x00, + 0x00, 0x3C, 0x26, 0x23, 0x26, 0x3C +])} +