'From Squeak3.2gamma of 15 January 2002 [latest update: #4811] on 6 April 2002 at 3:10:37 pm'! "Change Set: RCXFixes-nk Date: 6 April 2002 Author: Ned Konz Made serial comms work more reliably. Removed most delays. Added switchable byte logging, made logging happen in UI thread. "! Object subclass: #RCXSerialPortReader instanceVariableNames: 'sharedQueue serialPort process logging ' classVariableNames: '' poolDictionaries: '' category: 'People-Ab-RCX'! !RCX methodsFor: 'initialization' stamp: 'nk 4/6/2002 12:49'! onPort: portNumber port _ RCXSerialPortReader onPort: portNumber. irEncoder _ RCXIrEncoder new. self doInitAlive! ! !RCX methodsFor: 'operation' stamp: 'nk 4/6/2002 12:40'! doInitAlive | r | r_#(85 255 0 16 239 16 239) asByteArray. port nextPutAll: r. irEncoder setLastCommandArray: r. r _ self read. ^ (r at: 1) = 231! ! !RCX methodsFor: 'operation' stamp: 'nk 4/6/2002 15:07'! enableLogging: aBoolean port enableLogging: aBoolean! ! !RCX methodsFor: 'operation' stamp: 'nk 4/6/2002 13:07'! log: anObject Transcript nextPutAll: anObject asString; cr! ! !RCX methodsFor: 'transferring' stamp: 'nk 4/6/2002 14:53'! downloadRawProgram: byteCodes as: aNumber self log: (self selectProgram: aNumber). self log: (self startTaskDownloadingWithTask: 0 andLength: byteCodes size) asArray. self log: (self transfertForIndex: 0 data: byteCodes) asArray. ! ! !RCX methodsFor: 'transferring' stamp: 'nk 4/6/2002 13:45'! flush port flush! ! !RCX methodsFor: 'transferring' stamp: 'nk 4/6/2002 12:49'! read ^ irEncoder newDecode: port readByteArray ! ! !RCX methodsFor: 'transferring' stamp: 'nk 4/6/2002 14:14'! send: aByteArray | r | r _ irEncoder encode: aByteArray. port nextPutAll: r. ! ! !RCX methodsFor: 'transferring' stamp: 'nk 4/6/2002 12:38'! startTaskDownloadingWithTask: taskNumber andLength: taskLength self send: (self byteCodeForStartTaskDownloadingWithTask: taskNumber andLength: taskLength). ^ self read ! ]style[(30 10 12 10 3 4 54 10 12 10 6 4 6)f1b,f1cblack;b,f1b,f1cblack;b,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1,f1cblack;,f1! ! !RCX methodsFor: 'transferring' stamp: 'nk 4/6/2002 13:07'! transfertForIndex: index data: aProgram self send: (self byteCodeForTransfertForIndex: index data: aProgram). ^ self read! ! !RCX class methodsFor: 'Examples' stamp: 'nk 4/6/2002 12:37'! downloadRawProgram: byteCodes as: aNumber onPort: aPortNumber | rcx | rcx _ RCX new. rcx onPort: aPortNumber. rcx isAlive. self log: (rcx selectProgram: aNumber). self log: (rcx startTaskDownloadingWithTask: 0 andLength: byteCodes size) asArray. self log: (rcx transfertForIndex: 0 data: byteCodes) asArray. rcx closePort! ! !RCXMotor methodsFor: 'as yet unclassified' stamp: 'nk 4/6/2002 15:02'! start |v| v_RCXMotor getByteCodeFromMotor: plug motorStatus: 2. rcx send: (ByteArray with: 16r21 with: v). ^ ((rcx read) at: 1) = 16rD6! ]style[(5 126 1 9)f1b,f1,f1cblue;,f1! ! !RCXSerialPortReader methodsFor: 'communication' stamp: 'nk 4/6/2002 14:27'! flush sharedQueue flush. serialPort readByteArray.! ! !RCXSerialPortReader methodsFor: 'communication' stamp: 'nk 4/6/2002 13:11'! nextPutAll: aStringOrByteArray self logSentBytes: aStringOrByteArray. serialPort nextPutAll: aStringOrByteArray! ! !RCXSerialPortReader methodsFor: 'communication' stamp: 'nk 4/6/2002 14:58'! readByteArray | delay stream bytes lastReceived | stream _ WriteStream on: (ByteArray new: 80). delay _ Delay forMilliseconds: 100. lastReceived _ Time millisecondClockValue. "Poll the receive queue until there have been no characters for at least 600 msec" [ delay wait. bytes _ sharedQueue nextOrNil. bytes ifNotNil: [ stream nextPutAll: bytes. lastReceived _ Time millisecondClockValue. true ] ifNil: [ (Time millisecondClockValue - lastReceived) < 300 ] ] whileTrue. bytes _ stream contents. self logReceivedBytes: bytes. ^bytes ! ! !RCXSerialPortReader methodsFor: 'logging' stamp: 'nk 4/6/2002 15:05'! enableLogging: aBoolean logging _ aBoolean! ! !RCXSerialPortReader methodsFor: 'logging' stamp: 'nk 4/6/2002 14:45'! logDirection: dir andBytes: string WorldState addDeferredUIMessage: [ Transcript nextPutAll: dir; nextPutAll: string size printString; nextPutAll: ' bytes: '. string do: [ :ch | Transcript nextPutAll: (Character value: ch) hex; space ]. Transcript cr; flush ]! ! !RCXSerialPortReader methodsFor: 'logging' stamp: 'nk 4/6/2002 15:07'! logReceivedBytes: string logging ifTrue: [ self logDirection: 'RECV ' andBytes: string ]! ! !RCXSerialPortReader methodsFor: 'logging' stamp: 'nk 4/6/2002 15:07'! logSentBytes: string logging ifTrue: [ self logDirection: 'SEND ' andBytes: string ]! ! !RCXSerialPortReader methodsFor: 'initialize-release' stamp: 'nk 4/6/2002 14:29'! close process ifNotNil: [ process terminate. process _ nil. ]. serialPort ifNotNil: [ serialPort close. ]. sharedQueue _ nil. ! ! !RCXSerialPortReader methodsFor: 'initialize-release' stamp: 'nk 4/6/2002 15:07'! initialize sharedQueue _ SharedQueue new. logging _ false.! ! !RCXSerialPortReader methodsFor: 'initialize-release' stamp: 'nk 4/6/2002 14:45'! serialPort: aSerialPort serialPort _ aSerialPort. serialPort readByteArray. "flush it" process _ [ | delay | delay _ (Delay forMilliseconds: 100). [ | bytes | bytes _ serialPort readByteArray. (bytes notNil and: [ bytes notEmpty ]) ifTrue: [ sharedQueue nextPut: bytes]. delay wait ] repeat ] forkAt: Processor userInterruptPriority ! ! !RCXSerialPortReader class methodsFor: 'as yet unclassified' stamp: 'nk 4/6/2002 12:48'! onPort: portNumber | port | port _ SerialPort new. port baudRate: 2400. port dataBits: 8. port parityType: 1. port stopBitsType: 1. port openPort: portNumber. ^self new initialize serialPort: port! ! RCXSerialPortReader class removeSelector: #createFromSerialPort:! RCXSerialPortReader removeSelector: #log:! RCXSerialPortReader removeSelector: #readBytes:! !RCXSerialPortReader reorganize! ('communication' flush nextPutAll: readByteArray) ('logging' enableLogging: logDirection:andBytes: logReceivedBytes: logSentBytes:) ('initialize-release' close initialize serialPort:) ! !RCX reorganize! ('ByteCode generator' byteCodeForClearTimer: byteCodeForPlaySystemSound: byteCodeForSelectProgram: byteCodeForSetPowerMotor:source:power: byteCodeForStartTaskDownloadingWithTask:andLength: byteCodeForTransfertForIndex:data: byteCodeForTurnOffMotor: byteCodeForTurnOnMotor: byteCodeForWait:arg:) ('initialization' onPort:) ('operation' closePort doInitAlive enableLogging: initialize isAlive log: motor: sound: soundBeep soundClick soundError soundFastSweepUp soundSweepDown soundSweepUp touchSensor:) ('transferring' downloadRawProgram:as: flush read selectProgram: send: startTaskDownloadingWithTask:andLength: transfertForIndex:data:) !