Dual Quadrature Decode
Warning: if you clip this code into your program, look out for possible html code slipping in.
REM Dual quadrature decode example for SBC2000-074 and SBC2000-062 REM REM Author: Steven R. Wheeler REM REM Copyright 1999 Vesta Technology, Inc. REM All rights reserved. REM REM Revision history: REM Nov. 9, 1999 First version. REM This example decodes the 4 upper lines on port B (normally used REM as keypad inputs) as two pairs of quadrature inputs. We do this REM with a state machine. The two quadrature channels are on the REM keypad connector (pins 5 and 6 are channel 1, and pins 7 and 8 REM are channel 2). REM REM We will use the ON INT0 capability of VSTB to keep from missing REM any transitions (up to the maximum rate we can sustain). We will REM require four variables: the current quadrature count for each REM input pair, and an error count for each input pair. The error REM count will be incremented each time we get an illegal transition. REM This would be an indication that the signals are changing faster REM than we can handle them. REM REM The "output" for each quadrature channel is the count variable, REM which can be thought of as representing a position. This will REM be in the range -32768 to +32767. This routine does not take REM any action when the count wraps from "most positive" to "most REM negative" and vice-versa. This can be done, but will limit the REM top end of quadrature input speed. REM REM The information provided by the error counts is only how many REM transitions we think we have missed. We can't really use it to REM adjust the counts unless we know we're always incrementing or REM always decrementing. REM Because we have 4 lines we are monitoring in pairs, we will end REM up with 16 separate cases to handle. We will define a 16x16 REM constant array to tell us which case to use. REM REM This array is indexed using the previous state of the input lines REM and the current state of the input lines as the indices into the REM array. The contents of the array element tell us what actions REM must be taken. The possibilities are: REM REM 0 - do nothing REM 1 - increment the channel 1 count REM 2 - decrement the channel 1 count REM 3 - increment the channel 1 errors REM 4 - increment channel 2 count REM 5 - increment channel 2 count, increment channel 1 count REM 6 - increment channel 2 count, decrement channel 1 count REM 7 - increment channel 2 count, increment channel 1 error REM 8 - decrement channel 2 count REM 9 - decrement channel 2 count, increment channel 1 count REM 10 - decrement channel 2 count, decrement channel 1 count REM 11 - decrement channel 2 count, increment channel 1 error REM 12 - increment channel 2 error REM 13 - increment channel 2 error, increment channel 1 count REM 14 - increment channel 2 error, decrement channel 1 count REM 15 - increment both error counts DIM Transitions[16,16] AS BYTE CONSTANT = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 2, 0, 3, 1, 6, 4, 7, 5, 10, 8, 11, 9, 14, 12, 15, 13, 1, 3, 0, 2, 5, 7, 4, 6, 9, 11, 8, 10, 13, 15, 12, 14, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 8, 9, 10, 11, 0, 1, 2, 3, 12, 13, 14, 15, 4, 5, 6, 7, 10, 8, 11, 9, 2, 0, 3, 1, 14, 12, 15, 13, 6, 4, 7, 5, 9, 11, 8, 10, 1, 3, 0, 2, 13, 15, 12, 14, 5, 7, 4, 6, 11, 10, 9, 8, 3, 2, 1, 0, 15, 14, 13, 12, 7, 6, 5, 4, 4, 5, 6, 7, 12, 13, 14, 15, 0, 1, 2, 3, 8, 9, 10, 11, 6, 4, 7, 5, 14, 12, 15, 13, 2, 0, 3, 1, 10, 8, 11, 9, 5, 7, 4, 6, 13, 15, 12, 14, 1, 3, 0, 2, 9, 11, 8, 10, 7, 6, 5, 4, 15, 14, 13, 12, 3, 2, 1, 0, 11, 10, 9, 8, 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3, 14, 12, 15, 13, 10, 8, 11, 9, 6, 4, 7, 5, 2, 0, 3, 1, 13, 15, 12, 14, 9, 11, 8, 10, 5, 7, 4, 6, 1, 3, 0, 2, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ] REM Define the variables we need. GLOBAL Chan_1_Count AS INTEGER : REM Lower pair "position" value GLOBAL Chan_1_Error AS INTEGER : REM Lower pair missing transitions GLOBAL Chan_2_Count AS INTEGER : REM Upper pair "position" value GLOBAL Chan_2_Error AS INTEGER : REM Upper pair missing transitions REM This is our interrupt handler. The value passed in is a 4-bit REM quantity representing the state of the lines on the upper 4 REM bits of port B. Case 0 is not included in the SELECT statement REM because no action is required for that case. REM REM Note that we get an interrupt on each transition of each line REM in each quadrature pair. This means that the count values will REM increment 4 times during each waveform period. With no other REM processing going on, the shortest quadrature period with which REM the system will be able to keep up is about 5.5 msec on a REM revision 4 SBC2000-074. VITAL SUBROUTINE Quadrature(lines AS INTEGER) STATIC last_lines AS INTEGER SELECT Transitions[last_lines, lines] CASE 1 Chan_1_Count = Chan_1_Count + 1 CASE 2 Chan_1_Count = Chan_1_Count - 1 CASE 3 Chan_1_Error = Chan_1_Error + 1 CASE 4 Chan_2_Count = Chan_2_Count + 1 CASE 5 Chan_1_Count = Chan_1_Count + 1 Chan_2_Count = Chan_2_Count + 1 CASE 6 Chan_1_Count = Chan_1_Count - 1 Chan_2_Count = Chan_2_Count + 1 CASE 7 Chan_1_Error = Chan_1_Error + 1 Chan_2_Count = Chan_2_Count + 1 CASE 8 Chan_2_Count = Chan_2_Count - 1 CASE 9 Chan_1_Count = Chan_1_Count + 1 Chan_2_Count = Chan_2_Count - 1 CASE 10 Chan_1_Count = Chan_1_Count - 1 Chan_2_Count = Chan_2_Count - 1 CASE 11 Chan_1_Error = Chan_1_Error + 1 Chan_2_Count = Chan_2_Count - 1 CASE 12 Chan_2_Error = Chan_2_Error + 1 CASE 13 Chan_1_Count = Chan_1_Count + 1 Chan_2_Error = Chan_2_Error + 1 CASE 14 Chan_1_Count = Chan_1_Count - 1 Chan_2_Error = Chan_2_Error + 1 CASE 15 Chan_1_Error = Chan_1_Error + 1 Chan_2_Error = Chan_2_Error + 1 ENDSELECT last_lines = lines SET INT0 TO 1 END REM Upon powerup, these will be initialized to zero anyway. This just REM gives us clean counts if we're in debug mode and restarting under REM command from the IDE. Chan_1_Count = 0 Chan_1_Error = 0 Chan_2_Count = 0 Chan_2_Error = 0 REM Set up the handler for decoding the quadrature counts. ON INT0 Quadrature SET INT0 TO 1 REM Direct print output to the LCD. You DO NOT want to have your REM application doing a lot of printing to the serial ports, because REM it will severely limit the maximum quadrature rate the system REM will be able to handle without problems. PIPE PRINT LCD REM Now a simple application to give us an idea of what's going on. DO WHILE 1 LCD_Command(0x80) PRINT Chan_1_Count, " " LCD_Command(0x8A) PRINT Chan_1_Error, " " LCD_Command(0xC0) PRINT Chan_2_Count, " " LCD_Command(0xCA) PRINT Chan_2_Error, " " LOOP