JDCOGSERIAL
Table of Contents
Preface
Introduction Connection Diagram Global CONstants... PUBlic Spin Methods Start and Stop Stop Start Basic send/receive... Extended send/receive... Generic Interface...
I_ReadByteCheck
Assembly Cog I_ReadByte I_WriteByte I_ReadWord I_WriteWord I_ReadLong I_WriteLong I_ReadString I_WriteString I_ReadBlock I_WriteBlock License |
JDCogSerial Object Version 09.03.19JDCogSerial.spin : V08.07.01 - Initial Release V09.01.10 - Added MIT license for OBEX v09.03.19 - Fixed some bugs in the spin code
──────────────────────────────────────────────────────────────────── JDCogSerialDemo.spin ──────────────────────────────────────────────────────────────────── SOURCE CODE... CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 │ BaudRate = 38400 RxPin = |<31 TxPin = |<30 OBJ Comms : "JDCogSerial" Sub : "SubObject" VAR long CommPtr PUB Start CommPtr := Comms.start(RxPin, TxPin, BaudRate) if CommPtr then Sub.Init(CommPtr) Sub.SendGreeting ──────────────────────────────────────────────────────────────────── SubObject.spin ──────────────────────────────────────────────────────────────────── SOURCE CODE... VAR long RxPtr, TxPtr PUB Init(CommPtr) RxPtr := CommPtr TxPtr := CommPtr + 4 PUB Rx : RxByte repeat while (RxByte := long[RxPtr]) < 0 long[RxPtr] := -1 PUB Tx(TxByte) repeat while long[TxPtr] => 0 long[TxPtr] := TxByte PUB Str(StringPtr) repeat strsize(StringPtr) Tx(byte[StringPtr++]) PUB SendGreeting Str(string("Hello",13,10)) ──────────────────────────────────────────────────────────────────── Read and Write a byte using PASM ──────────────────────────────────────────────────────────────────── SOURCE CODE... ' Receive a byte into rx aRx rdlong rx,RxPtr 'Check the receiver shl rx,#1 WC 'Carry set if no byte available if_c jmp #aRx 'Wait for a byte to be received wrlong MinusOne,RxPtr 'Mark the byte as having been read ... RxPtr long 0 'Initialized in spin or at cog start rx long 0 MinusOne long -1 ' Transmit a byte from tx, also need a temporary variable aTx rdlong temp,TxPtr 'Check the transmitter shl temp,#1 WC 'Carry set if transmitter is idle if_nc jmp #aTx 'Wait til the transmitter is idle wrlong tx,TxPtr 'Write the byte into the transmitter ... TxPtr long 0 'Initialized in spin or at cog start tx long 0 temp long 0 ────────────────────────────────────────────────────────────────────
Global CONstantsSOURCE CODE... ' The buffer sizes may be freely adjusted. As long as the code still compiles ' to fit into the cog. The sizes are currently at their maximum. The sizes are ' number of longs, so the number of bytes stored is four times as many! RX1FIFO_SIZE = 167 '668 bytes TX1FIFO_SIZE = 168 '672 bytes Global VARiablesSOURCE CODE... long cog 'cog flag/id long rx1_buf '5 longs long tx1_buf long rx1_mask long tx1_mask long baud1_ticks PUBlic Spin MethodsStart and StopStart and Stop methods are used for starting and stopping this object. This uses/frees one cog and the rx/tx-pins used.StopStop serial driver - frees the cog that was usedSOURCE CODE... PUB Stop if cog cogstop(cog~ - 1) Start(rxpin, txpin, baudrate)┌─────────────────────────────────────────────────────────────────────┐ │Purpose: │ │ Start a single port serial driver - uses a single cog. │ ├─────────────────────────────────────────────────────────────────────┤ │Inputs: │ │ rxpin and txpin are passed in as pin masks. The transmitter │ │ may be disabled by passing in a mask of 0. The receiver may be │ │ disabled by simply ignoring it. │ │ baudrate etc Is passed in as the desired baudrate. The transmit │ │ / receive pair operate at the same baudrate. │ ├─────────────────────────────────────────────────────────────────────┤ │Output: │ │ Returns the address of the shared memory space if a cog was │ │ successfully started, or 0 if no cog available. │ └─────────────────────────────────────────────────────────────────────┘ SOURCE CODE... PUB Start(rxpin, txpin, baudrate) : addr Stop rx1_buf := -1 'Set receiver to idle tx1_buf := -1 'Set transmitter to idle rx1_mask := rxpin 'Set receive pin tx1_mask := txpin 'Set transmit pin baud1_ticks := CLKFREQ / baudrate 'Set baudrate cog := cognew(@entry, @rx1_buf) + 1 'Start the cog if cog addr := @rx1_buf Basic send/receiveHere you find basic send/receive-methods for single bytes.RxFlushFlush receive bufferSOURCE CODE... PUB RxFlush repeat until rxcheck < 0 RxCheckCheck if byte received (never waits) returns < 0 if no byte received, $00..$FF if byteSOURCE CODE... PUB RxCheck : rxbyte if (rxbyte := rx1_buf) => 0 rx1_buf := -1 RxTime(ms)Wait ms milliseconds for a byte to be received returns -1 if no byte received, $00..$FF if byteSOURCE CODE... PUB RxTime(ms) : rxbyte | t t := cnt repeat until (rxbyte := rxcheck) => 0 or (cnt - t) / (clkfreq / 1000) > ms RxReceive byte (may wait for byte) returns $00..$FFSOURCE CODE... PUB Rx : rxbyte repeat while (rxbyte := rx1_buf) < 0 rx1_buf := -1 Tx(txbyte)Send byte (may wait for room in buffer)SOURCE CODE... PUB Tx(txbyte) repeat while tx1_buf => 0 tx1_buf := txbyte Extended send/receiveHere you find extended send/receive-methods. This serial object has just one extended send-method.You can use it for output of zero termiated strings. Str(stringptr)Send a stringSOURCE CODE... PUB Str(stringptr) repeat strsize(stringptr) tx(byte[stringptr++]) Generic Interfacethis Interface provides generic access with different objects.I_ReadByteCheckCheck if a byte is waiting in the receive buffer and return the byte if one is there, does NOT block (never waits). return: If no byte, then return(-1). If byte, then return(byte). SOURCE CODE... PUB I_ReadByteCheck RETURN RxCheck I_ReadBytereads a byteSOURCE CODE... PUB I_ReadByte RETURN Rx I_WriteByte(outByte)writes a byteSOURCE CODE... PUB I_WriteByte(outByte) RETURN Tx(outByte.Byte[0]) I_ReadWordreads a wordSOURCE CODE... PUB I_ReadWord RESULT.Byte[0]:=Rx RESULT.Byte[1]:=Rx I_WriteWord(outWord)writes a wordSOURCE CODE... PUB I_WriteWord(outWord) Tx(outWord.Byte[0]) RETURN Tx(outWord.Byte[1]) I_ReadLongreads a longSOURCE CODE... PUB I_ReadLong RESULT.Byte[0]:=Rx RESULT.Byte[1]:=Rx RESULT.Byte[2]:=Rx RESULT.Byte[3]:=Rx I_WriteLong(outLong)writes a longSOURCE CODE... PUB I_WriteLong(outLong) Tx(outLong.Byte[0]) Tx(outLong.Byte[1]) Tx(outLong.Byte[2]) RETURN Tx(outLong.Byte[3]) I_ReadString(addressToPut, terminator)reads a string terminated by terminator to addressToPut - terminator not added - returns bytes readSOURCE CODE... PUB I_ReadString(addressToPut, terminator) | inByte repeat while ((inByte:=Rx)<>terminator) byte[addressToPut++]:=inByte RESULT++ I_WriteString(addressToGet, terminator)writes a string terminated by terminator from addressToGet - terminator not added - returns bytes writtenSOURCE CODE... PUB I_WriteString(addressToGet, terminator) | outByte repeat while ((outByte:=byte[addressToGet++])<>terminator) Tx(outByte) RESULT++ I_ReadBlock(addressToPut, count)reads count bytes to addressToPut - returns bytes readSOURCE CODE... PUB I_ReadBlock(addressToPut, count) repeat count byte[addressToPut++]:=Rx RETURN count I_WriteBlock(addressToGet, count)writes count bytes from addressToGet- returns bytes writtenSOURCE CODE... PUB I_WriteBlock(addressToGet, count) repeat count Tx(byte[addressToGet++]) RETURN count Assembly CogSOURCE CODE... ORG 0 ' ' Initialisation. ' entry mov t1,PAR mov t2,#5 :en1 mov rx1ptr,t1 add :en1,c512 add t1,#4 djnz t2,#:en1 mov t2,#3 :en2 rdlong rx1mask,rx1mask add :en2,c513 djnz t2,#:en2 or OUTA,tx1mask or DIRA,tx1mask jmp dRx1 c512 long 512 c513 long 513 rx1ptr long 0 tx1ptr long 0 rx1mask long 0 tx1mask long 0 baud1 long 0 ' ' Receiver ' aRx1_Start mov rx1bits,#9 '# of bits to receive mov rx1cnt,baud1 shr rx1cnt,#2 'quarter of a bit tick ... add rx1cnt,baud1 '... plus a full bit tick mov dRx1,#aRx1_Wait aRx1_Wait test rx1mask, INA WC 'Wait for start bit if_c jmp #aRx1_Get add rx1cnt, CNT mov dRx1,#aRx1_Bits aRx1_Bits mov t1,rx1cnt 'Check if bit receive period done sub t1,cnt cmps t1,#0 WC 'Time to sample yet? if_nc jmp #aRx1_Get test rx1mask, INA WC 'Receive bit into carry rcr rx1data,#1 'Carry into Rx buffer add rx1cnt,baud1 'Go to next bit period djnz rx1bits,#aRx1_Bits 'Get next bit if_nc jmp #aRx1_Start and rx1data,cRxAnd 'Mask out the unwanted bits rol rx1data,rx1rol 'Put the data into the correct byte mov dRx1,#aRx1_Put jmp dTx1 'Go do some transmitter code 'General variables for the receiver cRxAnd long %0111_1111_1000_0000_0000_0000_0000_0000 rx1len long 0 rx1maxlen long (tx1fifo - rx1fifo - 1) * 4 dRx1 long aRx1_Start 'Variables used to receive a byte into the FIFO rx1data long 0 rx1bits long 0 rx1cnt long 0 rx1rol long 9 rx1out long 0 rx1put long rx1fifo rx1putb long $80 'Variables used to grab a byte from the FIFO rx1ror long 0 rx1get long rx1fifo rx1getb long $80 aRx1_Put cmp rx1len,rx1maxlen WZ if_z jmp #(aRx1_Get+2) mov dRx1,#aRx1_Start add rx1len,#1 or rx1out,rx1data 'Merge in the new data byte arp1 mov rx1fifo,rx1out 'Write to the FIFO memory add rx1rol,#8 'Prapare for the next byte rol rx1putb,#8 WC 'C true every 4 cycles if_nc jmp dTx1 add rx1put,#1 cmp rx1put,#tx1fifo WZ if_z mov rx1put,#rx1fifo movd arp1,rx1put 'Set the new FIFO destination mov rx1out,#0 jmp dTx1 aRx1_Get cmp rx1len,#0 WZ if_z jmp dTx1 rdlong t1,rx1ptr shl t1,#1 WC 'Is the receive buffer empty? if_nc jmp dTx1 'Jump if not sub rx1len,#1 arg1 mov t1,rx1fifo ror t1,rx1ror and t1,#$ff wrlong t1,rx1ptr add rx1ror,#8 rol rx1getb,#8 WC 'C true every 4 cycles if_nc jmp dTx1 add rx1get,#1 cmp rx1get,#tx1fifo WZ if_z mov rx1get,#rx1fifo movs arg1,rx1get jmp dTx1 ' ' Transmitter ' aTx1_Start cmp tx1len,#0 WZ if_z jmp #aTx1_Put mov dTx1,#aTx1_Byte sub tx1len,#1 atg1 mov tx1data,tx1fifo ror tx1data,tx1ror and tx1data,#$ff add tx1ror,#8 rol tx1getb,#8 WC if_nc jmp dRx1 add tx1get,#1 cmp tx1get,#fifo1end WZ if_z mov tx1get,#tx1fifo movs atg1,tx1get jmp dRx1 aTx1_Byte shl tx1data,#2 or tx1data,cFixedBits 'or in a idle line state and a start bit mov tx1bits,#11 mov tx1cnt,cnt aTx1_Bits shr tx1data,#1 WC muxc OUTA,tx1mask add tx1cnt,baud1 'Bit period counter mov dTx1,#aTx1_Wait jmp dRx1 aTx1_Wait mov t1,tx1cnt 'Check bit period sub t1,CNT cmps t1,#0 WC 'Is bit period done yet? if_nc jmp #aTx1_Put djnz tx1bits,#aTx1_Bits 'Transmit next bit mov dTx1,#aTx1_Start jmp dRx1 aTx1_Put cmp tx1len,#(fifo1end-tx1fifo) WZ if_z jmp dRx1 rdlong t1,tx1ptr shl t1,#1 NR, WC if_c jmp dRx1 wrlong cMinusOne,tx1ptr add tx1len,#1 and t1,#$ff shl t1,tx1rol add tx1rol,#8 or tx1out,t1 atp1 mov tx1fifo,tx1out rol tx1putb,#8 WC if_nc jmp dRx1 add tx1put,#1 cmp tx1put,#fifo1end WZ if_z mov tx1put,#tx1fifo movd atp1,tx1put mov tx1out,#0 jmp dRx1 'General variables for the transmitter tx1len long 0 tx1maxlen long (fifo1end - tx1fifo - 1) * 4 dTx1 long aTx1_Start 'Variables used to grab the transmit a byte from the FIFO tx1data long 0 tx1bits long 0 tx1cnt long 0 tx1ror long 0 tx1get long tx1fifo tx1getb long $80 'Variables used to receive a byte into the FIFO tx1rol long 0 tx1put long tx1fifo tx1putb long $80 tx1out long 0 ' ' Data ' cFixedBits long %1_0000_0000_0_1 'Stop + 8 x Data + Start + Idle bits cMinusOne long -1 t1 long 0 t2 long 0 ' ' The buffer sizes may be freely adjusted. As long as the code still compiles ' into the cog. The sizes are currently at their maximum, but may be adjusted ' to favour either the receiver or tranmitter. ' rx1fifo res RX1FIFO_SIZE tx1fifo res TX1FIFO_SIZE fifo1end FIT 496 License┌──────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this │ │software and associated documentation files (the "Software"), to deal in the Software │ │without restriction, including without limitation the rights to use, copy, modify, │ │merge, publish, distribute, sublicense, and/or sell copies of the Software, and to │ │permit persons to whom the Software is furnished to do so, subject to the following │ │conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies │ │or substantial portions of the Software. │ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, │ │INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A │ │PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT │ │HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF │ │CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE │ │OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────┘ |