principal.txt 14.5 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
; Équivalences

.equ PINA = 0x00
.equ DDRA = 0x01
.equ PORTA = 0x02
.equ PINC = 0x06
.equ DDRC = 0x07
.equ PORTC = 0x08
.equ PING = 0x12
.equ DDRG = 0x13
.equ PORTG = 0x14

.equ WDTCSR = 0x60

.equ TTCR0A = 0x24
.equ TTCR0B = 0x25
.equ TMSK0 = 0x6e

.equ EIMSK = 0x3D
.equ EICRA = 0x69
.equ EICRB = 0x6A

.equ ADMUX = 0x7C
.equ ADCSRB = 0x7B
.equ ADCSRA = 0x7A
.equ ADCH = 0x79
.equ DIR0 = 0x7E
.equ DIR2 = 0x7D

.equ SPH = 0x3E
.equ SPL = 0x3D

; Nommage des registres utilisés

.def etat = r12
.def compteur = r6 ; Utilisé pour modifier des valeurs dans le menu

.def reference = r13 ; Température de référence actuelle

.def d3 = r2 ; Digit 3 (tout à gauche)
.def d2 = r3 ; Digit 2
.def d1 = r4 ; Digit 1
.def d0 = r5 ; Digit 0 (tout à droite)

.def t2 = r8 ; Jour (3 premiers bits) et Heure (5 derniers bits)
.def t1 = r9 ; Minutes
.def t0 = r10 ; Secondes / 2
.def tt = r11 ; Watchdog artificiel

.def temp = r7 ; Utilisé pour différentes choses mais très brièvement

; Nommage des adresses RAM utilisées

.equ assocs = 0x0200 ; Association des modes aux heures (tableau de taille 168 octets)
.equ tempJour = 0x02a8 ; Température du mode jour
.equ tempNuit = 0x02a9 ; Température du mode nuit

; Vecteurs d'interruptions

.org 0x000 ; Vecteur RESET
    jmp debut

.org 0x0002 ; INT0
    jmp retour

.org 0x0004 ; INT1
    jmp decrementer
    
.org 0x0006 ; INT2
    jmp incrementer

.org 0x0008 ; INT3
    jmp valider

.org 0x0018 ; Watchdog
    jmp watchdog

.org 0x002E ; Timer
    jmp timer

.org 0x003A ; ADC
    jmp adc


.org 0x0080

; Tableaux de la mémoire du programme

afficheur:
    .DB 0x3F, 0x30, 0x6D, 0x79, 0x72, 0x5B, 0x5F, 0x31, 0x7F, 0x7B
    ;      0,    1,    2,    3,    4,    5,    6,    7,    8,    9

; Programme

debut:
; Configuration des composants
    ; Ports parallèles
    DDRA@IO <- 0xFF
    DDRC@IO <- 0xFF
    DDRG@IO <- 0xFF

    ; Barres de chargement
    PORTA@IO <- 0x40
    PORTC@IO <- 0x00

    ; Watchdog
    ;WDTCSR <- 0b00010000
    ;WDTCSR <- 0b01000111

    ; Timer
    TTCR0A@IO <- 0b00000000
    TTCR0B@IO <- 0b00000100 ; Timer toutes les 4ms
    TMSK0  <-    0b00000001

    ; Interruptions externes
    EIMSK <- 0b00001111
    EICRA <- 0b10101010
    EICRB <- 0b00000000

    ; ADC
    ADMUX  <- 0b01100000
    ADCSRB <- 0b00000010
    ADCSRA <- 0b11011110
    DIR0   <- 0b11111110
    DIR2   <- 0b11111111

; Initialisation des registre
    etat <- 0
    ; compteur initialisé quand on en aura besoin
    ; reference initialisé avec agirHeure
    ; d3, d2, d1, d0 initialisés avec afficherHorloge

    ; Mardi 14h00'55
    t2 <- 0b00101110
    t1 <- 0
    t0 <- 55
    tt <- 0

    ; temp initialisé quand on en aura besoin

; Initialisation de la RAM
    ; Valeurs de démonstration : 7° - 27° (on jouerait plus sur du 17° - 21° en réalité)
    tempNuit <- 20
    tempJour <- 220

    ; Initialisation des associations
    compteur <- 0 ; Jour
initJour:
    temp <- 0 ; Heure
initHeure:
    assocs[compteur * 24 + temp] <- 0 ; Par défaut le mode jour
    si temp <= 7 alors assocs[compteur * 24 + temp] <- 1 ; Entre minuit et 7h le mode nuit
    inc temp
    if temp < 24 saut initHeure
    inc compteur
    if compteur < 7 saut initJour

; Logique de démarrage
    call afficherHorloge
    call agirHeure

    ; On active les interruptions une fois que tout est prêt
    sei

boucle:
    sleep
    jmp boucle

; Fonctions

; Affichages
afficherHorloge:
    ; Affiche l'heure actuelle
    temp <- t2 & 0b00011111
    d3 <- 0x00
    si temp > 10 alors d3 <- afficheur@ROM[temp/10]
    d2 <- afficheur@ROM[temp%10] | 0b10000000
    d1 <- afficheur@ROM[t1/10]
    d0 <- afficheur@ROM[t1%10]
    ret

afficherTemperature:
    ; Considère le registre compteur comme une température et l'affiche
    d0 <- 0x63 ; Sigle degré
    d1 <- afficheur@ROM[compteur%10] ; Décimale
    temp <- compteur / 10 + 5 ; On stocke temporairement la partie entière pour simplifier
    d2 <- afficheur@ROM[temp%10] | 0b10000000 ; Chiffre des unités, auquel on ajoute le point
    d3 <- 0x00 ; On affiche le chiffre des dizaines si la température est > 10
    si temp > 10 alors d3 <- afficheur@ROM[temp/10]
    ret

afficherHeur:
    ; Considère le registre compteur comme une heure et l'affiche
    d3 <- afficheur@ROM[compteur/10]
    d2 <- afficheur@ROM[compteur%10] | 0b10000000
    d1 <- 0x00
    d0 <- 0x00
    ret

afficherMinu:
    ; Considère le registre compteur comme une minute et l'affiche
    d3 <- 0x00
    d2 <- 0b10000000
    d1 <- afficheur@ROM[compteur/10]
    d0 <- afficheur@ROM[compteur%10]
    ret

afficherJour:
    ; Considère le registre compteur comme un jour et l'affiche
    d1 <- 0x00;
    d0 <- 0x00;
    si compteur = 0 saut afficherLu
    si compteur = 1 saut afficherMa
    si compteur = 2 saut afficherMe
    si compteur = 3 saut afficherJe
    si compteur = 4 saut afficherVe
    si compteur = 5 saut afficherSa
    si compteur = 6 saut afficherDi
    ret ; Ne devrait pas arriver, mais permet d'éviter les dégâts

afficherLu:
    d3 <- 0x0E
    d2 <- 0x1c    
    ret

afficherMa:
    d3 <- 0x37
    d2 <- 0x77    
    ret

afficherMe:
    d3 <- 0x37
    d2 <- 0xcf    
    ret

afficherJe:
    d3 <- 0x3c
    d2 <- 0xcf    
    ret

afficherVe:
    d3 <- 0x1c
    d2 <- 0xcf    
    ret

afficherSa:
    d3 <- 0x5b
    d2 <- 0x77    
    ret

afficherDi:
    d3 <- 0xfc
    d2 <- 0x04    
    ret

; Logique

agir1s:
    ; Met à jour les registres de temps, active agir10s ou agirHeure si nécessaire
    inc t0
    si t0%10 != 0 saut ret ; Continue si on est sur un multiple de 10 secondes
    call agir10s
    si t0 < 60 saut ret ; Continue si on est sur un multiple de 60 secondes
    t0 <- 0
    inc t1
    si t1 < 60 saut ret ; Continue si on est sur un multiple de 60 minutes
    t1 <- 0
    inc t2
    si t2 & 0b00011111 >= 7 saut agir1sHeur ; Continue si il est minuit
    t2 <- t2 + 0b00100000 ; Jour suivant
    t2 <- t2 & 0b11100000 ; Heure à minuit
    si t2 >= 0b11100000 alors t2 <- 0b00000000 ; Si on est dimanche soir, on revient à lundi matin
agir1sHeur:
    call agirHeure
    ret

agir10s:
    ; Déclenche une conversion ADC
    ADCSRA <- 0b11011101
    ; Switche l'état de veille si veille il y a
    si etat =   0 saut a10sVeilleTemp
    si etat =   1 saut a10sVeilleHeur
    ret
a10sVeilleHeur:
    etat <- 0
    call afficherHorloge
    ret
a10sVeilleTemp:
    etat <- 1
    compteur <- ADCH
    call afficherTemperature
    ret

agirHeure:
    ; Recharge la température de référence
    temp <- (t2 / 0b00100000) * 24 + (t2 & 0b00011111)
    ;       ↑ numéro du jour de la semaine
    ;                                ↑ heure actuelle
    if assocs[temp] = 0x00 alors reference <- tempJour
    if assocs[temp] = 0x01 alors reference <- tempNuit
    ret

; Recadrage
boundHeur:
    si compteur =  255 alors compteur <- 23
    si compteur >= 24  alors compteur <- 0
    ret

boundMinu:
    si compteur =  255 alors compteur <- 59
    si compteur >= 60  alors compteur <- 0
    ret

boundJour:
    si compteur = 255 alors compteur <- 6
    si compteur >= 7  alors compteur <- 0
    ret

boundTemperature:
    si compteur < 5   alors compteur <- 250
    si compteur > 250 alors compteur <- 5
    ret

; Puisque l'assembleur étendu ne supporte pas les retours conditionnels
ret:
    ret
reti:
    reti

; États
; × : Arrivée à l'état par un niveau supérieur
; R : Arrivée à l'état par un niveau inférieur
; U : Mise à jour de l'affichage
; C : Changement de l'état

etatVeilleHeur:
    etat <- 0
    call afficherHorloge
    reti

etatVeilleTemp:
    etat <- 1
    compteur <- ADCH
    call afficherTemperature
    reti

etatMenuAssoc:
    etat <- 2
    d3 <- 0x77
    d2 <- 0x5b
    d1 <- 0x5b
    d0 <- 0x5c
    reti

etatMenuJours:
    ; Par défaut on prend le jour actuel
    compteur <- t2 / 0b00100000
etatMenuJoursU:
    etat <- 3 + compteur
    call afficherJour
    reti

etatMenuJoursR:
    compteur <- etat - 7 - 3
    jmp etatMenuJoursU

etatMenuJoursC:
    call boundJour
    jmp etatMenuJoursU

etatParaJours:
    etat <- etat + 7
    compteur <- t2 & 0b00011111
etatParaJoursU:
    d3 <- afficheur@ROM[compteur/10]
    d2 <- afficheur@ROM[compteur%10]
    d1 <- 0x00
    temp <- (etat - 10) * 24 + compteur
    ; Si la RAM n'est pas initialisée à cet endroit, on préfère afficher un tiret
    d0 <- 0x40
    si assocs[temp] = 0b00000000 alors d0 <- 0x3c
    si assocs[temp] = 0b00000001 alors d0 <- 0x54
    reti

etatParaJoursC:
    call boundHeur
    jmp etatParaJoursU

etatParaJoursS: ; Switch
    temp <- (etat - 10) * 24 + compteur
    assocs[temp] <- (assocs[temp] + 1) & 0b00000001
    call agirHeure ; Au cas où on change l'heure en cours
    jmp etatParaJoursU

; Appelé depuis l'état  2 après un appui sur le  bouton Incrémenter
;                      19                               Décrémenter
;                      18                               Valider
;                      18                               Retour
etatMenuTJour:
    etat <- 17
    d3 <- 0x3c ; "JOUR"
    d2 <- 0x5c
    d1 <- 0x1c
    d0 <- 0x44
    reti

; Appelé depuis l'état 17 après un appui sur Valider
etatParaTJour:
    etat <- 18
    compteur <- tempJour ; Lecture depuis la RAM
etatParaTJourU:
    call afficherTemperature
    reti

; Appelé depuis l'état 18 après un appui sur Incrementer ou Decrementer
etatParaTJourC:
    call boundTemperature ; Remet la température dans les bornes
    tempJour <- compteur ; Écriture vers la RAM
    call agirHeure ; Au cas où on change le mode de l'heure actuelle, on recharge la température de référence
    jmp etatParaTJourU

etatMenuTNuit:
    etat <- 19
    d3 <- 0x54 ; "NUIT"
    d2 <- 0x1c
    d1 <- 0x04
    d0 <- 0x4e
    reti

etatParaTNuit:
    etat <- 20
    compteur <- tempNuit
etatParaTNuitU:
    call afficherTemperature
    reti

etatParaTNuitC:
    call boundTemperature
    tempNuit <- compteur
    call agirHeure ; Au cas où on change le mode en cours
    jmp etatParaTNuitU

etatMenuHorloge:
    etat <- 21
    d3 <- 0x76 ; "HORL"
    d2 <- 0x5c
    d1 <- 0x44
    d0 <- 0x0E
    reti

etatMenuHJour:
    etat <- 22
    d3 <- 0x3c ; "JOUR"
    d2 <- 0x5c
    d1 <- 0x1c
    d0 <- 0x44
    reti

etatMenuHHeur:
    etat <- 23
    d3 <- 0x76 ; "HEUR"
    d2 <- 0xcf
    d1 <- 0x1c
    d0 <- 0x44
    reti

etatMenuHMinu:
    etat <- 24
    d3 <- 0x37 ; "MINU"
    d2 <- 0x04
    d1 <- 0x54
    d0 <- 0x1c
    reti

etatParaHJour:
    etat <- 25
    compteur <- t2 / 0b00100000
    call afficherJour
    reti

etatParaHJourC:
    call boundJour
    t2 <- (compteur * 0b00100000) + (t2 & 0b00011111)
    call agirHeure
    call afficherJour
    reti

etatParaHHeur:
    etat <- 26
    compteur <- t2 & 0b00011111
    call afficherHeur
    reti

etatParaHHeurC:
    call boundHeur
    t2 <- (t2 & 0b11100000) + compteur
    call agirHeure
    call afficherHeur
    reti

etatParaHMinu:
    etat <- 27
    compteur <- t1
    call afficherMinu
    reti

etatParaHMinuC:
    call boundMinu
    t1 <- compteur
    call afficherMinu
    reti

; Interruption boutons

incrementer:
    inc compteur
    si etat =   0 saut etatVeilleTemp
    si etat =   1 saut etatVeilleHeur
    si etat =   2 saut etatMenuTJour
    si etat <=  9 saut etatMenuJoursC
    si etat <= 16 saut etatParaJoursC
    si etat =  17 saut etatMenuTNuit
    si etat =  18 saut etatParaTJourC
    si etat =  19 saut etatMenuHorloge
    si etat =  20 saut etatParaTNuitC
    si etat =  21 saut etatMenuAssoc
    si etat =  22 saut etatMenuHHeur
    si etat =  23 saut etatMenuHMinu
    si etat =  24 saut etatMenuHJour
    si etat =  25 saut etatParaHJourC
    si etat =  26 saut etatParaHHeurC
    si etat =  27 saut etatParaHMinuC
    reti ; Ne devrait pas arriver, mais permet d'éviter les dégâts

decrementer:
    dec compteur
    si etat =   0 saut etatVeilleTemp
    si etat =   1 saut etatVeilleHeur
    si etat =   2 saut etatMenuHorloge
    si etat <=  9 saut etatMenuJoursC
    si etat <= 16 saut etatParaJoursC
    si etat =  17 saut etatMenuAssoc
    si etat =  18 saut etatParaTJourC
    si etat =  19 saut etatMenuTJour
    si etat =  20 saut etatParaTNuitC
    si etat =  21 saut etatMenuTNuit
    si etat =  22 saut etatMenuHMinu
    si etat =  23 saut etatMenuHJour
    si etat =  24 saut etatMenuHHeur
    si etat =  25 saut etatParaHJourC
    si etat =  26 saut etatParaHHeurC
    si etat =  27 saut etatParaHMinuC
    reti ; Ne devrait pas arriver, mais permet d'éviter les dégâts

valider:
    si etat <=  1 saut etatMenuAssoc
    si etat =   2 saut etatMenuJours
    si etat <=  9 saut etatParaJours
    si etat <= 16 saut etatParaJoursS
    si etat =  17 saut etatParaTJour
    si etat =  18 saut etatMenuTJour
    si etat =  19 saut etatParaTNuit
    si etat =  20 saut etatMenuTNuit
    si etat =  21 saut etatMenuHJour
    si etat =  22 saut etatParaHJour
    si etat =  23 saut etatParaHHeur
    si etat =  24 saut etatParaHMinu
    si etat =  25 saut etatMenuHJour
    si etat =  26 saut etatMenuHHeur
    si etat =  27 saut etatMenuHMinu
    reti ; Ne devrait pas arriver, mais permet d'éviter les dégâts

retour:
    si etat <=  1 saut reti
    si etat =   2 saut etatVeilleHeur
    si etat <=  9 saut etatMenuAssoc
    si etat <= 16 saut etatMenuJoursR
    si etat =  17 saut etatVeilleHeur
    si etat =  18 saut etatMenuTJour
    si etat =  19 saut etatVeilleHeur
    si etat =  20 saut etatMenuTNuit
    si etat =  21 saut etatVeilleHeur
    si etat <= 24 saut etatMenuHorloge
    si etat =  25 saut etatMenuHJour
    si etat =  26 saut etatMenuHHeur
    si etat =  27 saut etatMenuHMinu
    reti ; Ne devrait pas arriver, mais permet d'éviter les dégâts

; Interruption Watchdog
watchdog:
    call agir1s
    reti

; Interruption ADC
adc:
    ADCSRA <- 0b11011101 ; DEBUG Lire la température continuellement
    si ADCH > reference + 5 saut eteindreChaudiere
    si ADCH < reference - 5 saut allumerChaudiere
    reti
allumerChaudiere:
    PORTG@IO <- 0xFF
    reti
eteindreChaudiere:
    PORTG@IO <- 0x00
    reti

; Interruption timer (~4 ms)
timer:
    ; Notre composant requiert d'envoyer 0 sur PC7-4
    ; afin d'activer le digit qui y est connecté

    ; Affiche le digit suivant sur l'afficheur 7seg
    temp <- PORTC@IO ; On lit le port dans son état précédent
    lsr temp ; On change de digit
    ; Il y a 4 digits et 8 bits, on doit donc boucler plus tôt
    si temp < 0b00001111 alors temp <- 0b11110111
    PORTC@IO <- temp
    ; On envoie le registre correpspondant
    si temp = 0b11110111 alors PORTA@IO <- d3
    si temp = 0b01111011 alors PORTA@IO <- d2
    si temp = 0b00111101 alors PORTA@IO <- d1
    si temp = 0b00011110 alors PORTA@IO <- d0

    ; Watchdog artificiel
    inc tt
    if tt < 244 saut reti
    ;if tt < 10 saut reti ; DEBUG Avancer le temps
    tt <- 0
    call agir1s

    reti