' RPM.SXB ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28,OSCHS1,TURBO,OPTIONX,STACKX,BOR42 FREQ 50_000_000 ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- Sensor PIN RB.0 INPUT ' NOTE, this is made into a schmitt trigger below with ST_B 'display Segs PIN RC OUTPUT ' Segments on RC.0 - RC.7 Digs PIN RA OUTPUT ' Digit control pins (gnd) ' -----[ Constants ]------------------------------------------------------- Blank CON %00000000 ' all segments off ' -----[ Variables ]------------------------------------------------------- ' tach vars rpm VAR WORD pWidth0 VAR WORD pWidth1 VAR WORD 'loopcount VAR Byte dividendMSW VAR WORD dividendLSW VAR WORD overflow VAR BIT doneBit VAR BIT 'display vars theDig VAR Byte ' current display digit dug VAR Byte ' wish i had locals tmpW1 VAR Word tmpW2 VAR Word tmpB1 VAR Byte tmpB2 VAR Byte ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- DELAY_MS SUB 1, 2 ' delay in milliseconds SHOW_DISPLAY sub DIG FUNC 1, 2, 3 ' ========================================================================= PROGRAM Start ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: ST_B = %00000001 ' make RB.1 schmitt triggered Digs = %0000 ' all gnds off segs = %10000000 'loopcount = 0 DO 'loopcount = loopcount+1 ' Measure pulse low time PULSIN Sensor, 0, pWidth0 ' Measure pulse high time PULSIN Sensor, 1, pWidth1 ' Find total pulse time (high + low) pWidth0 = pWidth0 + pWidth1 ' Set dividend to 6,000,000 ($5B8D80) this many 10u/seconds in a minute dividendMSW = $005B dividendLSW = $8D80 ' Perform 32 bit division (rpm = dividend / pWidth0) rpm = 1 overflow = 0 DO doneBit = rpm.15 rpm = rpm << 1 IF overflow = 1 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ELSE IF dividendMSW >= pWidth0 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ENDIF ENDIF overflow = dividendMSW.15 dividendMSW = dividendMSW << 1 dividendMSW.0 = dividendLSW.15 dividendLSW = dividendLSW << 1 LOOP UNTIL doneBit = 1 rpm = rpm << 1 rpm.0 = overflow IF dividendMSW >= pWidth0 THEN rpm.0 = 1 ENDIF ' rpm now holds the correct value 'BREAK WATCH rpm WATCH pWidth0 'WATCH loopcount watch Segs, 8, UBIN watch Digs, 4, UBIN watch dug, 8, UDEC SHOW_DISPLAY 'DELAY_MS 1000 LOOP END ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- ' Use: DELAY_MS msecs DELAY_MS: IF __PARAMCNT = 1 THEN tmpW1 = __PARAM1 ' save byte value ELSE tmpW1 = __WPARAM12 ' save word value ENDIF PAUSE tmpW1 RETURN SHOW_DISPLAY: 'Reminder, i'm calling DIG and DELAY in here, so tmpW1-2 and tmpB1-2 are off limits! pwidth0=10 'how many times to show rpm to display. need to add banking, recycling this var for now pwidth0= pwidth0 * 4 ' <<2 is "* 4" number has to be a multiple of 4 since we need to loop 4 times to get 4 digits DO pWidth0 = pWidth0 - 1 READ DigSel + theDig, Digs ' select digit column number (theDig) from Digs 'DIG COMMAND: "value DIG #" (where number is the digit column 0-3) dug = DIG rpm, theDig ' find out what digit in rpm we are ready to draw READ Digit0 + dug, Segs ' move digit drawing DATA pattern to segs pins inc theDig ' Update, theDig = theDig // 4 ' ,digit column pointer DELAY_MS 5 'how long to light each singular digit Segs = Blank 'clear the gnds or we will light up the next digit column before we are ready LOOP UNTIL pWidth0 <= 0 RETURN ' Use: result = DIG value, position ' -- "value" is byte or word ' -- "position" is byte, 0 to 4 DIG: IF __PARAMCNT = 2 THEN tmpW1 = __PARAM1 tmpB1 = __PARAM2 ELSE tmpW1 = __WPARAM12 tmpB1 = __PARAM3 ENDIF tmpB2 = 0 IF tmpB1 < 4 THEN LOOKUP tmpB1, 1, 10, 100, 1000, tmpW2 tmpW1 = tmpW1 / tmpW2 tmpW1 = tmpW1 // 10 tmpB2 = tmpW1_LSB ENDIF RETURN tmpB2 ' -----[ EEPROM Data ]----------------------------------------------------- ' %.GFEDCBA Digit0: DATA %00111111 Digit1: DATA %00000110 Digit2: DATA %01011011 Digit3: DATA %01001111 Digit4: DATA %01100110 Digit5: DATA %01101101 Digit6: DATA %01111101 Digit7: DATA %00000111 Digit8: DATA %01111111 Digit9: DATA %01100111 DigSel: DATA %1110 ' digit 0 active DATA %1101 ' digit 1 active DATA %1011 ' digit 2 active DATA %0111 ' digit 3 active