FULLDUPLEXSERIAL2
Table of Contents
Preface
Global CONstants Global VARiabes SPIN CODE Start / Stop stop mailboxaddress start_default start start start2 startExt startpasm Basic I/O RX (1) rxflush rxcheck rxready rxtime rx strin strinE read RX (2) rxflush2 rxcheck2 rxready2 rxtime2 rx2 strin2 strinE2 read2 RX (common) rxflush_ rxcheck_ rxready_ rxtime_ rx_ strin_ strinE_ strinX_ read_ TX (1) txflush txcheck tx str writehex write TX (2) txflush2 txcheck2 tx2 str2 writehex2 write2 TX (common) txflush_ txcheck_ tx_ str_ writehex_ write_ Flex-IO Flex-IO (1) Num dec decuns decuns hex hex bin bin nl printf printf Flex-IO (2) Num2 dec2 decuns2 decuns2 hex2 hex2 bin2 bin2 nl2 printf2 printf2 Flex-IO (common) Num_ dec_ decuns_ hex_ bin_ nl_ printf_ Status RX (1) rxsize rxcount RX (2) rxsize2 rxcount2 RX (common) rxsize_ rxcount_ TX (1) txsize txcount TX (2) txsize2 txcount2 TX (common) txsize_ txcount_ Async I/O RX (1) check_rxready wait_rxready strin_async read_async RX (2) check_rxready2 wait_rxready2 strin_async2 read_async2 RX (common) check_rxready_ wait_rxready_ strin_async_ read_async_ TX (1) check_txready wait_txready tx_async str_async write_async TX (2) check_txready2 wait_txready2 tx_async2 str_async2 write_async2 TX (common) check_txready_ wait_txready_ tx_async_ str_async_ write_async_ PASM Start Loop Variables Documentation MIT License |
FullDuplexSerial2
Global CONstantsSOURCE CODE... ' _tx_mode_default = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, true output, output enabled for smart output _rx_mode_default = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, true input, input enabled for smart input _tx_mode_inverted = %1000_0000_000_0000000000000_01_11110_0 'async tx mode, iverted output, output enabled for smart output _rx_mode_inverted = %1000_0000_000_0000000000000_00_11111_0 'async rx mode, inverted input, input enabled for smart input Global VARiabesSOURCE CODE... ' long cog 'cog id of this instance long rx1cmd, rx1param, tx1cmd, tx1param, rx2cmd, rx2param, tx2cmd, tx2param 'mailbox of this instance 8 longs long hmailboxaddress 'the rest just needed for start parameters long hrxpin1, hrxbitrate1, hrxmode1, hrxlutstart1, hrxlutsize1 long htxpin1, htxbitrate1, htxmode1, htxlutstart1, htxlutsize1 long hrxpin2, hrxbitrate2, hrxmode2, hrxlutstart2, hrxlutsize2 long htxpin2, htxbitrate2, htxmode2, htxlutstart2, htxlutsize2 long htxclocks byte buf[32] ' SPIN CODEStart / Stop'stop pasm cog if already runningstop()SOURCE CODE... PUB stop() if cog cogstop(cog-1) cog := 0 'return parameter address of instance mailboxaddress()SOURCE CODE... PUB mailboxaddress() : RESULT RETURN @rx1_cmd ' start with default serial pins and mode start_default(baudrate)'use this to start a 1 port driver with 1024 bytes buffer each channelSOURCE CODE... PUB start_default(baudrate) : RESULT RETURN start(63, 62, 0, baudrate) {$flexspin #ifdef __FLEXSPIN__ start(rxpin = 63, txpin = 62, mode = 0, baudrate = 230_400)SOURCE CODE... PUB start(rxpin = 63, txpin = 62, mode = 0, baudrate = 230_400) | bitrate,rxmode1,txmode1 #else} start(rxpin, txpin, mode, baudrate)mode bit 0 = invert rxmode bit 1 = invert tx mode bit 2 = open-drain/source tx - not supported yet mode bit 3 = ignore tx echo on rx - not supported yet SOURCE CODE... PUB start(rxpin, txpin, mode, baudrate) : RESULT | bitrate,rxmode1,txmode1 {$flexspin #endif} bitrate := 7 + ((CLKFREQ / baudrate) << 16) rxmode1 := _rx_mode_default txmode1 := _tx_mode_default if (mode > -1) if (mode & %1) > 0 rxmode1 := _rx_mode_inverted if (mode & %10) > 0 txmode1 := _tx_mode_inverted RETURN startpasm(@rx1cmd, rxpin, bitrate, rxmode1, 0, $3FF, txpin, bitrate, txmode1, $100, $3FF, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 100) 'use this to start a 2 port driver with 512 bytes buffer each channel start2(rxpin1, txpin1, mode1, baudrate1, rxpin2, txpin2, mode2, baudrate2)mode bit 0 = invert rxmode bit 1 = invert tx mode bit 2 = open-drain/source tx - not supported yet mode bit 3 = ignore tx echo on rx - not supported yet SOURCE CODE... PUB start2(rxpin1, txpin1, mode1, baudrate1, rxpin2, txpin2, mode2, baudrate2) : RESULT | bitrate1, bitrate2,rxmode1,rxmode2,txmode1,txmode2 bitrate1 := 7 + ((CLKFREQ / baudrate1) << 16) bitrate2 := 7 + ((CLKFREQ / baudrate2) << 16) rxmode1 := _rx_mode_default txmode1 := _tx_mode_default if (mode1 > -1) if (mode1 & %1) > 0 rxmode1 := _rx_mode_inverted if (mode1 & %10) > 0 txmode1 := _tx_mode_inverted rxmode2 := _rx_mode_default txmode2 := _tx_mode_default if (mode2 > -1) if (mode2 & %1) > 0 rxmode2 := _rx_mode_inverted if (mode2 & %10) > 0 txmode2 := _tx_mode_inverted RETURN startpasm(@rx1cmd, rxpin1, bitrate1, rxmode1, 0, $1FF, txpin1, bitrate1, txmode1, $80, $1FF, rxpin2, bitrate2, rxmode2, $100, $1FF, txpin2, bitrate2, txmode2, $180, $1FF, 100) 'use this to start whatever combination you want startExt(rxpin1, txpin1, rxbaudrate1, txbaudrate1, rxconfig1, txconfig1, rxlutstart1, rxlutsize1, txlutstart1, txlutsize1, rxpin2, txpin2, rxbaudrate2, txbaudrate2, rxconfig2, txconfig2, rxlutstart2, rxlutsize2, txlutstart2, txlutsize2, txclocks)WARNING ======= HERE RXMODE AND TXMODE ARE THE SMARTPIN CONFIGURATION, NOT THE FULLDUPLEX SERIAL MODE SOURCE CODE... PUB startExt(rxpin1, txpin1, rxbaudrate1, txbaudrate1, rxconfig1, txconfig1, rxlutstart1, rxlutsize1, txlutstart1, txlutsize1, rxpin2, txpin2, rxbaudrate2, txbaudrate2, rxconfig2, txconfig2, rxlutstart2, rxlutsize2, txlutstart2, txlutsize2, txclocks) : RESULT | rxmode1, txmode1, rxmode2, txmode2, rxbitrate1, txbitrate1, rxbitrate2, txbitrate2 if rxconfig1 == -1 rxmode1 := _rx_mode_default else rxmode1 := rxconfig1 if txconfig1 == -1 txmode1 := _tx_mode_default else txmode1 := txconfig1 if rxconfig2 == -1 rxmode2 := _rx_mode_default else rxmode2 := rxconfig2 if txconfig2 == -1 txmode2 := _tx_mode_default else txmode2 := txconfig2 rxbitrate1 := 7 + ((CLKFREQ / rxbaudrate1) << 16) txbitrate1 := 7 + ((CLKFREQ / txbaudrate1) << 16) rxbitrate2 := 7 + ((CLKFREQ / rxbaudrate2) << 16) txbitrate2 := 7 + ((CLKFREQ / txbaudrate2) << 16) RETURN startpasm(@rx1cmd, rxpin1, rxbitrate1, rxmode1, rxlutstart1, rxlutsize1, txpin1, txbitrate1, txmode1, txlutstart1, txlutsize1, rxpin2, rxbitrate2, rxmode2, rxlutstart2, rxlutsize2, txpin2, txbitrate2, txmode2, txlutstart2, txlutsize2, txclocks) 'this provides the parameter array needed to start the pasm cog on the stack startpasm(hubmailboxaddress, rxpin1, rxbitrate1, rxmode1, rxlutstart1, rxlutsize1, txpin1, txbitrate1, txmode1, txlutstart1, txlutsize1, rxpin2, rxbitrate2, rxmode2, rxlutstart2, rxlutsize2, txpin2, txbitrate2, txmode2, txlutstart2, txlutsize2, txclocks)SOURCE CODE... PRI startpasm(hubmailboxaddress, rxpin1, rxbitrate1, rxmode1, rxlutstart1, rxlutsize1, txpin1, txbitrate1, txmode1, txlutstart1, txlutsize1, rxpin2, rxbitrate2, rxmode2, rxlutstart2, rxlutsize2, txpin2, txbitrate2, txmode2, txlutstart2, txlutsize2, txclocks): RESULT stop() hmailboxaddress := hubmailboxaddress hrxpin1 := rxpin1 hrxbitrate1 := rxbitrate1 hrxmode1 := rxmode1 hrxlutstart1 := rxlutstart1 hrxlutsize1 := rxlutsize1 htxpin1 := txpin1 htxbitrate1 := txbitrate1 htxmode1 := txmode1 htxlutstart1 := txlutstart1 htxlutsize1 := txlutsize1 hrxpin2 := rxpin2 hrxbitrate2 := rxbitrate2 hrxmode2 := rxmode2 hrxlutstart2 := rxlutstart2 hrxlutsize2 := rxlutsize2 htxpin2 := txpin2 htxbitrate2 := txbitrate2 htxmode2 := txmode2 htxlutstart2 := txlutstart2 htxlutsize2 := txlutsize2 htxclocks := txclocks 'Mailbox. So now I use long[long[]] to access the first long in the later used mailbox as Flag long[long[@hmailboxaddress]] := 0 'set flag (0) to know if the started cog has read its parameters cog := coginit(NEWCOG,@cogserial_init,@hmailboxaddress) + 1 if cog 'if I was able to start the COG repeat until long[long[@hmailboxaddress]] == -1 'I wait until Flag states cog is done reading parameter and ready to roll (-1) RESULT := 1 'now start done RETURN '======================================================================= 'All of these routines need a port value, 0 for rx1 and tx1, 1 for rx2 and tx2 'if you don't provide a port value fastspin will use 0 using rx1 and tx1 '======================================================================= Basic I/ORX (1)' returns nothing flushes rx buffer (waits until buffer completely empty)rxflush()SOURCE CODE... PUB rxflush() rxflush_(0) ' check if byte received (never waits) ' returns -1 if no byte, otherwise received byte rxcheck()SOURCE CODE... PUB rxcheck() : RESULT RETURN rxcheck_(0) ' find out if a byte is ready to receive ' returns 0 if none ready rxready()SOURCE CODE... PUB rxready() : RESULT RETURN rxready_(0) ' Wait ms milliseconds for a byte to be received ' returns -1 if no byte received, $00..$FF if byte rxtime(ms)SOURCE CODE... PUB rxtime(ms) : RESULT RETURN rxtime_(ms, 0) ' receive a byte (waits until done) ' returns received byte rx()SOURCE CODE... PUB rx() : RESULT read_(@RESULT, 1, 0) RETURN RESULT ' receive a string ending with CR or NL or max size (waits until done) strin(hubaddress, size)SOURCE CODE... PUB strin(hubaddress, size) : RESULT RETURN strin_(hubaddress, size, 0) ' receive a string ending with CR or NL or max size (waits until done) ' no Echo strinE(hubaddress, size)SOURCE CODE... PUB strinE(hubaddress, size) : RESULT RETURN strinE_(hubaddress, size, 0) ' receive a block from serial to memory of given size in bytes (waits until done) read(hubaddress, size)SOURCE CODE... PUB read(hubaddress, size) : RESULT RETURN read_(hubaddress, size, 0) RX (2)' returns nothing flushes rx buffer (waits until buffer completely empty)rxflush2()SOURCE CODE... PUB rxflush2() rxflush_(1) ' check if byte received (never waits) ' returns -1 if no byte, otherwise received byte rxcheck2()SOURCE CODE... PUB rxcheck2() : RESULT RETURN rxcheck_(1) ' find out if a byte is ready to receive ' returns 0 if none ready rxready2()SOURCE CODE... PUB rxready2() : RESULT RETURN rxready_(1) ' Wait ms milliseconds for a byte to be received ' returns -1 if no byte received, $00..$FF if byte rxtime2(ms)SOURCE CODE... PUB rxtime2(ms) : RESULT RETURN rxtime_(ms, 1) ' receive a byte (waits until done) ' returns received byte rx2()SOURCE CODE... PUB rx2() : RESULT read_(@RESULT, 1, 1) RETURN RESULT ' receive a string ending with CR or NL or max size (waits until done) ' no Echo strin2(hubaddress, size)SOURCE CODE... PUB strin2(hubaddress, size) : RESULT RETURN strin_(hubaddress, size, 1) ' receive a string ending with CR or NL or max size (waits until done) ' with Echo strinE2(hubaddress, size)SOURCE CODE... PUB strinE2(hubaddress, size) : RESULT RETURN strinE_(hubaddress, size, 1) ' receive a block from serial to memory of given size in bytes (waits until done) read2(hubaddress, size)SOURCE CODE... PUB read2(hubaddress, size) : RESULT RETURN read_(hubaddress, size, 1) RX (common)' returns nothing flushes rx buffer (waits until buffer completely empty)rxflush_(port)SOURCE CODE... PUB rxflush_(port) repeat while rxcheck_(port) >= 0 ' check if byte received (never waits) ' returns -1 if no byte, otherwise received byte rxcheck_(port)SOURCE CODE... PUB rxcheck_(port) : RESULT RETURN read_(0, -2, port) ' find out if a byte is ready to receive ' returns 0 if none ready rxready_(port)SOURCE CODE... PUB rxready_(port) : RESULT RETURN rxcount_(port) ' Wait ms milliseconds for a byte to be received ' returns -1 if no byte received, $00..$FF if byte rxtime_(ms, port)SOURCE CODE... PUB rxtime_(ms, port) : rxbyte | t t := getct() repeat until (rxbyte := rxcheck_(port)) >= 0 or (getct() - t) / (clkfreq / 1000) > ms RETURN rxbyte ' receive a byte (waits until done) ' returns received byte rx_(port)SOURCE CODE... PUB rx_(port) : RESULT read_(@RESULT, 1, port) RETURN RESULT ' receive a string ending with CR or NL or max size (waits until done) ' no Echo strin_(hubaddress, size, port)SOURCE CODE... PUB strin_(hubaddress, size, port) : RESULT RETURN strinX_(hubaddress, size, 0, port) ' receive a string ending with CR or NL or max size (waits until done) ' with Echo strinE_(hubaddress, size, port)SOURCE CODE... PUB strinE_(hubaddress, size, port) : RESULT RETURN strinX_(hubaddress, size, 1, port) ' receive a string ending with CR or NL or max size (waits until done) ' with Echo strinX_(hubaddress, size, echo, port)SOURCE CODE... PUB strinX_(hubaddress, size, echo, port) : RESULT strin_async_(hubaddress, size, echo, port) RETURN wait_rxready_(port, -1) ' receive a block from serial to memory of given size in bytes (waits until done) read_(hubaddress, size, port)SOURCE CODE... PUB read_(hubaddress, size, port) : RESULT read_async_(hubaddress, size, port) RETURN wait_rxready_(port, -1) check if byte can be send (never waits) ' returns -1 if no space in buffer otherwise number of bytes free in send buffer TX (1)' Flush transmit buffer (waits until buffer completely send)txflush()SOURCE CODE... PUB txflush() txflush_(0) check if byte can be send (never waits) ' returns -1 if no space in buffer otherwise number of bytes free in send buffer txcheck()SOURCE CODE... PUB txcheck() : RESULT RETURN txcheck_(0) ' transmit a byte (waits until done) tx(val)SOURCE CODE... PUB tx(val) tx_(val, 0) ' transmit a string (waits until done) str(s)SOURCE CODE... PUB str(s) str_(s, 0) ' transmit a block from memory in HEX to serial of given size in bytes (waits until done) writehex(hubaddress, size)SOURCE CODE... PUB writehex(hubaddress, size) writehex_(hubaddress, size, 0) ' transmit a block from memory to serial of given size in bytes (waits until done) write(hubaddress, size)SOURCE CODE... PUB write(hubaddress, size) write_(hubaddress, size, 0) TX (2)' Flush transmit buffer (waits until buffer completely send)txflush2()SOURCE CODE... PUB txflush2() txflush_(1) check if byte can be send (never waits) ' returns -1 if no space in buffer otherwise number of bytes free in send buffer txcheck2()SOURCE CODE... PUB txcheck2() : RESULT RETURN txcheck_(1) ' transmit a byte (waits until done) tx2(val)SOURCE CODE... PUB tx2(val) tx_(val, 1) ' transmit a string (waits until done) str2(s)SOURCE CODE... PUB str2(s) str_(s, 1) ' transmit a block from memory in HEX to serial of given size in bytes (waits until done) writehex2(hubaddress, size)SOURCE CODE... PUB writehex2(hubaddress, size) writehex_(hubaddress, size, 1) ' transmit a block from memory to serial of given size in bytes (waits until done) write2(hubaddress, size)SOURCE CODE... PUB write2(hubaddress, size) write_(hubaddress, size, 1) TX (common)' Flush transmit buffer (waits until buffer completely send)txflush_(port)SOURCE CODE... PUB txflush_(port) | bsize bsize := txsize_(port) repeat while txcount_(port) < bsize check if byte can be send (never waits) ' returns -1 if no space in buffer otherwise number of bytes free in send buffer txcheck_(port)SOURCE CODE... PUB txcheck_(port) : RESULT RETURN write_(0, -2, port) ' transmit a byte (waits until done) tx_(val, port)SOURCE CODE... PUB tx_(val, port) write_(-1,val, port) ' transmit a string (waits until done) str_(s, port)SOURCE CODE... PUB str_(s, port) write_(s, -5, port) ' transmit a block from memory in HEX to serial of given size in bytes (waits until done) writehex_(hubaddress, size, port)SOURCE CODE... PUB writehex_(hubaddress, size, port) : RESULT | tmp, count tmp:=hubaddress count:=size/4 repeat count hex_(long[tmp], 8, port) tmp:=tmp+4 RETURN wait_txready_(port) ' transmit a block from memory to serial of given size in bytes (waits until done) write_(hubaddress, size, port)SOURCE CODE... PUB write_(hubaddress, size, port) : RESULT write_async_(hubaddress, size, port) RETURN wait_txready_(port) Flex-IOadapted for two ports and bluntly stolen from Spin2gui / fastspin (thanks Eric!) standard routines for dealing with text these are intended to extend any class with a "tx" method with the following additional methods str(s) : print a string; note that unlike standard Spin the string() wrapper is not required for string literals, because we have defaulted the parameter s to be a string dec(d) : print a signed decimal number decuns(d) : print an unsigned decimal number hex(d, n): print a hex number with n digits (n defaults to 8) bin(d, n): print a binary number with n digits (n defaults to 32) nl : print a carriage return and newline printf(s, ...) : like C printf Flex-IO (1)Num(val, base, signflag, digitsNeeded)SOURCE CODE... PUB Num(val, base, signflag, digitsNeeded) Num_(val, base, signflag, digitsNeeded, 0) ' print a signed decimal number dec(val)' print an unsigned decimal number with the specified ' number of digits; 0 means just use as many as we needSOURCE CODE... PUB dec(val) dec_(val, 0) {$flexspin #ifdef __FLEXSPIN__ decuns(val, digits = 0)SOURCE CODE... PUB decuns(val, digits = 0) #else} decuns(val, digits)' print a hex number with the specified number ' of digits; 0 means just use as many as we needSOURCE CODE... PUB decuns(val, digits) {$flexspin #endif} decuns_(val, digits, 0) {$flexspin #ifdef __FLEXSPIN__ hex(val, digits = 8)SOURCE CODE... PUB hex(val, digits = 8) #else} hex(val, digits)' print a number in binary formSOURCE CODE... PUB hex(val, digits) {$flexspin #endif} hex_(val, digits, 0) {$flexspin #ifdef __FLEXSPIN__ bin(val, digits = 32)SOURCE CODE... PUB bin(val, digits = 32) #else} bin(val, digits)SOURCE CODE... PUB bin(val, digits) {$flexspin #endif} bin_(val, digits, 0) ' print a newline nl()' C like formatted print - uses port 1SOURCE CODE... PUB nl() nl_(0) {$flexspin #ifdef __FLEXSPIN__ printf(fmt = String("")SOURCE CODE... PUB printf(fmt = String(""), an = 0, bn = 0, cn = 0, dn = 0, en = 0, fn = 0) #else} printf(fmt, an, bn, cn, dn, en, fn)SOURCE CODE... PUB printf(fmt, an, bn, cn, dn, en, fn) {$flexspin #endif} printf_(0, fmt, an, bn, cn, dn, en, fn) Flex-IO (2)Num2(val, base, signflag, digitsNeeded)SOURCE CODE... PUB Num2(val, base, signflag, digitsNeeded) Num_(val, base, signflag, digitsNeeded, 1) ' print a signed decimal number dec2(val)' print an unsigned decimal number with the specified ' number of digits; 0 means just use as many as we needSOURCE CODE... PUB dec2(val) dec_(val, 1) {$flexspin #ifdef __FLEXSPIN__ decuns2(val, digits = 0)SOURCE CODE... PUB decuns2(val, digits = 0) #else} decuns2(val, digits)' print a hex number with the specified number ' of digits; 0 means just use as many as we needSOURCE CODE... PUB decuns2(val, digits) {$flexspin #endif} decuns_(val, digits, 0) decuns_(val, digits, 1) {$flexspin #ifdef __FLEXSPIN__ hex2(val, digits = 8)SOURCE CODE... PUB hex2(val, digits = 8) #else} hex2(val, digits)' print a number in binary formSOURCE CODE... PUB hex2(val, digits) {$flexspin #endif} hex_(val, digits, 1) {$flexspin #ifdef __FLEXSPIN__ bin2(val, digits = 32)SOURCE CODE... PUB bin2(val, digits = 32) #else} bin2(val, digits)SOURCE CODE... PUB bin2(val, digits) {$flexspin #endif} bin_(val, digits, 1) ' print a newline nl2()' C like formatted print - uses port 2SOURCE CODE... PUB nl2() nl_(1) {$flexspin #ifdef __FLEXSPIN__ printf2(fmt = String("")SOURCE CODE... PUB printf2(fmt = String(""), an = 0, bn = 0, cn = 0, dn = 0, en = 0, fn = 0) #else} printf2(fmt, an, bn, cn, dn, en, fn)SOURCE CODE... PUB printf2(fmt, an, bn, cn, dn, en, fn) {$flexspin #endif} printf_(1, fmt, an, bn, cn, dn, en, fn) Flex-IO (common)Num_(val, base, signflag, digitsNeeded, port)if signflag is nonzero, it indicates we should treatval as signed; if it is > 1, it is a character we should print for positive numbers (typically "+") make sure we will not overflow our buffer accumulate the digits now print the digits in reverse order SOURCE CODE... PUB Num_(val, base, signflag, digitsNeeded, port) | i, digit, r1, q1 if (signflag) if (val < 0) signflag := "-" val := -val if (digitsNeeded > 32) digitsNeeded := 32 i := 0 repeat if (val < 0) ' synthesize unsigned division from signed ' basically shift val right by 2 to make it positive ' then adjust the result afterwards by the bit we ' shifted out r1 := val&1 ' capture low bit q1 := val>>1 ' divide val by 2 digit := r1 + 2*(q1 // base) val := 2*(q1 / base) if (digit >= base) val++ digit -= base else digit := val // base val := val / base if (digit >= 0 and digit <= 9) digit += "0" else digit := (digit - 10) + "A" buf[i++] := digit --digitsNeeded while (val <> 0 or digitsNeeded > 0) and (i < 32) if (signflag > 1) tx_(signflag, port) repeat while (i > 0) tx_(buf[--i], port) ' print a signed decimal number dec_(val, port)SOURCE CODE... PUB dec_(val, port) num_(val, 10, 1, 0, port) ' print an unsigned decimal number with the specified ' number of digits; 0 means just use as many as we need decuns_(val, digits, port)SOURCE CODE... PUB decuns_(val, digits, port) num_(val, 10, 0, digits, port) ' print a hex number with the specified number ' of digits; 0 means just use as many as we need hex_(val, digits, port)SOURCE CODE... PUB hex_(val, digits, port) | mask if digits > 0 and digits < 8 mask := (1<< (4*digits)) - 1 val &= mask num_(val, 16, 0, digits, port) ' print a number in binary form bin_(val, digits, port)SOURCE CODE... PUB bin_(val, digits, port) | mask if digits > 0 and digits < 32 mask := (1<< digits) - 1 val &= mask num_(val, 2, 0, digits, port) ' print a newline nl_(port)SOURCE CODE... PUB nl_(port) tx_(13, port) tx_(10, port) ' C like formatted print with port as param 1 printf_(port, fmt, an, bn, cn, dn, en, fn)SOURCE CODE... PUB printf_(port, fmt, an, bn, cn, dn, en, fn) | c, valptr, val valptr := @an repeat c := byte[fmt++] if (c == 0) quit if c == "%" c := byte[fmt++] if (c == 0) quit if (c == "%") tx_(c, port) next val := long[valptr] valptr += 4 case c "d": dec_(val, port) "u": decuns_(val,0, port) "x": hex_(val,8, port) "s": str_(val, port) "c": tx_(val, port) elseif c == "\" c := byte[fmt++] if c == 0 quit case c "n": nl_( port) "r": tx_(13, port) "t": tx_(8, port) other: tx_(c, port) else tx_(c, port) StatusRX (1)returns size of receive buffer in bytesrxsize()SOURCE CODE... PUB rxsize() : RESULT RETURN rxsize_(0) returns number of bytes waiting in receive buffer rxcount()SOURCE CODE... PUB rxcount() : RESULT RETURN rxcount_(0) RX (2)returns size of receive buffer in bytesrxsize2()SOURCE CODE... PUB rxsize2() : RESULT RETURN rxsize_(1) returns number of bytes waiting in receive buffer rxcount2()SOURCE CODE... PUB rxcount2() : RESULT RETURN rxcount_(1) RX (common)returns size of receive buffer in bytesrxsize_(port)SOURCE CODE... PUB rxsize_(port) : RESULT RETURN read_(0, -4, port) returns number of bytes waiting in receive buffer rxcount_(port)SOURCE CODE... PUB rxcount_(port) : RESULT RETURN read_(0, -3, port) TX (1)' returns size of send buffer in bytestxsize()SOURCE CODE... PUB txsize() : RESULT RETURN txsize_(0) ' returns number of bytes free in send buffer txcount()SOURCE CODE... PUB txcount() : RESULT RETURN txcount_(0) TX (2)' returns size of send buffer in bytestxsize2()SOURCE CODE... PUB txsize2() : RESULT RETURN txsize_(1) ' returns number of bytes free in send buffer txcount2()SOURCE CODE... PUB txcount2() : RESULT RETURN txcount_(1) TX (common)' returns size of send buffer in bytestxsize_(port)SOURCE CODE... PUB txsize_(port) : RESULT RETURN write_(0, -4, port) ' returns number of bytes free in send buffer txcount_(port)SOURCE CODE... PUB txcount_(port) : RESULT RETURN write_(0, -3, port) Async I/ORX (1)' checks if rx port cmd = -1, signaling completion of last cmd or being ready for next cmdcheck_rxready()SOURCE CODE... PUB check_rxready() : RESULT RETURN check_rxready_(0) ' waits until rx port cmd = -1, signaling completion of last cmd or being ready for next cmd wait_rxready(timeout)SOURCE CODE... PUB wait_rxready(timeout) : RESULT RETURN wait_rxready_(0, timeout) ' receive a string (does not wait for completion - you may need to check rx_cmd if done or not later in your code) strin_async(hubaddress, size, echo)SOURCE CODE... PUB strin_async(hubaddress, size, echo) strin_async_(hubaddress, size, echo, 0) ' receive a block from serial to memory of given size in bytes (does not wait for completion - you may need to check rxX_cmd for -1 [done] or not later in your code) read_async(hubaddress, size)SOURCE CODE... PUB read_async(hubaddress, size) read_async_(hubaddress, size, 0) RX (2)' checks if rx port cmd = -1, signaling completion of last cmd or being ready for next cmdcheck_rxready2()SOURCE CODE... PUB check_rxready2() : RESULT RETURN check_rxready_(1) ' waits until rx port cmd = -1, signaling completion of last cmd or being ready for next cmd wait_rxready2(timeout)SOURCE CODE... PUB wait_rxready2(timeout) : RESULT RETURN wait_rxready_(1, timeout) ' receive a string (does not wait for completion - you may need to check rx_cmd if done or not later in your code) strin_async2(hubaddress, size, echo)SOURCE CODE... PUB strin_async2(hubaddress, size, echo) strin_async_(hubaddress, size, echo, 1) ' receive a block from serial to memory of given size in bytes (does not wait for completion - you may need to check rxX_cmd for -1 [done] or not later in your code) read_async2(hubaddress, size)SOURCE CODE... PUB read_async2(hubaddress, size) read_async_(hubaddress, size, 1) RX (common)' checks if rx port cmd = -1, signaling completion of last cmd or being ready for next cmdcheck_rxready_(port)SOURCE CODE... PUB check_rxready_(port) : RESULT if port RESULT := rx2cmd else RESULT := rx1cmd ' waits until rx port cmd = -1, signaling completion of last cmd or being ready for next cmd wait_rxready_(port, timeout)SOURCE CODE... PUB wait_rxready_(port, timeout) : RESULT RESULT := -2 if port if timeout > 0 repeat timeout-- if rx2cmd == -1 RESULT := rx2param timeout := -10 until timeout < 0 if timeout > -10 rx2cmd := -1 rx2param := -1 else repeat until rx2cmd == -1 RESULT := rx2param else if timeout > 0 repeat timeout-- if rx1_cmd == -1 RESULT := rx1param timeout := -10 until timeout < 0 if timeout > -10 rx1cmd := -1 rx1param := -1 else repeat until rx1cmd == -1 RESULT := rx1param ' receive a string (does not wait for completion - you may need to check rx_cmd if done or not later in your code) strin_async_(hubaddress, size, echo, port)SOURCE CODE... PUB strin_async_(hubaddress, size, echo, port) | stringflag if echo stringflag := $2000000 else stringflag := $1000000 read_async_(hubaddress, size+stringflag, port) ' receive a block from serial to memory of given size in bytes (does not wait for completion - you may need to check rxX_cmd for -1 [done] or not later in your code) read_async_(hubaddress, size, port)SOURCE CODE... PUB read_async_(hubaddress, size, port) wait_rxready_(port, -1) if port rx2param := hubaddress rx2cmd := size else rx1param := hubaddress rx1cmd := size TX (1)' checks if tx port cmd = -1, signaling completion of last cmd or being ready for next cmdcheck_txready()SOURCE CODE... PUB check_txready() : RESULT RETURN check_txready_(0) ' waits until tx port cmd = -1, signaling completion of last cmd or being ready for next cmd wait_txready()SOURCE CODE... PUB wait_txready() : RESULT RETURN wait_txready_(0) ' sends a byte (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) tx_async(val)SOURCE CODE... PUB tx_async(val) tx_async_(val, 0) ' transmit a string (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) str_async(hubaddress)SOURCE CODE... PUB str_async(hubaddress) str_async_(hubaddress, 0) ' sends a block from memory to serial of given size in bytes (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) write_async(hubaddress, size)SOURCE CODE... PUB write_async(hubaddress, size) write_async_(hubaddress, size, 0) TX (2)' checks if tx port cmd = -1, signaling completion of last cmd or being ready for next cmdcheck_txready2()SOURCE CODE... PUB check_txready2() : RESULT RETURN check_txready_(1) ' waits until tx port cmd = -1, signaling completion of last cmd or being ready for next cmd wait_txready2()SOURCE CODE... PUB wait_txready2() : RESULT RETURN wait_txready_(1) ' sends a byte (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) tx_async2(val)SOURCE CODE... PUB tx_async2(val) tx_async_(val, 1) ' transmit a string (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) str_async2(hubaddress)SOURCE CODE... PUB str_async2(hubaddress) str_async_(hubaddress, 1) ' sends a block from memory to serial of given size in bytes (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) write_async2(hubaddress, size)SOURCE CODE... PUB write_async2(hubaddress, size) write_async_(hubaddress, size, 1) TX (common)' checks if tx port cmd = -1, signaling completion of last cmd or being ready for next cmdcheck_txready_(port)SOURCE CODE... PUB check_txready_(port) : RESULT if port RESULT := tx2cmd else RESULT := tx1cmd RETURN RESULT ' waits until tx port cmd = -1, signaling completion of last cmd or being ready for next cmd wait_txready_(port)SOURCE CODE... PUB wait_txready_(port) : RESULT if port repeat until tx2cmd == -1 RESULT := tx2param else repeat until tx1cmd == -1 RESULT := tx1param RETURN RESULT ' sends a byte (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) tx_async_(val, port)SOURCE CODE... PUB tx_async_(val, port) write_async_(-1,val, port) ' transmit a string (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) str_async_(hubaddress, port)SOURCE CODE... PUB str_async_(hubaddress, port) write_async_(hubaddress, -5, port) ' sends a block from memory to serial of given size in bytes (does not wait for completion - you may need to check tx1_cmd if done or not later in your code) write_async_(hubaddress, size, port)SOURCE CODE... PUB write_async_(hubaddress, size, port) wait_txready_(port) if port tx2param := hubaddress tx2cmd := size else tx1param := hubaddress tx1cmd := size PASMStartI am reusing most of the initialisation code space for later needed Variables. Just ignore the labels on the left until the command loopSOURCE CODE... org 0 cogserial_init loading parameters and reusing init code space for variables SOURCE CODE... rx1_mailbox_ptr rdlong rx1_mailbox_ptr, ptra++ 'pointer to mailbox in hub and rx1 mailbox hub address rx1_pin rdlong rx1_pin, ptra++ 'serial1 rxpin1 rx1_bitperiod rdlong rx1_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) rx1_mode rdlong rx1_mode, ptra++ 'configure rx1_pin for asynchronous receive, always input rx1_lut_buff rdlong rx1_lut_buff, ptra++ 'lut rx1 receive buffer address in lut rx1_lut_btop rdlong rx1_lut_btop, ptra++ 'lut rx1 receive buffer top address in lut (size for rx1) tx1_pin rdlong tx1_pin, ptra++ 'serial1 txpin tx1_bitperiod rdlong tx1_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) tx1_mode rdlong tx1_mode, ptra++ 'configure tx1_pin for asynchronous transmit, always output tx1_lut_buff rdlong tx1_lut_buff, ptra++ 'lut tx1 send buffer address in lut tx1_lut_btop rdlong tx1_lut_btop, ptra++ 'lut tx1 send buffer top address in lut (size for tx1) rx2_pin rdlong rx2_pin, ptra++ 'serial1 rx2pin rx2_bitperiod rdlong rx2_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) rx2_mode rdlong rx2_mode, ptra++ 'configure rx2_pin for asynchronous receive, always input rx2_lut_buff rdlong rx2_lut_buff, ptra++ 'lut rx2 receive buffer address in lut rx2_lut_btop rdlong rx2_lut_btop, ptra++ 'lut rx2 receive buffer top address in lut (size for rx2) tx2_pin rdlong tx2_pin, ptra++ 'serial1 tx2pin tx2_bitperiod rdlong tx2_bitperiod, ptra++ 'bitperiod := 7 + ((CLKFREQ / baudrate) << 16) tx2_mode rdlong tx2_mode, ptra++ 'configure tx2_pin for asynchronous transmit, always output tx2_lut_buff rdlong tx2_lut_buff, ptra++ 'lut tx2 send buffer address in lut tx2_lut_btop rdlong tx2_lut_btop, ptra++ 'lut tx2 send buffer top address in lut (size for tx2) tx_i_ct1wait rdlong tx_i_ct1wait, ptra++ 'sysclocks to wait between calls to tx interrupt calculate mailbox pointers for later use SOURCE CODE... rx1_param_ptr mov rx1_param_ptr, rx1_mailbox_ptr 'rx1 param hub address rx1_head add rx1_param_ptr, #4 'rx1 head position tx1_mailbox_ptr mov tx1_mailbox_ptr, rx1_param_ptr 'tx1 mailbox hub address rx1_tail add tx1_mailbox_ptr, #4 'rx1 tail position tx1_param_ptr mov tx1_param_ptr, tx1_mailbox_ptr 'tx1 param hub address rx1_i_char add tx1_param_ptr, #4 'tmp char for rx1_isr rx2_mailbox_ptr mov rx2_mailbox_ptr, tx1_param_ptr 'rx2 mailbox hub address rx1_i_address add rx2_mailbox_ptr, #4 'tmp address for rx1_isr rx2_param_ptr mov rx2_param_ptr, rx2_mailbox_ptr 'rx2 param hub address tx1_head add rx2_param_ptr, #4 'tx1 head position tx2_mailbox_ptr mov tx2_mailbox_ptr, rx2_param_ptr 'tx2 mailbox hub address tx1_tail add tx2_mailbox_ptr, #4 'tx1 tail position tx2_param_ptr mov tx2_param_ptr, tx2_mailbox_ptr 'tx2 param hub address tx_i_test add tx2_param_ptr, #4 'tmp char for tx1_send clear mailboxes SOURCE CODE... tx_i_char wrlong minusOne, tx2_param_ptr 'tmp address for tx1_send tx_i_byteindex wrlong minusOne, tx2_mailbox_ptr 'rx2 head position tx_i_ct1 wrlong minusOne, rx2_param_ptr 'rx2 tail position rx2_i_char wrlong minusOne, rx2_mailbox_ptr 'tmp char for rx2_isr rx2_i_address wrlong minusOne, tx1_param_ptr 'tmp address for rx2_isr tx2_head wrlong minusOne, tx1_mailbox_ptr 'tx2 head position tx2_tail wrlong minusOne, rx1_param_ptr 'tx2 tail position Reset rx1 clear buffer pointers enable pin and int1 SOURCE CODE... mov rx1_head, #0 'reset serial buffer pointers mov rx1_tail, #0 rx1_i_lut_value cmp rx1_pin, minusOne wz 'tmp address for tx2_send 'if rx1_pin == -1 tx_i_tail if_z jmp #end_rx1_reset 'tmp cmd used for HEX and DEC out ' skip RX1 setting smart pin '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - setint1 #0 'disable int1 dirl rx1_pin 'disable receiver mov rx1_i_char, #%110<<6 add rx1_i_char, rx1_pin wrpin rx1_mode, rx1_pin 'configure rx_pin for asynchronous receive, always input wxpin rx1_bitperiod, rx1_pin setse1 rx1_i_char 'set se1 to trigger on rx1_pin (rx1_pin high) mov ijmp1, #rx1_isr 'set int1 jump vector to rx1 ISR setint1 #4 'set int1 to trigger on se1 rx1_i_byte_index dirh rx1_pin 'enable receiver end_rx1_reset Reset tx1 set tx1_mode and tx1_bitperiod, enable pin SOURCE CODE... tx1_param mov tx1_head, #0 'tmp parameter for tx1 cmd 'reset serial buffer pointers lutvalue mov tx1_tail, #0 rx2_i_byte_index cmp tx1_pin, minusOne wz 'if tx1_pin == -1 tx_i_lutbuf if_z jmp #end_tx1_reset 'value used in command loop ' skip setting TX1 smart pin '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - byteindex dirl tx1_pin 'tmp parameter for rx1 cmd 'disable transmitter rx2_i_lut_value wrpin tx1_mode, tx1_pin 'configure tx1_pin for asynchronous transmit, always output cmd wxpin tx1_bitperiod, tx1_pin 'tmp parameter for rx2 cmd tx2_param dirh tx1_pin 'tmp parameter for tx2 cmd 'enable transmitter end_tx1_reset ' ' Reset rx2 clear buffer pointers enable pin and int2 ' rx2_head mov rx2_head, #0 'tx_i_ct1 used in tx_isr 'reset serial buffer pointers rx2_tail mov rx2_tail, #0 'tx_i_ct1wait used in tx_isr lutaddress cmp rx2_pin, minusOne wz 'lutaddress used in command loop 'if rx2_pin == -1 value if_z jmp #end_rx2_reset 'value used in command loop ' skip RX2 setting smart pin '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - txblock setint2 #0 'tmp parameter for tx2 cmd 'disable int2 pxtail dirl rx2_pin 'pointer to current TXtail 'disable receiver tx_i_address mov rx2_i_char, #%110<<6 'txdec used by HEX/DEC tx_i_lutvalue add rx2_i_char, rx2_pin 'pointer for output of HX/DEC txcogptr wrpin rx2_mode, rx2_pin 'pointer for output of HX/DEC 'configure rx_pin for asynchronous receive, always input txloopctr wxpin rx2_bitperiod, rx2_pin lutbuff setse2 rx2_i_char 'set se1 to trigger on rx1_pin (rx1_pin high) pxdonewritepar mov ijmp2, #rx2_isr 'set int2 jump vector to rx2 ISR pxdone setint2 #5 'pointer to current TX donewritepar 'set int2 to trigger on se2 lutbtop dirh rx2_pin 'enable receiver end_rx2_reset Reset tx2 set tx2_mode and tx2_bitperiod, enable pin SOURCE CODE... pxcmd mov tx2_head, #0 'reset serial buffer pointers pxparam mov tx2_tail, #0 head cmp tx2_pin, minusOne wz 'if tx2_pin == -1 tail if_z jmp #end_tx2_reset ' skip setting TX2 smart pin '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - pxhead dirl tx2_pin 'disable transmitter tx1_address wrpin tx2_mode, tx2_pin 'configure tx2_pin for asynchronous transmit, always output rx1_param wxpin tx2_bitperiod, tx2_pin 'tmp parameter for rx1 cmd cmdparam dirh tx2_pin 'enable transmitter end_tx2_reset Enable int3 for TX SOURCE CODE... tx2_address mov ijmp3, #tx_isr 'set int3 vector - later sysclocks to wait for in tx_isr rx2_param setint3 #1 'tmp parameter for rx2 cmd 'set int3 for ct-passed-ct1 event later decimal num to send rxstring getct tx_i_ct1 'set initial tx_i_ct1 target txmailboxpointer addct1 tx_i_ct1, tx_i_ct1wait 'this tells calling cog we got the parameters and are ready to roll SOURCE CODE... pxgetchar wrlong minusOne, rx1_mailbox_ptr 'write -1 into rx1_mailbox_ptr in the HUB, now cogstart finished Loop'======================================================================= ' 'command loop - calls R1/TX1/RX2/TX2 routines to check the mailboxes and to do HUB/LUT LUT/HUB buffer transfer ' - first check if pin used (<>-1) then check if last command still running (<>-1) ' - if not get new one, else resume old one ' - do this for each channel. ' '======================================================================= SOURCE CODE... rx1_cmd_check cmp rx1_pin, minusOne wz 'RX1 pin active? 'gone 8 if_z jmp #tx1_cmd_check 'no - check TX1 next cmp rx1_cmd, minusOne wz 'old cmd finished? if_z rdlong rx1_cmd, rx1_mailbox_ptr 'yes - new cmd from rx1 mailbox if_z rdlong rx1_param, rx1_param_ptr 'yes - new param from rx1 mailbox cmp rx1_cmd, minusOne wz 'do we have a active command running? if_z jmp #tx1_cmd_check 'no - check TX1 next mov pxdonewritepar, #rx1_donewritepar 'set up pointers and values for RX1 mov pxdone, #rx1_done 'to use a common rxdocmd mov pxgetchar, #rx1_get_value mov pxparam, #rx1_param mov pxcmd, #rx1_cmd mov pxtail, #rx1_tail mov txmailboxpointer, tx1_mailbox_ptr mov lutbuff, rx1_lut_buff mov lutbtop, rx1_lut_btop mov head, rx1_head mov tail, rx1_tail mov cmd, rx1_cmd call #rxdocmd 'and call the common rxdocmd tx1_cmd_check cmp tx1_pin, minusOne wz 'TX1 pin active? if_z jmp #rx2_cmd_check 'no - check RX2 next cmp tx1_cmd, minusOne wz 'old cmd finished? if_z rdlong tx1_cmd, tx1_mailbox_ptr 'yes - new cmd from tx1 mailbox if_z rdlong tx1_param, tx1_param_ptr 'yes - new param from tx1 mailbox cmp tx1_cmd, minusOne wz 'do we have a active command running? if_z jmp #rx2_cmd_check 'no - check RX2 next mov pxdonewritepar, #tx1_donewritepar 'set up pointers and values for TX1 mov pxdone, #tx1_done 'to use a common txdocmd mov pxparam, #tx1_param mov pxcmd, #tx1_cmd mov pxhead, #tx1_head mov pxtail, #tx1_tail mov lutbtop, tx1_lut_btop mov lutbuff, tx1_lut_buff mov head, tx1_head mov tail, tx1_tail mov cmd, tx1_cmd call #txdocmd 'and call the common txdocmd rx2_cmd_check cmp rx2_pin, minusOne wz 'RX2 pin active? if_z jmp #tx2_cmd_check 'no - check TX2 next cmp rx2_cmd, minusOne wz 'old cmd finished? if_z rdlong rx2_cmd, rx2_mailbox_ptr 'yes - new cmd from rx2 mailbox if_z rdlong rx2_param, rx2_param_ptr 'yes - new param from rx2 mailbox cmp rx2_cmd, minusOne wz 'do we have a active command running? if_z jmp #tx2_cmd_check 'no - check TX2 next mov pxdonewritepar, #rx2_donewritepar 'set up pointers and values for RX2 mov pxdone, #rx2_done 'to use a common rxdocmd mov pxgetchar, #rx2_get_value mov pxparam, #rx2_param mov pxcmd, #rx2_cmd mov pxtail, #rx2_tail mov txmailboxpointer, tx2_mailbox_ptr mov lutbuff, rx2_lut_buff mov lutbtop, rx2_lut_btop mov head, rx2_head mov tail, rx2_tail mov cmd, rx2_cmd call #rxdocmd 'and call the common rxdocmd tx2_cmd_check cmp tx2_pin, minusOne wz 'TX2 pin active? if_z jmp #rx1_cmd_check 'no - check RX1 next -- loop cmp tx2_cmd, minusOne wz 'old cmd finished? if_z rdlong tx2_cmd, tx2_mailbox_ptr 'yes - new cmd from tx2 mailbox if_z rdlong tx2_param, tx2_param_ptr 'yes - new param from tx2 mailbox cmp tx2_cmd, minusOne wz 'do we have a active command running? if_z jmp #rx1_cmd_check 'no - check RX1 next -- loop mov pxdonewritepar, #tx2_donewritepar 'set up pointers and values for TX2 mov pxdone, #tx2_done 'to use a common xdocmd mov pxparam, #tx2_param mov pxcmd, #tx2_cmd mov pxhead, #tx2_head mov pxtail, #tx2_tail mov lutbtop, tx2_lut_btop mov lutbuff, tx2_lut_buff mov head, tx2_head mov tail, tx2_tail mov cmd, tx2_cmd call #txdocmd 'and call the common txdocmd jmp #rx1_cmd_check ' -- loop '======================================================================= ' ' INT 1 - rx1 read interrupt writes byte in lut buffer, runs if pin receives a char ' '======================================================================= SOURCE CODE... rx1_isr rdpin rx1_i_char, rx1_pin 'get received char shr rx1_i_char, #32-8 'shift char to lsb justify mov rx1_i_address, rx1_head 'do I have space in my buffer? incmod rx1_i_address, rx1_lut_btop 'rx1_i_char = head+1 cmp rx1_i_address, rx1_tail wz 'hitting tail is bad if_z reti1 'and return if buffer full - we lost a char - exit mov rx1_i_byte_index, rx1_head 'take last two bits of head and rx1_i_byte_index, #%11 'now index 0 to 3 mov rx1_i_address, rx1_head 'adjust address to buffer start (I need the long containing the byte) shr rx1_i_address, #2 'adjust address to buffer start add rx1_i_address, rx1_lut_buff 'by adding rx1_lut_buff rdlut rx1_i_lut_value, rx1_i_address 'get correct LUT long altsb rx1_i_byte_index, #rx1_i_lut_value 'patch the index setbyte 0, rx1_i_char, #0-0 'change the needed byte wrlut rx1_i_lut_value, rx1_i_address 'write long back to circular buffer in lut incmod rx1_head, rx1_lut_btop 'increment buffer head reti1 '======================================================================= ' ' INT 2 - rx2 read interrupt writes byte in lut buffer, runs if pin receives a char ' '======================================================================= SOURCE CODE... rx2_isr rdpin rx2_i_char, rx2_pin 'get received chr shr rx2_i_char, #32-8 'shift char to lsb justify mov rx2_i_address, rx2_head 'do I have space in my buffer? incmod rx2_i_address, rx2_lut_btop 'rx2_i_char = head+1 mod cmp rx2_i_address, rx2_tail wz 'hitting tail is bad if_z reti2 'and return if buffer full - we lost a char - exit ' shr rx2_i_char, #32-8 'shift char to lsb justify mov rx2_i_byte_index, rx2_head 'take last two bits of head and rx2_i_byte_index, #%11 'now index 0 to 3 mov rx2_i_address, rx2_head 'adjust to buffer start (I need the long containing the byte) shr rx2_i_address, #2 'adjust address to buffer start add rx2_i_address, rx2_lut_buff 'by adding rx2_lut_buff rdlut rx2_i_lut_value, rx2_i_address 'get correct LUT long altsb rx2_i_byte_index, #rx2_i_lut_value 'patch the index setbyte 0, rx2_i_char, #0-0 'change the needed byte wrlut rx2_i_lut_value, rx2_i_address 'write long back to circular buffer in lut incmod rx2_head, rx2_lut_btop 'increment buffer head reti2 '======================================================================= ' ' INT 3 - tx write interrupt, reads bytes from lut buffer , runs once every tx_i_ct1wait clocks ' '======================================================================= SOURCE CODE... tx_isr cmp tx1_pin, minusOne wz 'tx1 active? if_z jmp #.tx2_send 'no - check tx2 '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmp tx1_head, tx1_tail wz 'tx1 byte to send? if_z jmp #.tx2_send 'no - wait for next time '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - rdpin tx_i_test, tx1_pin wc 'wait for pin ready? if_c jmp #.tx2_send 'no - wait for next time '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov tx_i_tail, tx1_tail 'adjust to buffer start mov tx_i_lutbuf, tx1_lut_buff 'by adding tx1_lut_buff call #.txgetlutchar 'get the needed byte incmod tx1_tail, tx1_lut_btop 'increment buffer tail wypin tx_i_char, tx1_pin 'send the byte '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .tx2_send cmp tx2_pin, minusOne wz 'tx2 active? if_z jmp #.end_isr 'no - done '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmp tx2_head, tx2_tail wz 'tx2 byte to send? if_z jmp #.end_isr 'no - wait for next time '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - rdpin tx_i_test, tx2_pin wc 'wait for pin ready? if_c jmp #.end_isr 'no - wait for next time '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov tx_i_tail, tx2_tail 'adjust to buffer start mov tx_i_lutbuf, tx2_lut_buff 'by adding tx2_lut_buff call #.txgetlutchar 'get the needed byte incmod tx2_tail, tx2_lut_btop 'increment buffer tail wypin tx_i_char, tx2_pin 'send the byte '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .end_isr addct1 tx_i_ct1, tx_i_ct1wait 'update txct1 target reti3 'return to main program .txgetlutchar mov tx_i_byteindex, tx_i_tail 'take last two bits of tail and tx_i_byteindex, #%11 'now index 0 to 3 mov tx_i_address, tx_i_tail 'adjust to buffer start (I need the long containing the byte) shr tx_i_address, #2 'adjust address to buffer start add tx_i_address, tx_i_lutbuf 'by adding txX_lut_buff rdlut tx_i_lutvalue, tx_i_address 'get correct LUT long altgb tx_i_byteindex, #tx_i_lutvalue 'patch the index _ret_ getbyte tx_i_char, tx_i_lutvalue, #0 'get the needed byte '======================================================================= ' ' used for both RX and both TX ports ' '======================================================================= getbufused mov value, head 'returns count of bytes used in given buffe in value cmps head, tail wcz 'if head<tail if_b add value, lutbtop 'add size to head if_b add value, #1 _ret_ sub value, tail 'subtract tail fixindexaddress and byteindex, #%11 shr lutaddress, #2 _ret_ add lutaddress, lutbuff 'by adding txX_lut_buff '======================================================================= ' ' handle rx mailboxes ' '======================================================================= rx1_get_value call #rxgetrxchar _ret_ incmod rx1_tail, rx1_lut_btop 'increment buffer tail rx2_get_value call #rxgetrxchar _ret_ incmod rx2_tail, rx2_lut_btop 'increment buffer tail rxgetrxchar mov byteindex, tail mov lutaddress, tail 'adjust to buffer start call #fixindexaddress rdlut lutvalue, lutaddress 'get byte from circular buffer in lut altgb byteindex, #lutvalue _ret_ getbyte value, lutvalue, #0 rx1_donewritepar wrlong value, rx1_param_ptr 'write rx1 parameter back in HUB rx1_done mov rx1_cmd, minusOne _ret_ wrlong rx1_cmd, rx1_mailbox_ptr 'rx1 command finished rx2_donewritepar wrlong value, rx2_param_ptr 'rx2 parameter back in HUB rx2_done mov rx2_cmd, minusOne _ret_ wrlong rx2_cmd, rx2_mailbox_ptr 'rx2 command finished '= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ' 'used for both RX ports ' '= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = rxdocmd cmps cmd, #0 wcz '#rx_block also string if_ge jmp #.blockread cmp cmd, minusTwo wz '#rx_check if_nz jmp #.negcmd mov value, minusOne '#value cmp head, tail wz 'byte received? if_nz call pxgetchar+0 jmp pxdonewritepar+0 .negcmd neg cmd mov cmdparam, cmd shr cmdparam, #8 and cmd, #$FF cmp cmd, #3 wz 'get count of bytes in rx buffer if_z jmp #.count cmp cmd, #4 wz 'get size of rx buffer if_z mov value, lutbtop if_z jmp pxdonewritepar+0 'returns size of receive buffer jmp pxdone+0 .count call #getbufused 'returns count of bytes in receive buffer RXx in value jmp pxdonewritepar+0 .blockread mov rxstring, #0 cmps cmd, ##$1000000 wcz if_ge mov rxstring, #1 cmps cmd, ##$2000000 wcz if_ge mov rxstring, #2 and cmd, ##$FFFFFF cmp cmd, #0 wz 'need more bytes? if_z jmp pxdone+0 'no - clear rx_mailbox - rxblock finished cmps head, tail wcz 'byte received? if_b mov byteindex, lutbtop 'Head less then tail, add buffer size if_b add byteindex, #1 ' if_g mov byteindex, #0 'Head pointer bigger then tail all OK if_z ret wz 'no - buffer empty - try again don't block the rest '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - call pxgetchar+0 cmp rxstring, #1 wz 'string input without echo? if_z jmp #.isstring cmp rxstring, #2 wz 'string input with echo? if_z jmp #.isstring jmp #.nostring .isstring cmp cmd, #1 wz 'if max string len if_z jmp #.writezero 'terminate string and command cmp value, #13 wz 'if CR if_z jmp #.writezero 'terminate string and command cmp value, #10 wz 'if LF if_z jmp #.writezero 'terminate string and command cmp rxstring, #1 wz 'string input without echo? if_z jmp #.nostring cmp pxdone, #rx1_done wz 'port1? if_nz jmp #.echo2 stalli 'string input with echo 1 .waitecho1 rdpin tx_i_test, tx1_pin wc 'wait for pin ready if_c jmp #.waitecho1 wypin value, tx1_pin 'send the byte allowi jmp #.nostring 'terminate string and command .echo2 stalli 'string input with echo 2 .waitecho2 rdpin tx_i_test, tx2_pin wc 'wait for pin ready if_c jmp #.waitecho2 wypin value, tx2_pin 'send the byte allowi jmp #.nostring 'terminate string and command .writezero mov value, #0 'end of string input - terminate string and command call #.nostring 'add zero to buffer to end string jmp pxdone+0 'clear rx_mailbox - rx_block (string) finished .nostring alts pxparam wrbyte value, 0-0 'write byte to Block altd pxparam add 0-0, #1 'adjust Block address altd pxcmd _ret_ sub 0-0, #1 'adjust count - try again don't block the rest '======================================================================= ' ' handle tx mailboxes ' '======================================================================= tx1_donewritepar wrlong value, tx1_param_ptr 'return tx1 result tx1_done mov tx1_cmd, minusOne _ret_ wrlong tx1_cmd, tx1_mailbox_ptr 'clear tx1_mailbox - tx1_cmd finished tx2_donewritepar wrlong value, tx2_param_ptr 'return tx2 result tx2_done mov tx2_cmd, minusOne _ret_ wrlong tx2_cmd, tx2_mailbox_ptr 'clear tx2_mailbox - tx2_cmd finished '= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ' 'used by both TX ports ' '= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = txdocmd cmps cmd, #0 wcz '#txX_block if_ge jmp #.blockwrite neg cmd mov cmdparam, cmd shr cmdparam, #8 and cmd, #$FF cmp cmd, #2 wz 'get count of free bytes in tx buffer or -1 if full if_z jmp #.check cmp cmd, #3 wz 'get count of free bytes in tx buffer if_z jmp #.count cmp cmd, #4 wz 'get size of tx buffer if_z mov value, lutbtop if_z jmp pxdonewritepar+0 cmp cmd, #5 wz 'output str on tx1 if_nz jmp pxdone+0 'clear tx_mailbox - done '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .blockwrite mov lutaddress, head 'returns tx_head+1 incmod lutaddress, lutbtop 'in lutaddress cmp lutaddress, tail wz 'space in buffer? if_z ret 'no - buffer full - try again don't block the rest '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - altd pxparam cmp 0-0, minusOne wz 'if param == -1 just single char if_nz jmp #.notsinglechar mov value, cmd 'send it and done call #.putlutchar jmp pxdone+0 .notsinglechar cmps cmd, #0 wcz 'more bytes? if_le jmp pxdone+0 'no - clear tx_mailbox - txblock finished mov value, #0 alts pxparam rdbyte value, 0-0 'get next char altd pxcmd cmp 0-0, minusFive wz 'string output? if_nz altd pxcmd if_nz sub 0-0, #1 'no - adjust count of bytes to send if_z cmp value, #0 wz 'yes - more bytes? if_z jmp pxdone+0 'no - clear tx1_mailbox - tx1_block (string) finished call #.putlutchar altd pxparam 'Hubaddress Neilbox Parameter current TX _ret_ add 0-0, #1 'adjust buffer address .putlutchar mov lutaddress, lutbuff shl lutaddress, #2 add lutaddress, head mov byteindex, lutaddress and byteindex, #%11 shr lutaddress, #2 rdlut lutvalue, lutaddress altsb byteindex, #lutvalue setbyte 0, value, #0 wrlut lutvalue, lutaddress altd pxhead _ret_ incmod 0-0, lutbtop 'increment buffer head .check mov value, minusOne 'returns -1 or count of bytes in transmit buffer for tx1 mov lutaddress, head 'returns tx_head+1 incmod lutaddress, lutbtop 'in lutaddress cmp lutaddress, tail wz if_z jmp pxdonewritepar+0 'return buffer full else return tx1_count '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .count call #.countvalue jmp pxdonewritepar+0 'return tx buffer count (bytes current free in buffer) .countvalue call #getbufused neg value 'bytes used add value, lutbtop 'bytes free _ret_ add value, #1 VariablesSOURCE CODE... minusOne long -1 minusTwo long -2 minusFive long -5 rx1_cmd long -1 tx1_cmd long -1 rx2_cmd long -1 tx2_cmd long -1 DocumentationThis .spin file supports PhiPi's great Spin Code Documenter found at http://www.phipi.com/spin2html/ You can at any time create a .htm Documentation out of the .spin source. If you change the .spin file you can (re)create the .htm file by uploading your .spin file to http://www.phipi.com/spin2html/ and then saving the the created .htm page. MIT 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. | |______________________________________________________________________________________| |