I ported the Tiny-Software-Transmitter to PIC MC. The attached sample realizes a software UART (in fact ist an 'AT', because ist neither Universal nor a Receiver but an RS232 Asynchron Transmitter).
Tiny means, there are only 24 words (!) added to the hex to be able to send a byte.
- 13 lines of assembler code
- no timers are used
- no other hardware modules are used
- no interrupt is used
- 9600 - 128000 baud are possible at 16 Mhz
- 8N1 format only
- Tx-Pin is user configurable
Because I'm new to ASM I need some help. The code works for me on a PIC12f1501 an a PIC18f13k50. But it lacks on 'bank selection' and 'page selection' in the asm code. Can that be a problem, if the code would be inserted in another (more complex) program? How can this be fixed? If I try to add 'banksel' in the code, GCB generates an error - why?
Frank
The sample:
'''A demonstration program for GCB - PIC only -'''---------------------------------------------------------------------------------'''This program is a super slim software serial transmitter (151 words on a PIC12f1501)'''realizedwith13-lineasmcode,PIC-Assemblersoit's PIC only'''testedupto128000baudona16MhzPIC12f1501'''The pulse polarity ist designed for TTL-USB-Serial-Converters,'''toinvert,switchbcf/bsf(...TTX_PORT,TTX_PIN)inTTxSendByte''''''@authorFrankSteinbergguidedbythecodeofRalphDoncaster:''' http://nerdralph.blogspot.de/2013/12/writing-avr-assembler-code-with-arduino.html'''@licenceGPL'''@version 1.0'''@date21.12.2016'''********************************************************************************; ----- Configuration#chip 12F1501, 16#config LVP = Off#option Explicit'OSCCON=b'01011010''set internal oscillator to 1 Mhz'OSCCON=b'01110010''set internal oscillator to 8 Mhz OSCCON = b'01111010' 'setinternaloscillatorto16Mhz;----- Define Hardware settings;ConfigTinySoftwareTx:;calculatedelay-counter:TTX_DELAY=((CPUFrequency/4/BaudRate)-11)/3);16Mhz:7=1280008=11520019=5760031=3840043=2880066=19200135=9600;1Mhz:5=960031=2400#defineTTX_DELAY8'115200 baud#define TTX_PORT PORTA 'usethisporttosendserialdata#defineTTX_PIN2'use this pin to send serial dataDir TTX_PORT.TTX_PIN Out '...andmakeitoutputSetTTX_PORT.TTX_PINOn'set HIGH to make the first startbit recognizable; ----- VariablesDim xx As Bytexx = 48 'beginwitha0DimTTxSVarAsString*20'create a string; ----- Main body of program commences here. Do Forever TTxSendByte(13) 'newlineinTerminalTTxSendByte(10)TTxSendByte(">")TTxSendByte(xx)'send an alternating byte TTxSendText(" TinyTx Software Transmitter ") 'sendthetext'TTxSVar = Str(xx) 'Str(xx)adds278bytecode!'TTxSendString xx += 1 'alternatebyteWait1s'time to enjoy the result Loop 'jumpbacktothestartoftheprogramSubTTxSendText(InTTxText)'Send given text bytewise Dim TTxText As String * 20 'createastringDimiiAsByteForii=1ToTTxText(0)'first byte in array is the string-length TTxSendByte(TTxText(ii)) 'sendviasubroutineNextEndSubSubTTxSendString'Send string >TTxSVar< bytewise Dim ii As Byte For ii = 1 To TTxSVar(0) 'firstbyteinarrayisthestring-lengthTTxSendByte(TTxSVar(ii))'send via subroutine NextEnd SubSub TTxSendByte (In TTxDataByte) 'serialoutonebyte(8databit,noparitybit,1stopbit)DimTTxDlyCnt,TTxBitCntAsByteTTxBitCnt=10;10bitstotransmit(1start+8data+1stop)bcfSTATUS,C;clearCarryFlagto0(neededforstartbitLOW)TTxLoop:btfssSTATUS,C;skipnextlineifCarryFlag=1bcfTTX_PORT,TTX_PIN;setpinLOWifCarryFlag=0btfscSTATUS,C;skipnextlineifCarryFlag=0bsfTTX_PORT,TTX_PIN;setpinHIGHifCarryFlag=1TTxDlyCnt=TTX_DELAY;numberofdelay-loopsdecfszTTxDlyCnt,1;decrementdelaycounter,skipnextlineif0GOTO$-1;looptolineaboveuntildelaycounter=0bsfSTATUS,C;setCarryFlagto1(fillsdatabytewith8*1-neededforstopbitHIGH)rrfTTxDataByte,1;shiftnextbittoCarryFlagdecfszTTxBitCnt,1;decrementbitcounter,skipnextlineif0GOTOTTxLoop;processnextbituntilbitcounter=0EndSub
Last edit: Frank Steinberg 2016-12-22
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Do not struggle with banksel - simply mix ASM and Great Cow BASIC.
You assign a variable. Use GCB assignment. GCB will sort out pages andg banks.
You need a goto. Use GCB goto. GCB will sort the correct addressing across all the chips.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You assign a variable. Use GCB assignment. GCB will sort out pages andg banks.
I wonder if is's really ruled out, that GCB adds a 'banksel'. In this case the asm code won' t work anymore, because the jumps are only to the next line. I could handle that by adding goto-jumps to labels !? But that is extra code an slows it down (slightly).
You need a goto. Use GCB goto. GCB will sort the correct addressing across all the chips.
How can I force that; it's the same command?
Frank
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You lucky one!
I am filled with family and Christmas obligations until the 26th.
Ideas for the next steps:
creating compatible code for IC and AVR
finding a smart way to detect the interrupt status (enabled or not) to restore it after sending a byte
to do the baud calculation by a script
creating a proper GCB library
That's my last code, so the first step is mostly done (hopefully)
'''A demonstration program for GCB - PIC only -'''---------------------------------------------------------------------------------'''This program is a super slim software serial transmitter (151 words on a PIC12f1501)'''realizedwith13-lineasmcode,PIC-Assemblersoit's PIC only'''testedupto128000baudona16MhzPIC12f1501'''The pulse polarity ist designed for TTL-USB-Serial-Converters,'''toinvert,switchbcf/bsf(...TTX_PORT,TTX_PIN)inTTxSendByte''''''@authorFrankSteinbergguidedbythecodeofRalphDoncaster:''' http://nerdralph.blogspot.de/2013/12/writing-avr-assembler-code-with-arduino.html'''@licenceGPL'''@version 1.0'''@date24.12.2016'''********************************************************************************; ----- Configuration#chip 12F1501, 16#config LVP = Off#option Explicit'OSCCON=b'01011010''set internal oscillator to 1 Mhz'OSCCON=b'01110010''set internal oscillator to 8 Mhz OSCCON = b'01111010' 'setinternaloscillatorto16Mhz;----- Define Hardware settings;ConfigTinySoftwareTx:;calculatedelay-counter:TTX_DELAY=((CPUFrequency/4/BaudRate)-13)/3);16Mhz:6=1280007=11520019=5760031=3840043=2880066=19200135=9600;1Mhz:5=960031=2400#defineTTX_DELAY6'115200 baud#define TTX_PIN PORTA.2 'usethispintosendserialdataDirTTX_PINOut'... and make it outputSet TTX_PIN On 'setHIGHtomakethefirststartbitrecognizable;----- VariablesDimxxAsBytexx=48'begin with a 0Dim TTxSVar As String * 20 'createastring;----- Main body of program commences here.DoForeverTTxSendByte(13)'new line in Terminal TTxSendByte(10) TTxSendByte("T") TTxSendText("inyTx Software Transmitter: ") 'sendatextTTxSendByte(xx)'send an alternating byte 'TTxSVar=Str(xx)'Str(xx) adds 278 byte code! 'TTxSendStringxx+=1'alternate byte Wait 1 s 'timetoenjoytheresultLoop'jump back to the start of the programSub TTxSendText (In TTxText) 'SendgiventextbytewiseDimTTxTextAsString*20'create a string Dim ii As Byte For ii = 1 To TTxText(0) 'firstbyteinarrayisthestring-lengthTTxSendByte(TTxText(ii))'send via subroutine NextEnd SubSub TTxSendString 'Sendstring>TTxSVar<bytewiseDimiiAsByteForii=1ToTTxSVar(0)'first byte in array is the string-length TTxSendByte(TTxSVar(ii)) 'sendviasubroutineNextEndSubSubTTxSendByte(InTTxDataByte)'serialoutonebyte(8databit,noparitybit,1stopbit)DimTTxDlyCnt,TTxBitCntAsByteTTxBitCnt=10;10bitstotransmit(1start+8data+1stop)[GCB]bcfSTATUS,C;clearCarryFlagto0(neededforstartbitLOW)[ASM]TTxLoop:;9cycleloop+delayperbytebtfscSTATUS,C;skipnextlineifCarryFlag=0[ASM]gotoTTx1;gotoTTx1ifCarryFlag=1SetTTX_PINOff;setpinLOWifCarryFlag=0[GCB]TTx1:btfssSTATUS,C;skipnextlineifCarryFlag=1[ASM]gotoTTxDone;gotoTTxDoneifCarryFlag=0SetTTX_PINOn;setpinHIGHifCarryFlag=1[GCB]TTxDone:TTxDlyCnt=TTX_DELAY;numberofdelay-loops[GCB]TTxDelay:;delay-loop=(xcycle*delaycounter)-1decfszTTxDlyCnt,F;decrementdelaycounter,skipnextlineif0[ASM]gotoTTxDelay;looptoTTxDelayuntildelaycounter=0bsfSTATUS,C;setCarryFlagto1(fillsdatabytewith8*1-neededforstopbitHIGH)[ASM]rrfTTxDataByte,F;shiftnextbittoCarryFlag[ASM]decfszTTxBitCnt,F;decrementbitcounter,skipnextlineif0[ASM]gotoTTxLoop;processnextbituntilbitcounter=0EndSub
... and for AVR:
'''A demonstration program for GCB - AVR only -'''--------------------------------------------------------------------------------------------------------------------------------'''This program is a super slim software serial transmitter (322 bytes flash)'''realizedwith15-lineasmcode,AVR-Assemblersoit's AVR only''' tested up to 256000 baud on an 16 or 16.5 Mhz attiny85 (digispark)'''ThepulselogicistdesignedforTTL-USB-Serial-Converters,''' to invert, switch On / Off in Line 66 & 69 (Set TTX_PIN ...)''''''@author Frank Steinberg with the largest portion of Ralph Doncaster:'''http://nerdralph.blogspot.de/2013/12/writing-avr-assembler-code-with-arduino.html'''@licence GPL'''@version1.0'''@date 24.12.2016'''********************************************************************************;-----Configuration#chip tiny85, 16 'intended for digispark board#option Explicit;-----DefineHardwaresettings;ConfigSoftwareTx:;[calculatedelay-counter:TTX_DELAY=((CPUFrequency/BaudRate)-9)/3)]#define TTX_DELAY 17 '16.5Mhz: 17=256000 19=230400 44=115200 '1Mhz: 5=38400 135=2400#define TTX_PIN PORTB.3 'use this port to send serial dataDirTTX_PINOut'... and make it outputSetTTX_PINOn'set HIGH to make the first startbit recognizable;-----VariablesDimTTxSVarAsString*20'create a stringDimxxAsBytexx=48'begin with a 0;-----Mainbodyofprogramcommenceshere.DoForeverTTxSendByte(13)'new line in TerminalTTxSendByte(10)'TTxSendByte("T")'this is a valid byte tooTTxSendText("inyTx Software Transmitter: ")'send a textTTxSendByte(xx)'send an alternating byte'TTxSendByte(9) 'Tab'TTxSVar = Str(xx) 'thisadds564bytecode!'TTxSendString 'thisadds2bytecodexx+=1'alternate byteWait1s'time to enjoy the resultLoopSubTTxSendText(InTTxText)'Send given text bytewiseDimTTxTextAsString*20'create a stringDimiiAsByteForii=1ToTTxText(0)'first byte in array is the string-lengthTTxSendByte(TTxText(ii))'send via subroutineNextEndSubSubTTxSendString'Send string >TTxSVar< bytewiseDimiiAsByteForii=1ToTTxSVar(0)'first byte in array is the string-lengthTTxSendByte(TTxSVar(ii))'send via subroutineNextEndSubSubTTxSendByte(InTTxByte)'serial out one byte (8 databit, no paritybit, 1 stopbit)'cli ;disable interruptspushR24;saveregistercontenttostackpushR25;pushR26;ldsR24,TTxByte;loaddata-bytetoregisterldiR25,10;loadnumberofbitstoregister(1start+8data+1stop)comR24;invertbitsandsetcarryTTxLoop:;9cycleloop+delayperbytebrccTTx1;jumptoTTx1ifCarryFlag=0SetTTX_PINOff;setpinLOWifCarryFlag=1(translatedbyGCBtoASM:cbi...)TTx1:brcsTTxDone;jumptoTTxDoneifCarryFlag=1SetTTX_PINOn;setpinHIGHifCarryFlag=0(translatedbyGCBtoASM:sbi...)TTxDone:ldiR26,TTX_DELAY;loaddelaycountertoregisterTTxDelay:;delay-loop=(3cycle*delaycounter)-1decR26;decrementdelaycounterbrneTTxDelay;looptoTTxDelayuntildelaycounter=0lsrR24;shiftnextbittoCarryFlagdecR25;decrementbitcounterbrneTTxLoop;jumptoTTxLoopandtransmitnextbituntilbitcounter=0popR26;restoreregistercontentfromstackpopR25;popR24;'sei ;enable interruptsEndSub
Merry christmas to all
Last edit: Frank Steinberg 2016-12-25
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi
I ported the Tiny-Software-Transmitter to PIC MC. The attached sample realizes a software UART (in fact ist an 'AT', because ist neither Universal nor a Receiver but an RS232 Asynchron Transmitter).
Tiny means, there are only 24 words (!) added to the hex to be able to send a byte.
- 13 lines of assembler code
- no timers are used
- no other hardware modules are used
- no interrupt is used
- 9600 - 128000 baud are possible at 16 Mhz
- 8N1 format only
- Tx-Pin is user configurable
Because I'm new to ASM I need some help. The code works for me on a PIC12f1501 an a PIC18f13k50. But it lacks on 'bank selection' and 'page selection' in the asm code. Can that be a problem, if the code would be inserted in another (more complex) program? How can this be fixed? If I try to add 'banksel' in the code, GCB generates an error - why?
Frank
The sample:
Last edit: Frank Steinberg 2016-12-22
Good code, Frank. Really nice.
Do not struggle with banksel - simply mix ASM and Great Cow BASIC.
You assign a variable. Use GCB assignment. GCB will sort out pages andg banks.
You need a goto. Use GCB goto. GCB will sort the correct addressing across all the chips.
Thank you for the answer.
I wonder if is's really ruled out, that GCB adds a 'banksel'. In this case the asm code won' t work anymore, because the jumps are only to the next line. I could handle that by adding goto-jumps to labels !? But that is extra code an slows it down (slightly).
How can I force that; it's the same command?
Frank
@Frank. Which piece of code are we trying to optimise? i can try here over the Holiday period.
It is the Holiday period. :-)
You lucky one!
I am filled with family and Christmas obligations until the 26th.
Ideas for the next steps:
That's my last code, so the first step is mostly done (hopefully)
... and for AVR:
Merry christmas to all
Last edit: Frank Steinberg 2016-12-25