Results 1 to 4 of 4

Thread: RTTY Decoder - Pt1

  1. #1

    Default RTTY Decoder - Pt1

    The RTTY decoder is designed to display radio teleprinter signals on a 16 character by 2
    line LCD module based on the Hitachi 44780 controller. I used a BATG Multyterm terminal
    unit for the tone decoder, although any of the many TU designs found on the Internet could
    be used. With the advent of PC based sound card input software such as MixW these are otherwise redundant.

    Initial testing was performed using the soundcard output from MixW PC software. On air
    testing was mainly on the 20m amateur band where the center of activity is 14.080MHz.
    Solid copy was also received from the German weather service DDK9 on 10,100.8 kHz.

    The code consists of 4 modules, an interrupt driven input module, circular input buffer,
    lookup table and lcd driver.

    Hardware is built on veroboard with plug and socket to the lcd and to a small daughter
    board with the RS232 to 5V logic convertor. This allows for the addition of a dedicated
    tone decoder (proberbly using an NE 567 pll) later....

    I used a 20X2 because I had one. Some of the commands are not available on M2 parts but
    little recoding should be necessary if you wanted to try. I run at 16MHz because a)it was
    fast enough b)because I couldn't get the LCD to work faster (yes I did change the timings).

    This is my first attempt at picaxe coding so constructive critisism is welcomed. Let me
    know if you build one.

    Code has to be split to fit post. Join pt1 and pt2 together to complete program.

    Code:
    #picaxe 20x2
    
    ; RTTY Decoder (45.5/50 baud)
    ;
    ;Baudot code has 5 data bits, 1 start bit and at least 1.5 stop bits.
    ;Start bit is 0
    ;Stop bits are 1
    ;
    
    ;Look for idle 
    ;wait for start bit
    ;30ms later look for data 1
    ;clock data into a byte variable every 20ms
    ;look up the ascii
    ;add to circular buffer
    ;start again
    
    ;Here's the ITA2 code
    
    ;	LTR 	FIGS	  lsb	
    
    ;0 	NUL 		00 00000 NULL, Nothing (blank tape) 
    ;1 	E 	3 	01 10000   
    ;2 	LF 		02 01000 Line Feed (new line - translate as space ) 
    ;3 	A 	- 	03 11000   
    ;4 	SP 		04 00100 Space 
    ;5 	S 	' 	05 10100   
    ;6 	I 	8 	06 01100   
    ;7 	U 	7 	07 11100   
    ;8 	CR 		08 00010 Cariage Return 
    ;9 	D 	ENC 	09 10010 Enquiry (Who are you?, WRU) 
    ;10 	R 	4 	0A 01010   
    ;11 	J 	BEL 	0B 11010 BELL (ring bell at the other end) 
    ;12 	N 	, 	0C 00110   
    ;13 	F 	! 	0D 10110   
    ;14 	C 	: 	0E 01110   
    ;15 	K 	( 	0F 11110   
    ;16 	T 	5 	10 00001   
    ;17 	Z 	+ 	11 10001   
    ;18 	L 	) 	12 01001   
    ;19 	W 	2 	13 11001   
    ;20 	H 	$ 	14 00101 Currency symbol (can also be £) 
    ;21 	Y 	6 	15 10101   
    ;22 	P 	0 	16 01101   
    ;23 	Q 	1 	17 11101   
    ;24 	O 	9 	18 00011   
    ;25 	B 	? 	19 10011   
    ;26 	G 	& 	1A 01011   
    ;27 	FIGS 		1B 11011 Figures (Shift on) 
    ;28 	M 	. 	1C 00111   
    ;29 	X 	/ 	1D 10111   
    ;30 	V 	; 	1E 01111   
    ;31 	LTRS 		1F 11111 Letters (Shift off) 
    ;-----------------------------------------------------------------------------
    
    SYMBOL offset = b40
    ;SYMBOL  letters_start = b40	;pointer to the start of letters lookup table
    ;SYMBOL  figures_start = b41	;pointer to the start of figures lookup table
    SYMBOL  codein = c.1		;Define pin for RTTY input
    SYMBOL  testpin = c.0		;Define a testpin for output
    
    SYMBOL  bytee = b12		;This is the character or command to be sent
    					;to the display
    
    symbol rttyin = pinsC		;the input port
    symbol mask = b42			;bit mask for input
    symbol rttyout = b43		;byte containing the ITA2 code of the i/p
    
    
    ;------------------------------------------------------------
    ;LCD Routine declarations
    ;------------------------------------------------------------
    SYMBOL  getting   = b11		;This is a pointer to the EEPROM
    SYMBOL  rsbit     = b13
    SYMBOL  presbptr  = b44
    
    SYMBOL char0 = b20		;The line buffer....b20 to b35
    SYMBOL char1 = b21
    SYMBOL char2 = b22		;Symbols not used in this version, 
    SYMBOL char3 = b23		;variables are though
    SYMBOL char4 = b24
    SYMBOL char5 = b25
    SYMBOL char6 = b26
    SYMBOL char7 = b27
    SYMBOL char8 = b28
    SYMBOL char9 = b29
    SYMBOL char10 = b30
    SYMBOL char11 = b31
    SYMBOL char12 = b32
    SYMBOL char13 = b33
    SYMBOL char14 = b34
    SYMBOL char15 = b35
    
    SYMBOL charcount = b36		; Cursor position on current line
    SYMBOL preserve_char = b37	; Preserve the current character while we move lines
    
    SYMBOL  RSCMDmask = %00000000 ; Select Command register
    SYMBOL  RSDATmask = %00000100 ; Select Data register
    
    SYMBOL  RS        = B.2         ; 0 = Command   1 = Data
    SYMBOL  E         = B.3         ; 0 = Idle      1 = Active
    SYMBOL  DB4       = B.4         ; LCD Data Line 4
    SYMBOL  DB5       = B.5         ; LCD Data Line 5
    SYMBOL  DB6       = B.6         ; LCD Data Line 6
    SYMBOL  DB7       = B.7         ; LCD Data Line 7
    ;--------------------------------------------------------------------
    ;Circular buffer defines
    SYMBOL cbinptr = b46		;circular buffer input pointer
    SYMBOL cboutpptr = b47		;circular buffer output pointer
    SYMBOL cbstart = $10		;circular buffer start location in scratchpad
    SYMBOL cbend = $17		;circular buffer end location in scratchpad
    SYMBOL ascii_in = b48		;ascii character coresponding to rttyout
    ptr = cbstart			;set scratchpad pointer to start of buffer
    ;--------------------------------------------------------------------
    
    ;Baudot to Acsii Lookup table
    
    EEPROM $40, ($00,"E",$20,"A",$20,"SIU",$00,"DRJNFCKTZLWHYPQOBG",$00,"MXV",$00)			;letters
    EEPROM $60, ($00,"3",$20,"-",$20,"'87",$00,$00,"4",$00,",!:(5+)2$6019?&",$00,"./;",$22,$00)	;figures
    
    ;---------------------------------------------------------------------
    ;Welcome message
    EEPROM 6,("G8XUL RTTY      DECODER     ") ;last location is 33
    ;---------------------------------------------------------------------
    setfreq m16 			; setfreq to 16MHz
    ;Setup pins:
    let dirsC = %00000001		;Set port C for the code input
    let dirsB = %11111111		;Set port B to all outputs for LCD
    let adcsetup = 0			;Disable all ADCs
    let offset = $40			;lookup table start
    ;---------------------------------------------------------------------
    
    let charcount = 0			;first position on the LCD line
    
    ;-----------------------------------------------------------------------------
    GOSUB InitialiseLcd		;Setup the display 
    
    
    
    bytee	= $C0 			;Cursor to start of line one
    bptr  = 20    			;set variable pointer to b20 (start of line buffer)
    presbptr = 20
    gosub SendCmdByte
    
    FOR getting = 6 TO 32		;write the welcome message
        READ getting,bytee
        ;sertxd (bytee)
        GOSUB charprint
        pause 100
    NEXT
    
    wait 5 
    
     
    SETINT %00000000,%00000010,C		;Interupt when we see a start bit
    
    ;-------------------------------------------------------------------------
    ; Use scratchpad as input buffer. 8 bytes should be enough.
    ;-------------------------------------------------------------------------
    
    main:
    gosub readbuffer				;Loop untill interupted by a start sequence
    goto main
    
    ;------------------------------------------------------------------------
    interrupt:
    	
    gosub getchar				;get the character and display it
    setint %00000000,%00000010,C		;get ready for the next character
    return
    
    ;------------------------------------------------------------------------
    getchar:
    pauseus 6000
    mask = %00000001				;put the mask to bit 1
    rttyout = 0
    for b45 = 1 to 5				;do it one for each bit
    IF rttyin BIT 1 SET THEN		
    rttyout=rttyout or mask 		;set the bit if the input is high
    endif
    mask = mask * 2	 			;move to the next bit in the mask
    pauseus 4000    				;wait for the next bit	
    next
    
    select case rttyout
    case $1F					;if letters received point at letters in lookup table
    offset = $40 :return
    case $1B 					;if figures received point at figures in lookup table
    offset = $60 :return
    endselect
    
    ;look it up!
    rttyout = offset + rttyout		;point to the ascii character
    
    READ rttyout,ascii_in			;do the lookup
    
    
    if ascii_in != 0 then 			;if it's null, do nothing
    ;gosub charprint
    put cbinptr,ascii_in			;put the character in the buffer 
    cbinptr = cbinptr + 1			;and increment the pointer
    cbinptr = cbinptr AND %00000111	;and roll over if = 8
    endif
    
    
    return
    
    ;----------------------------------------------------------------
    ;read the buffer and send to the display
    readbuffer:
    b50 = cbinptr - cboutpptr		;test for buffer empty
    if b50 = 0 then return			;no character to process
    endif
    GET cboutpptr, bytee			;get the next char to print from the buffer
    gosub charprint				;and put to the LCD
    cboutpptr = cboutpptr + 1		;increment the pointer
    cboutpptr = cboutpptr AND %00000111	;and roll over if = 8
    return
    ;----------------------------------------------------------------
    ;
    ;Display routines follow
    ;
    ;----------------------------------------------------------------
    rtty.jpg
    Last edited by gpodave; 21-04-2012 at 20:04.

  2. #2

    Default RTTY Decoder - Pt2

    The rest of the code...

    Code:
    ;----------------------------------------------------------------
    ;
    ;Display routines follow
    ;
    ;----------------------------------------------------------------
    
    'Print a charactor to the LCD
    'If the first line is full,
    '   clear the display
    '   move the first line to the second line
    '   set the cursor to the first position on the first line
    '   reset the line buffer
    '   print the character
    'Otherwise,
    '   print the character where it is and add it to the line buffer
    
    'Uses Hippy's LCD routine
    
    ;----------------------------------------------------------------------
    
    
    charprint:				;Prints the character in bytee to the LCD
    bptr = presbptr			;bptr needs to be preverved between calls
    if charcount > 15 then		;Is the first line full?
    gosub moveline			;If it is move it to line 2
    endif
    gosub SendDataByte		;Send the character to the display
    @bptrinc = bytee			;and mirror it in the line buffer
    inc charcount			;move the pointer to the next position in the line buffer
    presbptr = bptr			;save current bptr			
    return
    
    
    
    moveline: 				;scroll display
    preserve_char = bytee		;look after the current character
    bptr = 20				;go to the start of the line buffer		;
    bytee = $01				;%0000 0001  Clear display
    gosub SendCmdByte
    bytee = $80				;%1000 0000  Put cursor at start of second line
    gosub SendCmdByte
    
    for charcount = 0 to 15		;Write the line buffer to the second line
    bytee = @bptrinc
    gosub SendDataByte
    next
    
    bptr = 20				;Back to the start of the buffer
    bytee	= $C0 			;Cursor back to start of line one
    gosub SendCmdByte				
    bytee = preserve_char		;restore the last character
    charcount = 0			;reset the character counter
    return				;and get out of here
    
    '---------------------------------------------------------------
        InitialiseLcd:
    
            FOR getting = 0 TO 5
              READ getting,bytee
              GOSUB SendInitCmdByte
            NEXT
    
            ' Nibble commands - To initialise 4-bit mode
    
            EEPROM 0,( $33 )    ; %0011---- %0011----   8-bit / 8-bit
            EEPROM 1,( $32 )    ; %0011---- %0010----   8-bit / 4-bit
    
            ' Byte commands - To configure the LCD
    
            EEPROM 2,( $28 )    ; %00101000 %001LNF00   Display Format
            EEPROM 3,( $0C )    ; %00001100 %00001DCB   Display On
            EEPROM 4,( $06 )    ; %00000110 %000001IS   Cursor Move
    
                                ; L : 0 = 4-bit Mode    1 = 8-bit Mode
                                ; N : 0 = 1 Line        1 = 2 Lines
                                ; F : 0 = 5x7 Pixels    1 = N/A
                                ; D : 0 = Display Off   1 = Display On
                                ; C : 0 = Cursor Off    1 = Cursor On
                                ; B : 0 = Cursor Steady 1 = Cursor Flash
                                ; I : 0 = Dec Cursor    1 = Inc Cursor
                                ; S : 0 = Cursor Move   1 = Display Shift
    
            EEPROM 5,( $01 )    ; Clear Screen
    
            RETURN
    
        '-----------------------
        SendInitCmdByte:
    
            PAUSE 30                       	;Delay 15mS at 16MHz
    
        SendCmdByte:
    
            PEEK $30,rsbit                 	;Recover Out0 and Out1
            rsbit = rsbit & %11            	;Send to Command register
            GOTO SendCmdOrDataByte
    
        SendDataByte:
    
            PEEK $30,rsbit                  	;Recover Out0 and Out1
            rsbit = rsbit & %11 | RSDATmask 	;Send to Data register
    
        SendCmdOrDataByte:
    
            pinsB = bytee & %11110000 | rsbit ; Put MSB out first
            PULSOUT E,4                       ; Give a 10uS pulse on E
            pinsB = bytee * %00010000 | rsbit ; Put LSB out second
            PULSOUT E,4                       ; Give a 10uS pulse on E
    
            RETURN

  3. #3
    Moderator
    Join Date
    Mar 2008
    Location
    Western Australia
    Posts
    11,069

    Default

    @gpo dave,

    welcome to the PICAXE forum.

    I have moved your two related posts together under one so that they stay together otherwise as time passes they may become separated and possibly harder for some to trace both parts.

    Well done on your project and while I have no immediate use for such a RTTY project, thank you for posting as a source of suitable code for others in the future.
    Good to see comments included.

    If any feedback is to be given, it can be worth indenting program code within the various subroutines, looping structures plus IF...THEN and SELECT...CASE segments so the structures are easy to see.
    Last edited by westaust55; 08-11-2012 at 13:37.
    westaust55

    Hey Hamlet, 2B OR NOT 2B = $FF

  4. #4

    Default

    Thanks west, You'll see the post was a little late at night and I couldn't seem to post code in the reply to post. I guess I should just have added code tags myself - hey ho.

    Thanks also for the coding advice. I'll take that on board for next time. Hopefully others will find some of the modules useful for other application.

    Cheers,

    Dave

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •