2015-03-21 1 views
5

J'essaie de créer un délai logiciel. Voici un exemple de programme de ce que je fais:Z80 Software Delay

Address Data Opcode Comment  
    1800  06 LD, B Load register B with fix value 
    1801  “ “   Fixed value 
    1802  05 DEC, B Decrement value in register B 
    1803  C2 JP cc Jump to 1802 if value is not 0 
    1804  02 -  Address XX 
    1805  18 -  Address XX 

Ma question est de savoir comment puis-je calculer la valeur fixe nécessaire pour charger dans le registre B afin que le processus de décrémenter la valeur jusqu'à ce que 0 prend 2 secondes?

Dans mon manuel, le temps imparti pour exécuter les instructions est basé sur un processeur 4MHz mais le processeur Z80 que j'utilise a une vitesse de 1,8 MHz. Une idée de comment je peux calculer ça? Merci. PS est ici le décrément (DEC) et saut (JP cc) les instructions du manuel:

Instruction M Cycles T states 4 MHz E.t 
DEC r    1   4   1.00 
JP cc    3  10 (4,3,3) 2.50 

Répondre

3

Si par 1.8MHz vous dire exactement 1.800.000 Hz, puis d'obtenir un délai de 2 secondes, vous aurez besoin de retarder pour 3 600 000 Etats-T. Votre boucle de retard actuelle prend 14 états T par itération, ce qui signifie que votre valeur initiale pour B doit être 3600000/14 = 257143, ce qui ne tient évidemment pas dans un octet.

Le plus grand nombre d'itérations que vous pourriez spécifier avec un registre de 8 bits est 256, et pour atteindre 3 600 000 états T avec 256 itérations, chaque itération devrait prendre 14 062 états T. C'est un grand corps de boucle. Si nous utilisons un compteur 16 bits, les choses deviennent un peu plus gérables. À 65.536 itérations, nous avons seulement besoin de 55 états-T par itération pour atteindre un total de 3.600.000 états-T. Ci-dessous un exemple de ce qui pourrait ressembler à:

; Clobbers A, B and C 
    ld  bc,#0 
1$: 
    bit  #0,a ; 8 
    bit  #0,a ; 8 
    bit  #0,a ; 8 
    and  a,#255 ; 7 
    dec  bc  ; 6 
    ld  a,c  ; 4 
    or  a,b  ; 4 
    jp  nz,1$ ; 10, total = 55 states/iteration 
    ; 65536 iterations * 55 states = 3604480 states = 2.00248 seconds 
+0

oups. Ca fait longtemps que je ne l'ai pas fait. –

2

Je suis un peu d'un monstre d'optimisation, donc voici mon go en utilisant la syntaxe avec laquelle je suis plus familier (de l'assembleur TASM et similaires) :

Instruction opcode timing ld bc,$EE9D ;01EE9D 10cc ex (sp),hl ;E3 19*(256C+B) ex (sp),hl ;E3 19*(256C+B) ex (sp),hl ;E3 19*(256C+B) ex (sp),hl ;E3 19*(256C+B) djnz $ ;10FA 13cc*(256C+B) - 5*C dec c ;0D 4*C jr nz,$-3 ;20F7 12*C-5

Ce code est de 12 octets et 3600002 cycles d'horloge.

EDIT: Il semble qu'une partie de ma réponse est partie! Pour mieux répondre à votre question, votre Z80 peut traiter 1800 000 cycles d'horloge en une seconde, donc vous en aurez besoin deux fois plus (3600000). Si vous ajoutez les horaires donnés dans mon code, vous obtenez:

= 10 + (256C + B) (19 * 4 + 13) + 4C -5C + 12C-5

= 5 + (256C + B) + 89 11C

= 5 + 22795C + 89B

Ainsi, le temps de code est largement dépendante de C. 3600000/22795 est d'environ 157, alors on initialise C avec 157 (0x9D). En rebranchant cela, nous obtenons que B soit approximativement 237,9775, donc nous arrondissons cela à 238 (0xEE). Brancher ceux-ci obtient notre timing final de 3600002cc ou environ 2.000001 secondes. Cela suppose que le processeur fonctionne exactement à 1,8 MHz, ce qui est très improbable.

De même, si vous pouvez utiliser des interruptions, déterminez approximativement combien de fois il se déclenche par seconde et utilisez une boucle comme halt \ djnz $-1. Cela économise beaucoup plus en termes de consommation d'énergie.

+0

"Cela économise beaucoup plus en termes de consommation d'énergie". Vous ne savez pas si cette instruction est vraie car HALT répète les opérations NOP jusqu'à ce qu'une interruption masquable se produise. Je ne pensais pas que des codes d'opération différents provoquaient une consommation d'énergie significativement plus ou moins importante que d'autres. J'ai peut-être tort cependant. –