// Telefoni seznam SKD
// by fallvonder 2007
// fallvonder.net

//nezapomente prilozit znaky.inc


.include "m169def.inc"
.org 0x0000
     jmp first

.org 0x000A
     jmp int_T2
.org 0x0100
first:
//inicializace zasob
ldi r16, 0x00
out SPL, r16
ldi r16, 0x04
out SPH, r16
jmp start
database:
.db "RIMMER" ,':',"325322",';', \
"LISTER" ,':',"326345",';', \
"HOLLY" ,':',"*001",';', \
"CAT" ,':',"3094",';', \
"CASE" ,':',"098723",';', \
"MOLLY" ,':',"187345",';', \
"LEELA" ,':',"645743",';', \
"BENDER" ,':',"234356",';', \
"ADAMS" ,':',"*42",';', \
"ADAMA" ,':',"87549",';', \
"TRACE" ,':',"78709",';', \
"FRY" ,':',"945034",';', \
"KIFF" ,':',"568923",';', \
"NIBLER" ,':',"291653",';', \
"KASSAD" ,':',"21",';',0

str: .include "znaky.inc"

.dseg
    trigger: .byte 1

dtb_pamet:      .Byte 1

.cseg

start:


      call init_disp
      call init_joy


      call create_index
      call bubble


              //inicializace preruseni
              cli ; globální zakázání prerušení
     ldi r16, 0b00001000
     sts ASSR, r16
     // vyber hodiny od krystalového oscilátoru 32768 Hz
     ldi r16, 0b00000001
     sts TIMSK2, r16 ; povolení prerušení od casovace 2
     ldi r16, 0b00000101
         //ldi r16, 0b00000001
     sts TCCR2A, r16 ; spuštení cítace s delicím pomerem 128
     clr r16 ; zákaz prerušení od
     sts PCMSK0, r16 ; joysticku
     out EIMSK, r16
     sei ; globální povolení prerušení
     ldi r16, 0x00
     sts trigger, r16



      ldi r28, low(dtb_pamet)
      ldi r29, high(dtb_pamet)
      ld r18, Y+

      clr r17
      clr r20




      call show_name

      ldi r19, 1
      ldi r27, 1
      //call modeI


              modeI_start:
              push r18
              call combo_load_errortest
              pop r18
              cpi r16, 0b01000000
              breq modeI_setUP
              cpi r16, 0b10000000
              breq modeI_setDOWN
              cpi r16, 0b00010000
              breq modeI_switchMode
              jmp modeI_trigger

      modeI_setUP:
              ldi r27, 0
      jmp modeI_trigger
      modeI_setDOWN:
              ldi r27, 1

      modeI_trigger:
              lds r16, trigger
              cpi r16, 1
              brne modeI_start
              clr r16
              sts trigger, r16

      cpi r27, 0
      brne modeI_down
      modeI_up:
              //dosazeni zacatku seznamu, presun na konec
              cpi r19, 1
              brne modeI_up_ok

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              ld r18, Y+

              mov r16, r18
              lsl r16
              add r28, r16

              clr r16
              adc r29, r16



              mov r19, r18
              //nastaveni r19 r18 jdeme pres konec indexu
              sbiw Y, 2
              jmp modeI_name
              modeI_up_ok:
                      dec r19
                      sbiw Y, 2
                      jmp modeI_name


      modeI_down:
              //dosazeni konce seznamu
              cp r19, r18
              brlo modeI_down_ok

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              ld r18, Y+
              clr r19
              inc r19
              jmp modeI_name
              modeI_down_ok:
                      inc r19
                      adiw Y, 2
                      jmp modeI_name


              modeI_name:
              call show_name
              jmp modeI_start



      modeI_switchMode:
              push r27
                      ldi r27, 0
                      call modeII
              pop r27

      jmp modeI_name


end:    rjmp    end

//_______________razeni__________________________________
create_index:
//r16 r17 - ulozeni adresy z Z reg do dalsiho pruchodu
//,jde i bez registru (2 zapisi do pameti navic)
//r19 nahravame znaky, testjeme na 0 ;
//r18 citac zaznamu
                               clr r18
              ldi r30, low(database<<1)
              ldi r31, high(database<<1)
              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              adiw Y, 1
              mov r16, r30
              mov r17, r31
      index_next:
              lpm r19, Z+
              cpi r19,';'
              brne index_end
              inc r18
      //ulozeni adresy zacatku slova,
      //pouziti r16,17 aby se neulozil koncici adresa
              st Y+, r16
              st Y+, r17
              mov r16, r30
              mov r17, r31

      index_end:
              tst r19
              brne index_next

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              st Y+, r18
ret


//bubble
      //r19,  r18 je nastaven z create_index
      //r17 uklada informaci o zavolani vymen
      //Y, Z , r20 r21
bubble:
      //nastaveni Y na zacatek indexu

      bubble_cyklus:
              clr r17
              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              ld r19, Y+
      //nastavani Y reg na adresu indexu
      //nahrani delky pole do r19

      bubble_next:
              dec r19
              tst r19
              breq bubble_end


      //skok pri nule na end
              ld r30, Y+
              ld r31, Y+
              ld r20, Y+
              ld r21, Y

              sbiw Y, 0x01

              call porovnej

              cpi r16, 1
              brne bubble_next

              ldi r17, 1
              call vymen
              rjmp bubble_next
      bubble_end:
              tst r17
              brne bubble_cyklus
ret


porovnej:
              push r17
porovnej_cyklus:
//adresu A dame primo do Z, r20 r21 B, r22vyrovnavaci ,
//r16 a r17 porovnani, r16 navratova hodnota
              lpm r16, Z+
              mov r22, r20
              mov r20, r30
              mov r30, r22
              mov r22, r21
              mov r21, r31
              mov r31, r22

              lpm r17, Z+
              //pripadne dat pred skok na cyklus- usetri pri konci retezce
              mov r22, r20
              mov r20, r30
              mov r30, r22
              mov r22, r21
              mov r21, r31
              mov r31, r22

              //konec A, test konce B
              cpi r16, ':'
              brne porovnej_tonext
              cp r16, r17
              breq porovnej_nula
              jmp porovnej_minus
              //test konce B
      porovnej_tonext:
              cpi r17, ':'
              breq porovnej_plus

              cp r16, r17
              breq porovnej_cyklus
              brlo porovnej_minus
              jmp porovnej_plus

      //vrati minus
      porovnej_minus:
              ldi r16, -1
              jmp porovnej_end
      //vraci nulu
      porovnej_nula:
              ldi r16, 0
              jmp porovnej_end
      porovnej_plus:
              ldi r16, 1
              jmp porovnej_end
      porovnej_end:
      pop r17
ret

vymen:
//prohodi hodnoty na r30 r20, r31 r21
//operuje s Y, vraci na zadany stav

      sbiw r28, 0x02

      ld r30, Y+
      ld r31, Y+
      ld r20, Y+
      ld r21, Y

      st Y, r31
      st -Y, r30
      st -Y, r21
      st -Y, r20

      adiw Y, 0x02

ret

//_______________________zobrazeni POLOZEK____________
show_zaznam:
// Z registr nastaveny,
//do r16 nahrvame znak, r27- ukoncovaci znak
              call cleansweep
      show_zaznam_pismeno:
              lpm r16, Z+
              cp r16, r27
              breq show_zaznam_end
              call show_char
              jmp show_zaznam_pismeno
      show_zaznam_end:

ret

show_name:
//nastaveny Y registr, Z registr, Ynemeni
//r27 na ukoncovaci znak, r16 v volaneFX
push r27
      ld r30, Y+
      ld r31, Y
      sbiw Y, 1
      ldi r27, ':'
      call show_zaznam
pop r27
ret

show_cislo:
//Y nemeni, Z, r27, r16
push r27
      ld r30, Y+
      ld r31, Y
      sbiw Y, 1
      show_cislo_najdi:
      lpm r16, Z+
      cpi r16, ':'
      brne show_cislo_najdi

      ldi r27, ';'
      call show_zaznam
pop r27
ret

//_______________SHOWCHAR__________________________________
show_char:
//save Z, r17
push r30
push r31
push r19
push r18
push r17
clr r25
   ldi r30, low(str<<1)
   ldi r31, high(str<<1)
   subi r16, 0x2a
   clz
   lsl r16
   //brcs, brcc adc - kontrola na prenosy shift left
   adc r31,r25
   lsl r16
   adc r31,r25

   add r30, r16
   adc r31,r25
       //pro obnoveni char_poz jeste kolize s r17
   //cpi r17, 2
   //BRLO zasebou
   //call show_charPoz
   //jmp konec

   zasebou:
   lpm
   mov r18, r0
   adiw r30, 1
   call mov_lccdrX0

   lpm
   mov r18, r0
   adiw r30, 1
   call mov_lccdrX5

   lpm
   mov r18, r0
   adiw r30, 1
   call mov_lccdrX10

   lpm
   mov r18,r0
   call mov_lccdrX15
   konec:
      pop r17
      pop r18
      pop r19
      pop r31
      pop r30
ret



mov_univ:
    ldi r17, 4
    cykl2:
           lsr r18
   ror r19
   ror r20
   ror r21
    dec r17
   brne cykl2


ret
mov_lccdrX0:
   lds r21, LCDDR0
   lds r20, LCDDR1
   lds r19, LCDDR2
   //call mov_univ
            ldi r17, 4
    cykl20:
           lsr r18
   ror r19
   ror r20
   ror r21
    dec r17
   brne cykl20

   sts LCDDR0, r21
   sts LCDDR1, r20
   sts LCDDR2, r19
ret
mov_lccdrX5:
   lds r21, LCDDR5
   lds r20, LCDDR6
   lds r19, LCDDR7
   //call mov_univ
             ldi r17, 4
    cykl25:
           lsr r18
   ror r19
   ror r20
   ror r21
    dec r17
   brne cykl25

   sts LCDDR5, r21
   sts LCDDR6, r20
   sts LCDDR7, r19
ret
mov_lccdrX10:
   lds r21, LCDDR10
   lds r20, LCDDR11
   lds r19, LCDDR12
   //call mov_univ
            ldi r17, 4
    cykl21:
           lsr r18
   ror r19
   ror r20
   ror r21
    dec r17
   brne cykl21

   sts LCDDR10, r21
   sts LCDDR11, r20
   sts LCDDR12, r19
ret
mov_lccdrX15:
   lds r21, LCDDR15
   lds r20, LCDDR16
   lds r19, LCDDR17
   //call mov_univ
            ldi r17, 4
    cykl215:
           lsr r18
   ror r19
   ror r20
   ror r21
    dec r17
   brne cykl215


   sts LCDDR15, r21
   sts LCDDR16, r20
   sts LCDDR17, r19
ret


init_disp:
   ldi r16, 0xB7
   sts LCDCRB, r16
   ldi r16, 0x10
   sts LCDFRR, r16
   ldi r16, 0x0F
   sts LCDCCR, r16
   ldi r16, 0x80
   sts LCDCRA, r16
ret

cleansweep:
push r27
push r17
clr r16
ldi r26, low(LCDDR0)
ldi r27, high(LCDDR0)
ldi r17, 18
 cykl:
st X+, r16
dec r17
brne cykl

pop r17
pop r27
ret

//__________________________JOYSTICK_______________
//joystickinit
init_joy:
     in r17, DDRE
     andi r17, 0b11110011
     in r16, PORTE
     ori r16, 0b00001100
     out DDRE, r17
     out PORTE, r16
     ldi r16, 0b00000000
     sts DIDR1, r16
     in r17, DDRB
     andi r17, 0b00101111
     in r16, PORTB
     ori r16, 0b11010000
     out DDRB, r17
     out PORTB, r16
         clr r17
ret

combo_load:
//v r17 ulozena predchozi poloha joysticku
//r16
//cyklus ceka na zmenu stavu joy
push r18
push r17
              call combo_load_errortest
              pop r17
              pop r18

              //zjistujeme jestli se zmenila pozice joysticku od minule
              cp r16, r17
              breq combo_load
              mov r17, r16
ret
combo_load_errortest:
//r16 vysledek, r18,r17 meni
     in r16, PINE
     in r18, PINB
     andi r16, 0b00001100
     andi r18, 0b11010000
     or r16, r18
     ori r16, 0b00100011
     com r16

      //pak jeste 1 cyklus
     ldi r18, 0xff
     cl:
     dec r18
     brne cl

     in r17, PINE
     in r18, PINB
     andi r17, 0b00001100
     andi r18, 0b11010000
     or r17, r18
     ori r17, 0b00100011
     com r17

              //odchyt chyby joysticku
              cp r16, r17
              brne combo_load_errortest
ret


/*
modeI:
//nahrava do r16 obsah triggeru, na 1 se posune na dalsi dal
// listovani UP/DOWN podle r27- nastavuje se dle jstk do r16 (pak prepsana ld)
//r19, r18 spolecne pro modeI a modeII
      modeI_start:
              call combo_load_errortest
              cpi r16, 0b01000000
              breq modeI_setUP
              cpi r16, 0b10000000
              breq modeI_setDOWN
              cpi r16, 0b00010000
              breq modeI_switchMode

      modeI_setUP:
              ldi r27, 0
      jmp modeI_trigger
      modeI_setDOWN:
              ldi r27, 1

      modeI_trigger:
              lds r16, trigger
              cpi r16, 1
              brne modeI_start
              clr r16
              sts trigger, r16

      cpi r27, 0
      brne modeI_down
      modeI_up:
              //dosazeni zacatku seznamu, presun na konec
              cpi r19, 1
              brne modeI_up_ok

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              adiw Y, 1

              mov r16, r18
              lsl r16
              add r28, r16
              clr r16
              adc r29, r16

              mov r19, r18
              //nastaveni r19 r18 jdeme pres konec indexu
              sbiw Y, 2
              jmp modeI_name
              modeI_up_ok:
                      dec r19
                      sbiw Y, 2
                      jmp modeI_name


      modeI_down:
              //dosazeni konce seznamu
              cp r19, r18
              brlo modeI_down_ok

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              adiw Y, 1
              clr r19
              inc r19
              jmp modeI_name
              modeI_down_ok:
                      inc r19
                      adiw Y, 2
                      jmp modeI_name


              modeI_name:
              call show_name
              jmp modeI_start



      modeI_switchMode:
              push r27
                      ldi r27, 0
                      call modeII
              pop r27
      jmp modeI_start

ret
*/



modeII:
//r17 predchozi info joystk
//r16 docanse pro nasobeni dvema pi odecitaniUP[preteceni nekontroluje
//r18 counter, r19 pricitameDown/odecitameUp
//r27 indikator 0jmeno-1cislo
clr r27
      modeII_start:
              call combo_load
              cpi r27, 1
              brne modeII_test_name
              //do leva- prenuti na jmeno
              cpi r17, 0b00000100
              breq modeII_name
              jmp modeII_test_enter

      modeII_test_name:
              cpi r17, 0b01000000
              breq modeII_up
              cpi r17, 0b10000000
              breq modeII_down
              cpi r17, 0b00001000
              breq modeII_cislo
      modeII_test_enter:
              cpi r17, 0b00010000
              brne modeII_start
                       modeII_test_enter_cykl:
                               call combo_load_errortest
                               cpi r16, 0b00000000
                       brne modeII_test_enter_cykl
              jmp modeII_end

      modeII_cislo:
              ldi r27, 1
              call show_cislo
              jmp modeII_start
      modeII_name:
              clr r27
              call show_name
              jmp modeII_start

      modeII_down:
              //dosazeni konce seznamu
              cp r19, r18
              brlo modeII_down_ok

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              ld r18, Y+
              clr r19
              inc r19
              jmp modeII_name
              modeII_down_ok:
                      inc r19
                      adiw Y, 2
                      jmp modeII_name

      modeII_up:
              //dosazeni zacatku seznamu, presun na konec
              cpi r19, 1
              brne modeII_up_ok

              ldi r28, low(dtb_pamet)
              ldi r29, high(dtb_pamet)
              ld r18, Y+


              mov r16, r18
              lsl r16
              add r28, r16

              clr r16
              adc r29, r16

              mov r19, r18

              //nastaveni r19 r18 jdeme pres konec indexu
              sbiw Y, 2
              jmp modeII_name
              modeII_up_ok:
                      dec r19
                      sbiw Y, 2
                      jmp modeII_name
              modeII_end:

ret


//__________________________PRERUSENI____________
init_prerus:
              cli ; globální zakázání prerušení
     ldi r16, 0b00001000
     sts ASSR, r16
     // vyber hodiny od krystalového oscilátoru 32768 Hz
     ldi r16, 0b00000001
     sts TIMSK2, r16 ; povolení prerušení od casovace 2
     ldi r16, 0b00000101
         //ldi r16, 0b00000001
     sts TCCR2A, r16 ; spuštení cítace s delicím pomerem 128
     clr r16 ; zákaz prerušení od
     sts PCMSK0, r16 ; joysticku
     out EIMSK, r16
     sei ; globální povolení prerušení
     ldi r16, 0x00
     sts trigger, r16
ret
int_T2: //… obsluha prerušení …
     push r16
     in r16, SREG
     push r16
     ldi r16, 1
     sts trigger, r16
     pop r16
     out SREG, r16
     pop r16

reti