;; ;; 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_DEF EQU .256 - .21 ; .29 DASH_DEF EQU .256 - .63 ; .87 WSPACE_DEF EQU .256 - .147 ; .203 TUNE_DEF EQU DOT_DEF BCONINT_DEF EQU .42 START_CHAR EQU 'N' 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 CLK_1HZ EQU GP5 ;; 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' TMP1 EQU H'0049' TMP2 EQU H'004A' RX_STATE EQU H'004B' RX_FSR_TMP EQU H'004C' RX_CSUM EQU H'004D' RX_BIT_CNT EQU H'004E' RX_BYTE_CNT EQU H'004F' RX_CMD EQU H'0050' RX_D_START EQU H'0051' RX_D_END EQU H'005F' ;; all pages BEACON_INT EQU H'0070' DOT EQU H'0071' ESPACE EQU DOT DASH EQU H'0072' CSPACE EQU DASH WSPACE EQU H'0073' TUNE EQU H'0074' 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 RX_STATE complete EQU .7 ;; ------------------------------------- ;; 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 clk_1hz_int ext_int bcf INTCON,INTF btfsc RX_STATE,complete goto interrupt_end bsf STATUS,RP0 movlw OSC_HIGH movwf OSCCON ;; we are on high OSC now bcf STATUS,RP0 clrf RX_CSUM movf FSR,w movwf RX_FSR_TMP movlw RX_CMD movwf FSR call rx_byte movlw b'00001111' andwf RX_CMD,w movwf RX_BYTE_CNT movwf RX_STATE btfsc STATUS,Z goto ext_int_send_csum ext_int_next call rx_byte decfsz RX_BYTE_CNT,f goto ext_int_next ext_int_send_csum call rx_send_csum movf RX_FSR_TMP,w movwf FSR swapf RX_CMD,w andlw b'00001111' movwf RX_CMD bsf RX_STATE,complete bsf STATUS,RP0 movlw OSC_LOW movwf OSCCON ;; back on low OSC goto interrupt_end clk_1hz_int bcf STATUS,RP0 btfss GPIO,CLK_1HZ goto clk_1hz_int_low bcf INTCON,RAIF goto interrupt_end clk_1hz_int_low bcf INTCON,RAIF 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'01000011' movwf OPTION_REG movlw b'11111100' movwf TRISIO movlw OSC_LOW movwf OSCCON movlw b'00100000' movwf IOCA bcf STATUS,RP0 ;; bank 0 movlw b'00010110' movwf WDTCON movlw b'00011000' movwf INTCON movlw b'00000111' movwf CMCON0 bcf GPIO,CWOUT bcf GPIO,CWENABLE clrf RX_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 movlw DOT_DEF ; TODO: read cw timings from EEPROM movwf DOT movlw DASH_DEF movwf DASH movlw WSPACE_DEF movwf WSPACE movlw TUNE_DEF movwf TUNE movf BEACON_INT,w movwf SECCNT bsf INTCON,GIE goto main ;; ------------------------------------- ;; SUBROUTINES rx_byte movlw .8 movwf RX_BIT_CNT clrf INDF rx_byte_clk_high btfss GPIO,SCLK goto rx_byte_clk_high btfsc GPIO,SDAT bsf INDF,0 decfsz RX_BIT_CNT,f goto rx_byte_next movf INDF,w xorwf RX_CSUM,f incf FSR,f return rx_byte_next rlf INDF,f goto rx_byte_clk_high ;; ------------------------------------- rx_send_csum bsf STATUS,RP0 bcf TRISIO,SDAT bcf STATUS,RP0 movlw .8 movwf RX_BIT_CNT rx_send_clk_high btfss GPIO,SCLK goto rx_send_clk_high btfss RX_CSUM,7 bcf GPIO,SDAT btfsc RX_CSUM,7 bsf GPIO,SDAT decfsz RX_BIT_CNT,f goto rx_send_next bsf STATUS,RP0 bsf TRISIO,SDAT bcf STATUS,RP0 return rx_send_next rlf RX_CSUM,f goto rx_send_clk_high ;; ------------------------------------- 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 movf CHAR,w xorwf PARITY,f char_next_element bsf GPIO,CWOUT btfss ELEMENT,7 movf DOT,w btfsc ELEMENT,7 movf DASH,w call dottime bcf GPIO,CWOUT rlf ELEMENT,f decfsz ELECNT,f goto char_espace return char_espace movf ESPACE,w 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 movf CSPACE,w 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 movf CSPACE,w 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 movf CSPACE,w call dottime rrf INDF,w andlw b'00011111' call base32 call send_char decfsz PENTLECNT,f goto case3 return case3 movf CSPACE,w 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 movf CSPACE,w 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 movf CSPACE,w 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 movf CSPACE,w 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 movf CSPACE,w call dottime movf INDF,w andlw b'00011111' call base32 call send_char decfsz PENTLECNT,f goto caseend return caseend movf CSPACE,w call dottime incf FSR,f goto case0 ;; ------------------------------------- send_cnt rlf BEACONCNTL,w movwf TMP2 rlf BEACONCNTH,w movwf TMP1 movlw TMP1 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 movf WSPACE,w call dottime return ;; ------------------------------------- send_beacon bsf GPIO,CWENABLE movf TUNE,w call dottime clrf PARITY movlw START_CHAR call send_char movf WSPACE,w call dottime call send_callsign movf WSPACE,w call dottime call send_cnt movf WSPACE,w 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 movf TUNE,w call dottime clrf PARITY movlw ACK_CHAR call send_char movf WSPACE,w call dottime movf RX_CMD,w addlw 'A' call send_char movf WSPACE,w call dottime movlw RX_CMD movwf FSR movf RX_STATE,w andlw b'00001111' movwf TMP1 btfsc STATUS,Z goto ack_parity ack_next incf FSR,f movf INDF,w call send_char movf CSPACE,w call dottime decfsz TMP1,f goto ack_next ;; movf ACK_DATA,w ;; call send_char movf CSPACE,w call dottime ack_parity call send_parity bcf GPIO,CWENABLE return ;; ------------------------------------- ;; MAINLOOP main ;; this gets called after reset and whenever a wakeup occured ;; (after GP5 change or interrupt on GP2) movf SECCNT,f btfsc STATUS,Z goto seccnt_zero btfsc RX_STATE,complete goto msg_received goto powerdown ;; this gets called every BEACON_INT seconds seccnt_zero movf BEACON_INT,w movwf SECCNT btfsc NVSTATE,safe call send_beacon goto powerdown ;; this gets called whenver a message was received from ihu msg_received call send_ack clrf RX_STATE powerdown sleep nop goto main ;; ------------------------------------- ;; END end