;; ;; mur.sat ;; ;; Somewhen in the year 2011, mur.at will have a nano satellite launched ;; into a low earth orbit (310 km above the surface of our planet). The ;; satellite itself is a TubeSat personal satellite kit, developed and ;; launched by interorbital systems. mur.sat is a joint venture of mur.at, ;; ESC im Labor and realraum. ;; ;; Please visit the project hompage at sat.mur.at for further information. ;; ;; ;; Copyright (C) 2011 Christian Pointner ;; ;; This file is part of mur.sat. ;; ;; mur.sat is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; any later version. ;; ;; mur.sat is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with mur.sat. If not, see . ;; ;; ------------------------------------- ;; PREAMBLE LIST p=12F635 include "p12f635.inc" __config _WUREN_OFF & _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_OFF & _WDT_ON & _INTRC_OSC_NOCLKOUT ;; ------------------------------------- ;; DEFINES ;; constants DOT EQU .256 - .21 ; .29 DASH EQU .256 - .63 ; .87 ESPACE EQU DOT CSPACE EQU DASH WSPACE EQU .256 - .147 ; .203 ENABLE_TIME EQU DOT BCONINT_DEF EQU .42 START_CHAR EQU 'A' ACK_CHAR EQU 'A' OSC_LOW EQU b'00000000' OSC_HIGH EQU b'01100000' ;; I/O Pins CWENABLE EQU GP0 CWOUT EQU GP1 SCLK EQU GP2 SDAT EQU GP4 ;; variables ;; page 0 only ELEMENT EQU H'0040' ELECNT EQU H'0041' CHAR EQU H'0042' PARITY EQU H'0043' CHARCNT EQU H'0044' PENTLE0 EQU H'0045' PENTLE1 EQU H'0046' PENTLECNT EQU H'0047' ACK_DATA EQU H'0048' RX_CNT EQU H'004E' RX_BYTE EQU H'004F' BUF EQU H'0050' ;; all pages STATE EQU H'0078' BEACON_INT EQU H'0079' NVSTATE EQU H'007A' BEACONCNTH EQU H'007B' BEACONCNTL EQU H'007C' SECCNT EQU H'007D' W_TEMP EQU H'007E' STATUS_TEMP EQU H'007F' ;; bits NVSTATE safe EQU .0 ;; bits STATE rx EQU .0 ;; ------------------------------------- ;; Reset Vector org .0 goto init ;; ------------------------------------- ;; Interrupt Vector org .4 ;; save context movwf W_TEMP swapf STATUS,W movwf STATUS_TEMP btfss INTCON,INTF goto tmr1_int ext_int bcf INTCON,INTF btfsc STATE,rx goto interrupt_end bsf STATUS,RP0 movlw OSC_HIGH movwf OSCCON bcf STATUS,RP0 movlw .8 movwf RX_CNT ext_int_clk_high btfss GPIO,SCLK goto ext_int_clk_high btfss GPIO,SDAT bcf RX_BYTE,0 btfsc GPIO,SDAT bsf RX_BYTE,0 decfsz RX_CNT,f goto ext_int_rx_next bsf STATE,rx bsf STATUS,RP0 movlw OSC_LOW movwf OSCCON goto interrupt_end ext_int_rx_next rlf RX_BYTE,f goto ext_int_clk_high tmr1_int bcf STATUS,RP0 bcf PIR1,TMR1IF bcf T1CON,TMR1ON clrf TMR1L movlw b'10000000' movwf TMR1H btfsc NVSTATE,safe ; safe mode -> disable scheduler goto interrupt_end bsf T1CON,TMR1ON movf SECCNT,f btfss STATUS,Z decf SECCNT,f goto interrupt_end interrupt_end ;; restore context swapf STATUS_TEMP,W movwf STATUS swapf W_TEMP,F swapf W_TEMP,W retfie ;; ------------------------------------- ;; TABLES ;; Morse Codes: 0=dot, 1=dash getcw addwf PCL,f nop retlw b'00010000' ; ! retlw b'01001000' ; " retlw b'00000000' ; # retlw b'00010010' ; $ retlw b'00000000' ; % retlw b'01000000' ; & retlw b'01111000' ; ' retlw b'10110000' ; ( retlw b'10110100' ; ) retlw b'00000000' ; * retlw b'01010000' ; + retlw b'11001100' ; , retlw b'10000100' ; - retlw b'01010100' ; . retlw b'10010000' ; / retlw b'11111000' ; 0 retlw b'01111000' ; 1 retlw b'00111000' ; 2 retlw b'00011000' ; 3 retlw b'00001000' ; 4 retlw b'00000000' ; 5 retlw b'10000000' ; 6 retlw b'11000000' ; 7 retlw b'11100000' ; 8 retlw b'11110000' ; 9 retlw b'11100000' ; : retlw b'10101000' ; ; retlw b'00010100' ; < retlw b'10001000' ; = retlw b'10001010' ; > retlw b'00110000' ; ? retlw b'01000000' ; @ retlw b'01000000' ; A retlw b'10000000' ; B retlw b'10100000' ; C retlw b'10000000' ; D retlw b'00000000' ; E retlw b'00100000' ; F retlw b'11000000' ; G retlw b'00000000' ; H retlw b'00000000' ; I retlw b'01110000' ; J retlw b'10100000' ; K retlw b'01000000' ; L retlw b'11000000' ; M retlw b'10000000' ; N retlw b'11100000' ; O retlw b'01100000' ; P retlw b'11010000' ; Q retlw b'01000000' ; R retlw b'00000000' ; S retlw b'10000000' ; T retlw b'00100000' ; U retlw b'00010000' ; V retlw b'01100000' ; W retlw b'10010000' ; X retlw b'10110000' ; Y retlw b'11000000' ; Z ;; Morse Code Length getcwlen addwf PCL,f nop retlw .5 ; ! retlw .6 ; " retlw .0 ; # retlw .7 ; $ retlw .0 ; % retlw .5 ; & retlw .6 ; ' retlw .5 ; ( retlw .6 ; ) retlw .0 ; * retlw .5 ; + retlw .6 ; , retlw .6 ; - retlw .6 ; . retlw .5 ; / retlw .5 ; 0 retlw .5 ; 1 retlw .5 ; 2 retlw .5 ; 3 retlw .5 ; 4 retlw .5 ; 5 retlw .5 ; 6 retlw .5 ; 7 retlw .5 ; 8 retlw .5 ; 9 retlw .6 ; : retlw .6 ; ; retlw .6 ; < retlw .5 ; = retlw .7 ; > retlw .6 ; ? retlw .6 ; @ retlw .2 ; A retlw .4 ; B retlw .4 ; C retlw .3 ; D retlw .1 ; E retlw .4 ; F retlw .3 ; G retlw .4 ; H retlw .2 ; I retlw .4 ; J retlw .3 ; K retlw .4 ; L retlw .2 ; M retlw .2 ; N retlw .3 ; O retlw .4 ; P retlw .4 ; Q retlw .3 ; R retlw .3 ; S retlw .1 ; T retlw .3 ; U retlw .4 ; V retlw .3 ; W retlw .4 ; X retlw .4 ; Y retlw .4 ; Z ;; Base32 Code base32 addwf PCL,f retlw 'A' retlw 'B' retlw 'C' retlw 'D' retlw 'E' retlw 'F' retlw 'G' retlw 'H' retlw 'I' retlw 'J' retlw 'K' retlw 'L' retlw 'M' retlw 'N' retlw 'O' retlw 'P' retlw 'Q' retlw 'R' retlw 'S' retlw 'T' retlw 'U' retlw 'V' retlw 'W' retlw 'X' retlw 'Y' retlw 'Z' retlw '2' retlw '3' retlw '4' retlw '5' retlw '6' retlw '7' ;; fixed strings callsign addwf PCL,f nop retlw 'R' retlw 'U' retlw 'M' retlw '6' retlw 'E' retlw 'O' ;; ------------------------------------- ;; INIT init ;; bank 1 bsf STATUS,RP0 bcf STATUS,RP1 movlw b'11000011' movwf OPTION_REG movlw b'11111100' movwf TRISIO movlw b'00000001' movwf PIE1 movlw OSC_LOW movwf OSCCON bcf STATUS,RP0 ;; bank 0 movlw b'00010110' movwf WDTCON clrf TMR1L movlw b'10000000' movwf TMR1H movlw b'00000110' movwf T1CON movlw b'01010000' movwf INTCON movlw b'00000111' movwf CMCON0 bcf GPIO,CWOUT bcf GPIO,CWENABLE clrf STATE clrf NVSTATE ; TODO: read State from EEPROM movlw .42 movwf BEACONCNTL ; TODO: read Beaconcnt from EEPROM movlw .23 movwf BEACONCNTH movlw BCONINT_DEF ; TODO: read Beacon Interval from EEPROM movwf BEACON_INT movf BEACON_INT,w movwf SECCNT btfss NVSTATE,safe ; safe mode -> disable scheduler bsf T1CON,TMR1ON bsf INTCON,GIE goto main ;; ------------------------------------- ;; SUBROUTINES dottime movwf TMR0 bcf INTCON,T0IF dot_inner btfss INTCON,T0IF goto dot_inner clrwdt return ;; ------------------------------------- send_char movwf CHAR movlw 'Z' + 1 subwf CHAR,w btfsc STATUS,C return movlw ' ' subwf CHAR,f btfss STATUS,C return btfsc STATUS,Z return movf CHAR,w call getcw movwf ELEMENT movf CHAR,w call getcwlen movwf ELECNT movf ELECNT,f btfsc STATUS,Z return xorwf PARITY,f char_next_element bsf GPIO,CWOUT btfss ELEMENT,7 movlw DOT btfsc ELEMENT,7 movlw DASH call dottime bcf GPIO,CWOUT rlf ELEMENT,f decfsz ELECNT,f goto char_espace return char_espace movlw ESPACE call dottime goto char_next_element ;; ------------------------------------- send_callsign movlw .6 movwf CHARCNT callsign_next_char call callsign call send_char decfsz CHARCNT,f goto callsign_cspace return callsign_cspace movlw CSPACE call dottime movf CHARCNT,w goto callsign_next_char ;; ------------------------------------- send_base32 movwf PENTLECNT case0 rrf INDF,w movwf PENTLE0 rrf PENTLE0,f rrf PENTLE0,w andlw b'00011111' call base32 call send_char decfsz PENTLECNT,f goto case1 return case1 movlw CSPACE call dottime rlf INDF,w movwf PENTLE0 rlf PENTLE0,w andlw b'00011100' movwf PENTLE0 incf FSR,f swapf INDF,w movwf PENTLE1 rrf PENTLE1,f rrf PENTLE1,w andlw b'00000011' iorwf PENTLE0,w call base32 call send_char decfsz PENTLECNT,f goto case2 return case2 movlw CSPACE call dottime rrf INDF,w andlw b'00011111' call base32 call send_char decfsz PENTLECNT,f goto case3 return case3 movlw CSPACE call dottime swapf INDF,w andlw b'00010000' movwf PENTLE0 incf FSR,f swapf INDF,w andlw b'00001111' iorwf PENTLE0,w call base32 call send_char decfsz PENTLECNT,f goto case4 return case4 movlw CSPACE call dottime rlf INDF,w andlw b'00011110' movwf PENTLE0 incf FSR,f btfsc INDF,7 bsf PENTLE0,0 movf PENTLE0,w call base32 call send_char decfsz PENTLECNT,f goto case5 return case5 movlw CSPACE call dottime rrf INDF,w movwf PENTLE0 rrf PENTLE0,w andlw b'00011111' call base32 call send_char decfsz PENTLECNT,f goto case6 return case6 movlw CSPACE call dottime swapf INDF,w movwf PENTLE0 rrf PENTLE0,w andlw b'00011000' movwf PENTLE0 incf FSR,f swapf INDF,w movwf PENTLE1 rrf PENTLE1,w andlw b'00000111' iorwf PENTLE0,w call base32 call send_char decfsz PENTLECNT,f goto case7 return case7 movlw CSPACE call dottime movf INDF,w andlw b'00011111' call base32 call send_char decfsz PENTLECNT,f goto caseend return caseend movlw CSPACE call dottime incf FSR,f goto case0 ;; ------------------------------------- send_cnt rlf BEACONCNTL,w movwf BUF+1 rlf BEACONCNTH,w movwf BUF movlw BUF movwf FSR movlw .3 call send_base32 return ;; ------------------------------------- send_parity movf PARITY,w btfsc PARITY,5 xorlw b'00000001' andlw b'00011111' call base32 call send_char movlw WSPACE call dottime return ;; ------------------------------------- send_beacon bsf GPIO,CWENABLE movlw ENABLE_TIME call dottime clrf PARITY movlw START_CHAR call send_char movlw WSPACE call dottime call send_callsign movlw WSPACE call dottime call send_cnt movlw WSPACE call dottime call send_parity incfsz BEACONCNTL,f goto beacon_end incf BEACONCNTH,f ;; TODO write new cnt value to EEPROM beacon_end bcf GPIO,CWENABLE return ;; ------------------------------------- send_ack movwf ACK_DATA bsf GPIO,CWENABLE movlw ENABLE_TIME call dottime clrf PARITY movlw ACK_CHAR call send_char movlw CSPACE call dottime movf ACK_DATA,w call send_char movlw CSPACE call dottime call send_parity bcf GPIO,CWENABLE return ;; ------------------------------------- ;; MAINLOOP main ;; this gets called after reset and whenever a wakeup occured ;; (after TMR1 overrun or interrupt on GP2) movf SECCNT,f btfsc STATUS,Z goto seccnt_zero btfsc STATE,rx goto byte_received goto powerdown ;; this gets called every BEACON_INT seconds seccnt_zero movf BEACON_INT,w movwf SECCNT call send_beacon goto powerdown ;; this gets called whenver a byte was received from ihu byte_received movf RX_BYTE,w bcf STATE,rx call send_ack powerdown sleep nop goto main ;; ------------------------------------- ;; END end