( Timer operation and status comments ( CTRL ( BASE + 6 ( 000 ( COUNT MODE NO COUNT ( 001 ( COUNT RISING EDGES OF PRIMARY SOURCE ( 010 ( COUNT RISING AND FALLING EDGES OF PRIMARY SOURCE ( 011 ( COUNT RISING EDGES OF PRIMARY SOURCE WHILE SEC. HIGH ( 100 ( QUADRATURE RISING EDGES OF PRIMARY AND SEC. SOURCE ( 101 ( COUNT PRIMARY SOURCE RISING EDGES, SEC. SPECS. DIRECTION ( 110 ( EDGE OF SEC. SOURCE TRIGGERS PRIMARY COUNT TILL COMPARE ( 111 ( CASCASE COUNTER MODE UP/DOWN ( 0000 ( Counter #0 input pin ( 0001 ( Counter #1 input pin ( 0010 ( Counter #2 input pin ( 0011 ( Counter #3 input pin ( 0100 ( Counter #0 output ( 0101 ( Counter #1 output ( 0110 ( Counter #2 output ( 0111 ( Counter #3 output ( 1000 ( PRIMARY COUNT SOURCE IP/1 ( 1001 ( PRIMARY COUNT SOURCE IP/2 ( 1010 ( PRIMARY COUNT SOURCE IP/4 ( 1011 ( PRIMARY COUNT SOURCE IP/8 ( 1100 ( PRIMARY COUNT SOURCE IP/16 ( 1101 ( PRIMARY COUNT SOURCE IP/32 ( 1110 ( PRIMARY COUNT SOURCE IP/64 ( 1111 ( PRIMARY COUNT SOURCE IP/128 ( 00 ( SECONDARY COUNT Counter # 0 input ( 01 ( SECONDARY COUNT Counter # 1 input ( 10 ( SECONDARY COUNT Counter # 2 input ( 11 ( SECONDARY COUNT Counter # 3 input ( 0 ( COUNT ONCE - 0 REPEATEDLY ( 1 ( COUNT ONCE - 1 ONCE AND STOP ( 0 ( COUNT LENGTH ROLL OVER ( 1 ( COUNT LENGTH COUNT UNTIL COMPARE AND REINITIALIZE ( 0 ( DIR COUNT UP ( 1 ( DIR COUNT DN ( 0 ( COINIT NO FORCE BY OTHER CHANNELS ( 1 ( COINIT FORCE BY OTHER COUNTER WHEN ACTIVE COMPARE ( 000 ( Active while counter is active, OUPUT MODE ( 001 ( CLEAR OFLAG OUTPUT ON SUCCESSFUL COMPARE ( 010 ( SET OFLAG OUTPUT ON SUCCESSFUL COMPARE ( 011 ( TOGGLE OFLAG OUTPUT ON SUCCESSFUL COMPARE ( 100 ( TOGGLE OFLAG USING ALTERNATING COMPARE REG ( 101 ( SET ON COMPARE, CLEAR ON SEC. SOURCE INPUT EDGE ( 110 ( SET ON COMPARE, CLEAR ON COUNTER ROLLOVER ( 111 ( ENABLE GATED CLOCK OUTPUT WHILE COUNTER IS ACTIVE ( STATUS ( BASE + 7 ( 00 TCF, TCFIE ( 00 TOF, TOFIE ( 00 IEF, IEFIE ( 0 IPS ( 0 INPUT ( 00 CAPTURE DISABLED ( 01 CAPTURE REGISTER OPERATION CAP ON RISING EDGE IF IPS=0 ( 01 CAPTURE REGISTER OPERATION CAP ON FALLING EDGE IF IPS=1 ( 10 CAPTURE REGISTER OPERATION CAP ON FALLING EDGE IF IPS=0 ( 10 CAPTURE REGISTER OPERATION CAP ON RISING EDGE IF IPS=1 ( 11 CAPTURE REGISTER OPERATION CAP ON BOTH EDGE ( 0 MASTER ( 0 EEOF ( 0 VAL ( 0 FORCE ( 0 OPS ( 0 OEN ( Quadrature Generator ( The idea here is to take a variable containing a desired Pulses Per Second ( and generate a quadrature output that produces those counts ( ( I originally tried to do this with PWM, but it was hard to get the 90 degree ( phasing to work out. Then I did it with individual port lines. While not at ( 90 degrees, at least I generated workably overlaping Phase A and B signals. ( The idea seemed to be to do the generation with two timers, each timing out ( and toggling an output in the middle of the other timers time span. ( Seems fine for a steady state after the thing was rolling. But for a dynamic ( changing of two timers in synchronization while still running..., ( the idea got murky. ( Then I came up with the idea: one timer that times out four times as often. ( get to the timer each time before it times out ( change the output mode to toggle a different pin. ( but you don't get to assign output pins, so that wouldn't work. ( While interrupts could be used at time out to do a software toggle of pins ( the latency would determine how accurately the phases changed. ( however, this wouldn't be fine enough for a "perfect" wave. ( Instead, using four timers could create perfect form waves, to 25ns anyway ( One timer is needed to do prescaling to bring the quadrature down to ( reasonable rates, say milliseconds. Then another timer is set to count how ( many of these ticks pass per phase. Two other timers count this output. ( These two timers have repetitive counts to 2, and are set off by one count. ( They toggle their outputs each time out. ( So, here's my current thought. ( SCRUB ( CLEARS THE MEMORY HEX ( CTRL ( 001 ( COUNT RISING EDGES OF PRIMARY SOURCE ( 1000 ( PRIMARY COUNT SOURCE IP/1 ( XX ( SECONDARY COUNT Counter # 3 input ( 0 ( COUNT ONCE - 0 REPEATEDLY ( 1 ( COUNT LENGTH COUNT UNTIL COMPARE AND REINITIALIZE ( 1 ( DIR COUNT DN ( 0 ( COINIT NO FORCE BY OTHER CHANNELS ( 011 ( TOGGLE OFLAG OUTPUT ON SUCCESSFUL COMPARE ( 0011000110110011 ( 0011 0001 1011 0011 31B3 w/output toggle ( STATUS ( 00 TCF, TCFIE ( 00 TOF, TOFIE ( 00 IEF, IEFIE ( 0 IPS ( 0 INPUT ( 00 CAPTURE DISABLED ( 0 MASTER ( 1 EEOF ( 0 VAL ( 0 FORCE ( 0 OPS ( 1 OEN ( 0000000000000001 ( TMRB3 MAKE SLOW PRESCALER 0000 D3E ! ( CTRL TMRB1 STOP TIMER WHILE INIT FFFF D38 ! ( CMP1 FOR OVERFLOW 0000 D39 ! ( CMP2 FOR UNDERFLOW 9C40 D3B ! ( LOAD ON UNDERFLOW ( 40,000 gives 1ms toggles .2ms period 0000 D3D ! ( COUNTER 31B3 D3E ! ( CTRL TMRB3 COUNT ON 0001 D3F ! ( STATUS ( CTRL ( 001 ( COUNT RISING EDGES OF PRIMARY SOURCE ( 0111 ( Counter #3 output ( XX ( SECONDARY COUNT Counter # 2 input ( 0 ( COUNT ONCE - 0 REPEATEDLY ( 1 ( COUNT LENGTH COUNT UNTIL COMPARE AND REINITIALIZE ( 1 ( DIR COUNT DN ( 0 ( COINIT NO FORCE BY OTHER CHANNELS ( 011 ( TOGGLE OFLAG OUTPUT ON SUCCESSFUL COMPARE ( 0010111100110011 ( 0010 1111 0011 0011 2F33 w/output toggle ( STATUS ( 00 TCF, TCFIE ( 00 TOF, TOFIE ( 00 IEF, IEFIE ( 0 IPS ( 0 INPUT ( 00 CAPTURE DISABLED ( 0 MASTER ( 0 EEOF ( 0 VAL ( 0 FORCE ( 0 OPS ( 1 OEN ( 0000000000000001 ( TMRB2 MAKE PERIODIC COUNTER 0000 D36 ! ( CTRL TMRB1 STOP TIMER WHILE INIT FFFF D30 ! ( CMP1 FOR OVERFLOW 0000 D31 ! ( CMP2 FOR UNDERFLOW 0064 D33 ! ( LOAD ON UNDERFLOW ( 100 gives .2s toggless .4s period 0000 D35 ! ( COUNTER 2F33 D36 ! ( CTRL TMRB2 0001 D37 ! ( STATUS ( CTRL ( 001 ( COUNT RISING EDGES OF PRIMARY SOURCE ( 0110 ( Counter #2 output ( XX ( SECONDARY COUNT Counter # 0 input ( 0 ( COUNT ONCE - 0 REPEATEDLY ( 1 ( COUNT LENGTH COUNT UNTIL COMPARE AND REINITIALIZE ( 1 ( DIR COUNT DN ( 0 ( COINIT NO FORCE BY OTHER CHANNELS ( 011 ( TOGGLE OFLAG OUTPUT ON SUCCESSFUL COMPARE ( 0010110000110011 ( 0010 1100 0011 0011 2C33 w/output toggle ( STATUS ( 00 TCF, TCFIE ( 00 TOF, TOFIE ( 00 IEF, IEFIE ( x IPS ( 0 INPUT ( 00 CAPTURE DISABLED ( 0 MASTER ( 1 EEOF ( 0 VAL ( 0 FORCE ( 0 OPS ( 1 OEN ( 0000000000000001 ( 0000001000000001 ( QUAD CH GEN MADE OUT OF TMRB0/1 0000 D26 ! ( CTRL TMRB0 STOP TIMER WHILE INIT FFFF D20 ! ( CMP1 FOR OVERFLOW 0000 D21 ! ( CMP2 FOR UNDERFLOW 0001 D23 ! ( CMP2 FOR UNDERFLOW 0001 D25 ! ( COUNTER 2C33 D26 ! ( CTRL TMRB0 0001 D27 ! ( STATUS 0000 D2E ! ( CTRL TMRB1 STOP TIMER WHILE INIT FFFF D28 ! ( CMP1 FOR OVERFLOW 0000 D29 ! ( CMP2 FOR UNDERFLOW 0001 D2B ! ( CMP2 FOR UNDERFLOW 0001 D2D ! ( COUNTER 2C33 D2E ! ( CTRL TMRB1 0201 D2F ! ( STATUS SCRUB HEX : QUAD-GEN-INIT 0000 D26 ! ( CTRL TMRB0 STOP TIMER WHILE INIT 0000 D2E ! ( CTRL TMRB1 STOP TIMER WHILE INIT 0000 D36 ! ( CTRL TMRB2 STOP TIMER WHILE INIT 0000 D3E ! ( CTRL TMRB3 STOP TIMER WHILE INIT 0.0 E57 2! ( CLEAR QUAD REG FFFF D38 ! ( CMP1 FOR OVERFLOW 0000 D39 ! ( CMP2 FOR UNDERFLOW 9C3F D3B ! ( LOAD ON UNDERFLOW ( 40,000 1- gives 1ms toggles .2ms period 0000 D3D ! ( COUNTER 31B3 D3E ! ( CTRL TMRB3 COUNT ON 0001 D3F ! ( STATUS FFFF D30 ! ( CMP1 FOR OVERFLOW 0000 D31 ! ( CMP2 FOR UNDERFLOW 0063 D33 ! ( LOAD ON UNDERFLOW ( 100 1- gives .2s toggless .4s period 0000 D35 ! ( COUNTER 2F33 D36 ! ( CTRL TMRB2 0001 D37 ! ( STATUS FFFF D28 ! ( CMP1 FOR OVERFLOW 0000 D29 ! ( CMP2 FOR UNDERFLOW 0001 D2B ! ( CMP2 FOR UNDERFLOW 0001 D2D ! ( COUNTER ( 2C33 D2E ! ( CTRL TMRB1 0001 D2F ! ( STATUS FFFF D20 ! ( CMP1 FOR OVERFLOW 0000 D21 ! ( CMP2 FOR UNDERFLOW 0001 D23 ! ( CMP2 FOR UNDERFLOW 0000 D25 ! ( COUNTER ( 2C33 D26 ! ( CTRL TMRB0 0001 D27 ! ( STATUS ( START THEM AT THE SAME TIME 2C33 D2E ! ( CTRL TMRB1 2C33 D26 ! ( CTRL TMRB0 ; EEWORD ( FOLLOW GIVES A VISUAL INDICATION, ( BUT IT SHOULD ONLY BE TRUSTED AT ( LOW OUTPUT RATES LESS THAN 125 Hz ( BECAUSE IT RUNS ONLY 1000 TIMES A SECOND ( AND CAN GET INTO SYNCH'D ALIASING MODES ( WHICH LOOK ERRONEOUS FOR HIGHER FREQS. ( FOLLOW IS ONLY A TOOL AND CAN BE OMITTED ( AS CAN IT'S STARTUP LINE "EVERY C...." LINE : FOLLOW E5D @ 0080 AND REDLED SET ( QUAD DECODER INPUT PH A E5D @ 0040 AND YELLED SET ( QUAD DECODER INPUT PH B E5D @ 0020 AND GRNLED SET ( QUAD DECODER INPUT PH IN ; EEWORD HEX : STARTUP QUAD-GEN-INIT EVERY C350 A / CYCLES SCHEDULE-RUNS FOLLOW ; EEWORD D3B CONSTANT PRESCALER EEWORD ( DEFAULT CONTENTS 94C0 40,000 D33 CONSTANT COUNTER EEWORD ( DEFAULT CONTENTS 64 100 ( USE ( 0 PRESCALER ! ( 0 COUNTER ! ( GIVES 2.5 MHz OUTPUT ( DECIMAL ( 40000 1- PRESCALER ! ( 50000 1- COUNTER ! ( GIVES .0012 Hz OUTPUT DECIMAL : CYC/SEC 40.E6 PRESCALER @ 1+ 0 D>F F/ COUNTER @ 1+ 0 D>F F/ 16 S>F F/ ( F/ F. ." Hz" ; EEWORD : DUR. ( HALF CYCLE TIME .5E0 CYC/SEC F/ F. ." SEC/H.C." ; EEWORD : FREQ. CYC/SEC F. ." Hz" ; EEWORD HEX : QUAD. E57 2@ D. ; EEWORD HEX : REV D2D @ DUP 1 XOR D2D ! D25 ! ; EEWORD ( HEX 7C00 AUTOSTART STARTUP ( SAVE-RAM