Menu

Tiny AVR-Asm software serial transmitter and questions about it

2016-12-18
2016-12-24
  • Frank Steinberg

    Frank Steinberg - 2016-12-18

    Hi all!

    First of all: Thanks to Evan, Hugh and the others for the 0.96.00 release!
    I took this as an opportunity to try out a new idea. I have a (unfinished) project for an atTiny85 or digispark, where the flash reached the limit. The program istself fits in the flash, but if i add software serial to do some debugging output, it extends the flash memory. So I searched the internet for a solution and found that:
    http://nerdralph.blogspot.de/2013/12/writing-avr-assembler-code-with-arduino.html

    First i tried to understand the code (90% done, see my comments) an then to implement in a GCB-Program. This is the result:

    '''A demonstration program for GCB  - AVR only -
    '''----------------------------------------------------------------------------
    '''This program is a super slim software serial transmitter (322 bytes flash)
    ''' realized with 15-line asm code, AVR-Assembler so it's AVR only
    ''' tested up to 256000 baud on an 16 or 16.5 Mhz attiny85 (digispark)
    '''The pulse logic ist designed for TTL-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:
    ''' nerdralph.blogspot.de/2013/12/writing-avr-assembler-code-with-arduino.html
    '''@licence GPL
    '''@version 1.0
    '''@date    17.12.2016
    '''****************************************************************************
    
    ; ----- Configuration
    #chip tiny85, 16.5       'intended for digispark board
    #option Explicit
    
    ; ----- Define Hardware settings
    ;       Config Software Tx:
    ;       [ calculate delay-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.1  'use this port to send serial data
    Dir TTX_PIN Out          '... and make it output
    Set TTX_PIN On           'set HIGH to make the first startbit recognizable
    
    ; ----- Variables
    Dim TTxText As String * 30  'create a string
    Dim ii, xx As Byte
    xx = 48                     'begin with a 0
    
    ; ----- Main body of program commences here.
    
     Do Forever
    
      TTxSendByte(13)   'new line in Terminal
      TTxSendByte(10)   '
      TTxText = "TinyTx Software Transmitter: "
      TTxSendString     'send the text
      TTxSendByte(xx)   'send an alternating byte
      'TTxText = Str(xx) 'this adds 564 byte code!
      'TTxSendString     'this adds 2 byte code
      xx += 1           'alternate byte
      Wait 1 s          'time to enjoy the result
    
     Loop
    
    Sub TTxSendString  'Send TTxText bytewise
    
      For ii = 1 To TTxText(0)   'first byte in array is the string-length
       TTxSendByte(TTxText(ii))  'send via subroutine
      Next
    
    End Sub
    
    Sub TTxSendByte (In TTxByte)  'serial out one byte (8 databit, no paritybit, 1 stopbit)
    
      cli                   ;disable interrupts
      lds R24, TTxByte      ;load data-byte to register
      ldi R25, 10           ;load number of bits to register (1 start + 8 data + 1 stop)
      com R24               ;invert bits and set carry
      TTxLoop:
        ;9 cycle loop + delay per byte
        brcc TTx1           ;jump to TTx1 if CarryFlag=0
        Set TTX_PIN Off     ;set pin LOW if CarryFlag=1 (translated by GCB to ASM: cbi ...)
      TTx1:
        brcs TTxDone        ;jump to TTxDone if CarryFlag=1
        Set TTX_PIN On      ;set pin HIGH if CarryFlag=0 (translated by GCB to ASM: sbi ...)
      TTxDone:
        ldi R26, TTX_DELAY  ;load delaycounter to register
      TTxDelay:
        ;delay-loop = (3 cycle * delaycounter) -1
        dec R26             ;decrement delaycounter
        brne TTxDelay       ;loop to TTxDelay until delaycounter=0
        lsr R24             ;shift next bit to CarryFlag
        dec R25             ;decrement bitcounter
        brne TTxLoop        ;jump to TTxLoop and transmit next bit until bitcounter=0
      sei                   ;enable interrupts
    
    End Sub
    

    It works well up to 256000 baud but there are still some questions for me:
    1.
    Is it ok to use the registers that way or can this interfere other parts of the program?
    2.
    Are there smarter ways to pick registers? The ones I use, are "fallen from sky".
    3.
    I tried to use GCBs IntOn/IntOff but it produces no asm code - bug or feature?

    Regards
    Frank

    TinyTx on Terminl

     
  • Frank Steinberg

    Frank Steinberg - 2016-12-24

    Nobody?

    Let me ask more specifically:
    Do I need to save the used registers and 'pop' them back afterwards?

    Frank

     
  • Anobium

    Anobium - 2016-12-24

    It is the Holiday period. :-)

    1. Is it ok to use the registers that way or can this interfere other parts of the program? Should be ok.
    2. Are there smarter ways to pick registers? Look in the .dat file specific for the chip, then, cross reference to the datasheet.
    3. Tried to use GCBs IntOn/IntOff but it produces no asm code. GCB handles the IntOn/IntOff for you. If you do not set an interrupt handler using 'On Interrupt' then these commands would not generate code. This is the expected behaviour.
     

Log in to post a comment.