#! /usr/bin/env python import sys import getopt import binascii from sys import exit, stderr, stdout from crcmod import mkCrcFun from binascii import hexlify, unhexlify from serial import Serial from time import sleep def usage(type): if type==0: print """Usage: clio.py [operand] [options] [parameter...] Transfer files to and from the HP 41CL Recommended 41cl settings: TURBO50, BAUD96 Operands: s Send file to HP 41CL r Receive file from from 41CL c Calculate checksum for file. For further information type clio.py [operand] -h""" elif type==1: print """Usage clio.py s -hcx file comport Send file to 41CL -h Show this help text -c Calculate CRC-checksum -x Send hex-file in ASCII encoding If -x is not specified bin-file format is assumed.""" elif type==2: print """Usage clio.py c -hx file Calculate CRC-checksum for file -h Show this help text -x Read hex-file in ASCII encoding If -x is not specified bin-file format is assumed.""" elif type==3: print """Usage clio.py r -hcx comport file Receive file from 41CL Recommended 41cl settings: TURBO50, BAUD48 -h Show this help text -c Calculate CRC-checksum -x Receive hex-file in ASCII encoding If -x is not specified bin-file format is assumed.""" def swapBytes( binData ): if 2 * ( len( binData ) / 2) <> len( binData ): throw( "Length of data must be even!" ); return reduce( lambda x, y: x+y, map( lambda x: x[0]+x[1], zip(binData[1::2], binData[0::2] ) ) ) class ClData: def __init__( self ): g32 = 0x104C11DB7 self.crc32Fun=mkCrcFun( g32, -1L, False, False ) self.binData = "" def toHexData( self ): return hexlify( swapBytes( self.binData ) ); def fromHexData(self, hexData): self.binData = swapBytes( unhexlify( hexData ) ); def crc32(self ): return self.crc32Fun( self.binData ); def readHexFile( self, filename ): self.binData = "" hexFile = file( filename, "r" ); self.fromHexData( hexFile.read() ); hexFile.close(); def readBinFile( self, filename ): self.binData = "" binFile = file( filename, "rb" ); self.binData = binFile.read(); binFile.close(); def readCl( self, comport, speed=9600, nData=0x2000 ): self.binData = "" serialPort = Serial( comport, speed, timeout=10 ) while len(self.binData) < nData: n = serialPort.inWaiting(); if (n>0): self.binData = self.binData + serialPort.read( n ); serialPort.close() self.binData = swapBytes( self.binData ) def writeHexFile( self, filename ): hexFile = file( filename, "w" ); hexFile.write( self.toHexData() ); hexFile.close(); def writeBinFile( self, filename ): binFile = file( filename, "wb" ); binFile.write( self.binData ); binFile.close(); def writeCl( self, comport,speed=4800 ): serialPort = Serial( comport, speed, timeout=10 ) swappedData = swapBytes( self.binData ); nData = len( swappedData ) for i in range(0, nData, 64 ): bl = min(64, nData-i); serialPort.write( swappedData[ i:i+bl ] ) stdout.write ("%04X - %04x / %04X\r" % (i, i+bl-1, nData)) stdout.flush() sleep(0.1) serialPort.close() stdout.write(" \r"); stdout.flush() def main(argv): if len(argv)<2: usage(0) return if argv[1] in [ 's', 'send' ]: try: opts, args = getopt.getopt(argv[2:], 'hxc', ['help', 'hex', 'crc']) except getopt.error, msg: usage(1) exit(1) binTransfer=True; printCrc=False; for opt, arg in opts: if opt in ('-h', '--help'): usage(1) return elif opt in ('-x', '--hex'): binTransfer = False elif opt in ('-c', '--crc'): printCrc = True clData = ClData(); if binTransfer: clData.readBinFile( args[0] ); else: clData.readHexFile( args[0] ); if printCrc: print "%s:%04X" % (args[0], clData.crc32()); clData.writeCl(args[1]); elif argv[1] in [ 'c', 'crc' ]: try: opts, args = getopt.getopt(argv[2:], 'hx', ['help', 'hex']) except getopt.error, msg: usage(1) exit(1) binTransfer=True; printCrc=False; for opt, arg in opts: if opt in ('-h', '--help'): usage(2) return elif opt in ('-x', '--hex'): binTransfer = False clData = ClData(); if binTransfer: clData.readBinFile( args[0] ); else: clData.readHexFile( args[0] ); print "%s:%04X" % (args[0], clData.crc32()); elif argv[1] in [ 'r', 'receive' ]: try: opts, args = getopt.getopt(argv[2:], 'hxc', ['help', 'hex', 'crc']) except getopt.error, msg: usage(3) exit(1) binTransfer=True; printCrc=False; for opt, arg in opts: if opt in ('-h', '--help'): usage(3) return elif opt in ('-x', '--hex'): binTransfer = False elif opt in ('-c', '--crc'): printCrc = True clData = ClData(); clData.readCl( args[0] ) if binTransfer: clData.writeBinFile( args[1] ); else: clData.writeHexFile( args[1] ); if printCrc: print "%s:%04X" % (args[1], clData.crc32()); else: usage(0) if __name__ == '__main__': main(sys.argv)