Teletron.asm ;Apell 2012 04 24, ;Ekholm 20120509 ;ver 2/EUF eepromskrivning ;ver.3/UCZ 20120511 eepromskrivning vidare ;ver.4/EUF/UCZ 20120514 fixat eepromskrivningens buggar ;ver.5/UCZ 20120515 fixat toggling mellan 100Hz och 1kHz stegning ;ver.6/UCZ 20120517 sänkt klockfrekvensen till 32kHz för att reducera störningar från processorn ;Program för att styra en en Teletron TE704C mottagare via en pulsgivare, VFO-ratt, för att ersätta tumhjulen. ;Programmet skrivet i MPLAB IDE v8.83... hämtas gratis hos microchip.com ; ;eftersom processorn endast har 25 I/O portar så har "10Hz" funktionen slopats.. sparar 4 bitar. ;då räcker portarna till precis! Övriga önskemål av extra funktioner hindras effektivt av detta!! ;Alltså skall vi styra 6 siffror BCD 00.010.0 ... 29.999.9 kHz Lägsta frekvens 10kHz. ;när vfo-ratten stått still i 10 sekunder...sparas den frekvensen i eepromminnet, och kommer tillbaka vid nästa power on ; ;Att mottagaren inte är specad för mellanvågsbandet hanteras inte just nu!... den funkar där oxo! ;man ville förhindra rundradiomottagning på jobbet! Flera dämpkretsar i radion! ;Processorn jobbar med intern klocka 8MHz, alla faciliteter avstängda... vi ska bara räkna register upp och ner ;och skyffla data mellan register och utportar. ;*****[ Data Storage Reg's ]***** CBLOCK 0x20 ; Tilldela registerna olika namn från adressen 0x20 enctempnew enctempold ; Olika register till delayfunktionerna encod Hz100 kHz1 kHz10 kHz100 MHz1 MHz10 xPORTA xPORTB xPORTC Flags VARVREG1 ;Varvräknare för PROM-uppdateringar VARVREG2 ; VARVREG3 ENDC ;tilldela enskilda bitar egna namn, lättare att läsa #define encx PORTA,0 ; Encoder inputs #define ency PORTA,1 #define quick PORTE,3 ;snabbräknarknappen #define sparat Flags,0 ;flagga som sätts när frekvensen sparats #define enkHzstep Flags,1 ;flagga för 1kHz stegning #define enkHzflag Flags,2 ;flankflagga vid toggling 100Hz/1kHz ;********************************************************************************** ;Här talar vi om för assemblerprogrammet vilken processor vi har och vilka adresser ;som vi ska starta ifrån list p=18f2520 ;direktiv till assemblern om vilken process. som valts #include ; processor specific variable definitions errorlevel -302 ; Ignore error message when storing to Bank 1. ; __CONFIG _MCLRE_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INT_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF ;bitarna ställs i MPLAB manuellt! intern oscillator, MCLRE off, allt off! jag reder inte ut alla optionerna... org 0 ;adress vid power on eller reset här startar programkörningen goto init ;gå till initiering av kretsen vid power on... längst ner i programmet. ;********************************************************************************** ;Och här kommer själva programkoden... ;En smart code från Alvaro för att läsa av en encoder! ;genom att läsa in förändringen och sen skifta bitarna höger/vänster ;och ta hjälp av "carry-flaggan" kan det konstateras åt vilket håll ;pulsgivaren vrides! ;Alvaro Deibe Diaz [adeibe at CDF.UDC.ES] says: ; Encoder read main call skrivtimer ;kör timern och spara om tiden är mogen call toggla ;kolla om stegningen skall togglas?? clrf enctempnew ; cleara ett tempregister btfsc encx ; and get encoder inputs bsf enctempnew,0 ; in bit 0... btfsc ency bsf enctempnew,1 ; ...and 1 movf enctempnew,w ;kolla om det är någon förändring på inkommande encodersignal?? subwf enctempold,w btfsc STATUS,Z goto main ;om inte...hoppa till main movf enctempnew,w ;förändring har skett...skriv nya värdet i tempregistret "old"... för att kunna kolla nästa gång movwf enctempold ;om pulsgivaren har snurrats ; ; Here starts the hard work ;nu vet vi att någon har fingrat på pulsgivaren.. men åt vilket håll?? movf enctempnew,W ; encod <- (actual state) xor (previous one) xorwf encod,F ; (only bits 0 and 1 affected) ;här kommer det smarta... rotera via "carry-flaggan" rrcf enctempnew,F ; XOR results, reordered, get rlcf encod,F ; into encod, in bits 0 and 1. rrcf enctempnew,F ; This bits are the motion indicators rlcf encod,F ; ;At this point you have a new read of the encoder. Bits 2 and 3 of 'encod' ;have the information about the direction of movement of the encoder. If you ;have to translate this information into a variable, then you can do ;something like this: ; btfsc encod,2 ; Direction 'X' motion goto countup ;hoppa till räkna upp btfsc encod,3 ; ...or 'Y' goto countdown ;hoppa till räkna ner goto main ; ;Bits 4,5 and 6,7 of 'encod' have the previous reads. ;*************************************************************************************************** toggla ;att toggla mellan 100Hz och 1kHz stegning varannan gång QUICK knappen tryckes btfsc quick ;när quickknappen släppes reset flankflaggan goto jmp15 bcf enkHzflag return jmp15 btfsc enkHzflag ;kolla om flankflaggan är satt return ;då blir det return btfss enkHzstep goto jmp16 bcf enkHzstep bsf enkHzflag return jmp16 bsf enkHzstep bsf enkHzflag return ;************************************************************************************************ ;Att räkna upp är enkelt... men kolla därefter om registret blev "10" ;då skall nästa siffra räknas upp! vi räknar bara 0,1,2...9 BCD! i varje register countup btfsc quick ;kolla om det skall snabbräknas, tryckknappen QUICK är TILL goto snabb btfsc enkHzstep ;val mellan 100Hz eller 1kHz stegning goto enkHzu incf Hz100,f ;öka 100Hz med 1 movlw .10 ;kolla om det blev "10". ladda in "10" subwf Hz100,w ;minska registret med 10 och kolla om det blev "0" = Z btfss STATUS,Z goto display ;om inte "10" gå till displayvisning... bara denna siffran ändrade sig enkHzu ;toggling mellan 100Hz/1kHz stegning clrf Hz100 ;om lika med "10" sätt Hz till "0" incf kHz1,f ;öka 1kHz siffran istället movlw .10 subwf kHz1,w ;kolla om "10" btfss STATUS,Z goto display ;och lika för alla siffrorna clrf kHz1 incf kHz10,f ;10kHz movlw .10 subwf kHz10,w btfss STATUS,Z goto display clrf kHz10 snabb btfsc quick ;nollställ de lägsta siffrorna vid snabbscrollning call clearas incf kHz100,f ;hoppa hit direkt vid snabbräkning movlw .10 subwf kHz100,w ;100kHz btfss STATUS,Z goto display clrf kHz100 incf MHz1,f ;1MHz movlw .10 subwf MHz1,w btfss STATUS,Z goto display clrf MHz1 incf MHz10,f ;10MHz movlw .10 subwf MHz10,w btfss STATUS,Z goto display goto display ;************************************************************************************************* ;Att räkna ner är inte lika enkelt när vi skall hålla oss till siffrorna 0...9 i BCD format countdown btfsc quick ;kolla om det skall snabbräknas goto jmpq ;hoppa då till 100kHz siffran direkt btfsc enkHzstep ;val mellan 100Hz eller 1kHz stegning goto enkHzd movf Hz100, w ;kolla först om det är "0" i Hz100, då är det nästa siffra som skall räknas ner btfsc STATUS, Z ;genom att ladda i filen i w så sätts Z om det är noll goto jmp1 ;det är "0" hoppa till nästa siffra decf Hz100, f ;inte "0" då stegar vi ner ett hack goto display ;det blir bara denna siffra som skall räknas ner...gå direkt till visning jmp1 movlw .9 ;skriv in "9" i föregående siffra...den var ju "0" innan movwf Hz100 enkHzd btfsc enkHzstep clrf Hz100 ;toggling mellan 100Hz/1kHz stegning movf kHz1,w ;kolla så det inte är "0" btfsc STATUS,Z goto jmp2 decf kHz1, f ; 1kHz goto display jmp2 movlw .9 movwf kHz1 movf kHz10,w btfsc STATUS,Z goto jmp3 decf kHz10, f ; 10kHz goto display jmp3 movlw .9 movwf kHz10 jmpq btfsc quick ;nollställ de lägsta siffrorna vid snabbscrollning call clearas movf kHz100,w ;hoppa hit om det skall snabbräknas btfsc STATUS,Z goto jmp4 decf kHz100, f ;100kHz goto display jmp4 movlw .9 movwf kHz100 movf MHz1,w btfsc STATUS,Z goto jmp5 decf MHz1, f ; 1Mhz goto display jmp5 movlw .9 movwf MHz1 movf MHz10,w btfsc STATUS,Z goto jmp6 decf MHz10, f ; 10MHz goto display jmp6 clrf MHz10 goto display clearas clrf Hz100 clrf kHz1 clrf kHz10 return ;**************************************************************************************************** ;kolla om det är under 10kHz!! Mottagaren funkar inte där! lågkoll movlw .0 ;genom att kolla om alla BCD är "0" subwf MHz10,w ;kan det fastställas om frekvensen btfss STATUS,Z ;är under 10kHz return movlw .0 subwf MHz1,w btfss STATUS,Z return movlw .0 subwf kHz100,w btfss STATUS,Z return movlw .0 subwf kHz10,w btfss STATUS,Z return ;inte under 10kHz...tebaks ;det blev under 10kHz movlw .9 ;skriv in 29.999.9kHz movwf Hz100 movwf kHz1 movwf kHz10 movwf kHz100 movwf MHz1 movlw .2 movwf MHz10 return ;******************************************************************************************************** ;kolla om det är över 29.999.9 kHz.. då skriver vi in 10kHz högkoll movlw .3 ;det är över 29.999.9...alltså 30.XXX.XXX subwf MHz10,w ;det räcker att kolla om 10MHz är "3" btfss STATUS,Z return ;inte över...tebaks cleara clrf Hz100 ;över...då rensar vi alla siffror clrf kHz1 clrf kHz10 clrf kHz100 clrf MHz1 clrf MHz10 movlw .1 ;och skriver in 10kHz movwf kHz10 return ;****************************************************************************************************** ;Nu är det dax att flytta ut resultaten till mottagaren och displayen ;för att det inte skall bli flimmer så sorterar vi upp alla bitarna till ;sina rätta platser i temporära register. ;därefter kopieras dessa register ut till verkligheten display call lågkoll ;kolla först om värdet är under eller över tillåtet call högkoll ;att vi håller oss inom mottagaren specifikationer clrf xPORTA ;flytta över varje bit till sin plats i utporten btfsc MHz10,0 ;först i ett tempregister, sen ut till porten bsf xPORTA,2 ;enklast är att rensa registret först btfsc MHz10,1 ;och sen skriva in i respektive bit en "1" om det skall vara en. bsf xPORTA,3 ;10MHz btfsc MHz1,0 bsf xPORTA,4 btfsc MHz1,1 ;1MHz bsf xPORTA,5 btfsc MHz1,2 bsf xPORTA,6 btfsc MHz1,3 bsf xPORTA,7 clrf xPORTB btfsc kHz10,0 bsf xPORTB,0 btfsc kHz10,1 ;10kHz bsf xPORTB,1 btfsc kHz10,2 bsf xPORTB,2 btfsc kHz10,3 bsf xPORTB,3 btfsc kHz100,0 bsf xPORTB,4 btfsc kHz100,1 bsf xPORTB,5 ;100kHz btfsc kHz100,2 bsf xPORTB,6 btfsc kHz100,3 bsf xPORTB,7 clrf xPORTC btfsc Hz100,0 bsf xPORTC,0 btfsc Hz100,1 bsf xPORTC,1 ;100Hz btfsc Hz100,2 bsf xPORTC,2 btfsc Hz100,3 bsf xPORTC,3 btfsc kHz1,0 bsf xPORTC,4 btfsc kHz1,1 bsf xPORTC,5 ;1kHz btfsc kHz1,2 bsf xPORTC,6 btfsc kHz1,3 bsf xPORTC,7 movf xPORTA,w ;och här flyttas det ut till verkligheten! movwf PORTA movf xPORTB,w movwf PORTB movf xPORTC,w movwf PORTC clrf VARVREG1 ;nollställ skrivtimern till eepromskrivningen clrf VARVREG2 ;pulsgivaren är fingrad... movlw .10 ;ger ca 10 sek fördröjning av dataskrivningen till eeprommet movwf VARVREG3 bcf sparat ;frekvensen är ändrad från tidigare sparade...tillåt ny arkivering i eeprom goto main ;*************************************************************************************** ;Timer som fördröjer skrivningen till minnet ca 10 sekunder ;efter det man slutat att vrida på vfo-ratten skrivtimer ;med VARVREG3=10 så ca 10 sek fördröjning ; decfsz VARVREG1,f ;Minska inre loop med 1 return ;Om INTE =0 gör ett varv till ; decfsz VARVREG2,f ;Minska yttre loop med 1... vid 32kHz klocka slopas denna! ; return ;Gör ett varv till decfsz VARVREG3,f return call spara ;här har den yttre räknaren blivit "0" spara i eeprom!! return ;******************************************************************************************* ; Write Byte to EEPROM... rutin som anropas vid varje byte skrivning ; ; Input: Adress och data måste ligga i EEADR och EEDATA när rutinen anropas WriteEEPROM: banksel EECON1 bcf EECON1,EEPGD bcf EECON1,CFGS bsf EECON1,WREN ; start the write (must follow this sequence exactly!) bcf INTCON,GIE movlw 55h movwf EECON2 ; Write 55h movlw 0AAh movwf EECON2 ; Write AAh bsf EECON1,WR ; Set WR bit starta skrivningen bsf INTCON,GIE ; write now in progress jmpee btfss PIR2,EEIF ;vänta tills interruptflaggan kommer...skrivningen färdig goto jmpee bcf EECON1,WREN ;stäng skrivmöjligheten bcf PIR2,EEIF ;reset interruptflaggan banksel 0 return ;---------------------------------------------------------------------- ; Read Byte from EEPROM ;Adressen måste finnas i EEADR när rutinen anropas ;datat ligger i w när rutinen lämnas ; Input: W=address ; Output: W=Byte ; ReadEEPROM: banksel EECON1 wait_read: btfsc EECON1,RD ; wait for end of previous read goto wait_read ; bcf EECON1,EEPGD bcf EECON1,CFGS bsf EECON1,RD ;initiate READ movf EEDATA,W ;transfer Byte to W banksel 0 RETURN ;---------------------------------------------------------------------- ;frekvensen sparas 10 sekunder efter det att vfo-ratten slutat att vridas ;Skriv från resp. "siffra" till EEPROM spara btfsc sparat ;kolla om samma frekvens redan är sparad! Spärrflaggan är satt return ;den är redan sparad...tebaks movlw .0 ;spara undan 100Hz movwf EEADR ;först rätt adress movf Hz100,w movwf EEDATA ;och sen rätt data call WriteEEPROM ;skickas till eepromskrivningen movlw .1 ;spara undan 1kHz movwf EEADR movf kHz1,w movwf EEDATA call WriteEEPROM movlw .2 ;spara undan 10kHz movwf EEADR movf kHz10,w movwf EEDATA call WriteEEPROM movlw .3 ;spara undan 100kHz movwf EEADR movf kHz100,w movwf EEDATA call WriteEEPROM movlw .4 ;spara undan 1MHz movwf EEADR movf MHz1,w movwf EEDATA call WriteEEPROM movlw .5 ;spara undan 10MHz movwf EEADR movf MHz10,w movwf EEDATA call WriteEEPROM ; clrf PORTC ;släcker porten som kvitto på att skrivningen är färdig...för testningen bsf sparat ;sätt flaggan frekvensen sparad.... resetas när pulsgivaren vrides return ;skrivningen är färdigt...tebaks ;******************************************************************************************** ;detta anropas vid power on och läser in senast sparade frekvensen läseeprom movlw .0 ;Promadr 0 till w movwf EEADR ; call ReadEEPROM movwf Hz100 ;läsningen finns i w bara att pytsa ut i rätt file movlw .1 ;Promadr 1 till w movwf EEADR ; call ReadEEPROM movwf kHz1 ;läsningen finns i w bara att pytsa ut i rätt file movlw .2 ;Promadr 2 till w movwf EEADR ; call ReadEEPROM movwf kHz10 ;läsningen finns i w bara att pytsa ut i rätt file movlw .3 ;Promadr 3 till w movwf EEADR ; call ReadEEPROM movwf kHz100 ;läsningen finns i w bara att pytsa ut i rätt file movlw .4 ;Promadr 4 till w movwf EEADR ; call ReadEEPROM movwf MHz1 ;läsningen finns i w bara att pytsa ut i rätt file movlw .5 ;Promadr 5 till w movwf EEADR ; call ReadEEPROM ;hämta från eeprommet movwf MHz10 ; movlw 0FFH ;nytt chip kan ha FF i minnena subwf MHz1,w ;kollar bara en siffra... btfsc STATUS,Z call cleara ;i så fall rensa och skriv in 10kHz call display ;pytsa ut värdena på displayen return ;**************************************************************************************** init ;initiering av kretsen vid power on clrf PORTA ;rensa först alla portar clrf PORTB ;så inte siffrorna fladdrar till vid power on clrf PORTC clrf PORTE clrf LATA clrf LATB movlw 0fh movwf ADCON1 ;gör analogmodulen till vanliga I/O movlw 07h movwf CMCON ;gör komparatormodulen till vanliga I/O movlw b'10001111' movwf OSCCON ;(sätt 8MHz klocka) klockan reducerad till 32kHz! movlw b'00000011' ;fixa till två ingångar till pulsgivaren RA0 + RA1 movwf TRISA ;1=Input 0=output clrf TRISB ;alla övriga portar göres till utgångar clrf TRISC ;ingången RE3 är alltid en ingång...behöver ej sättas clrf Hz100 ;säkerställ att registren är rena vi använder bara 4 av 8 bitar i varje register clrf kHz1 clrf kHz10 clrf kHz100 clrf MHz1 clrf MHz10 clrf Flags call läseeprom ;läs in från minnet till frekvensen vid start upp movlw .5 movwf VARVREG3 ;förställ timern för skrivintervallerna goto main ;gå till huvudprogrammet end