' MeterStampBox.bs2 ' Box with Meter and speaker ' John Saunders 3/2/2009 ' {$STAMP BS2} ' {$PBASIC 2.5} 'Stamp Ports DS1302CE PIN 0 'Output: DS1302 Chip Enable DS1302IO PIN 1 'Bi-directional:DS1302 Data DIO1 PIN 2 'Input or Output:Digital I/O #1, D-25 pin 19 DIO2 PIN 3 'Input or Output:Digital I/O #2, D-25 pin 20 UPSW PIN 4 'Input: UP Switch DNSW PIN 5 'Input: Down Switch SDOut PIN 6 'Output to SD Interface SDIn PIN 7 'Input from SD Interface SelPort VAR OUTC 'Selector for 138 and 259 chips, pins 8,9,10 En138 PIN 11 'Output:High pulse to enable the 138 CLK PIN 12 'Output:Clocks all InPort PIN 13 'Input:166 and ADC Data En259 PIN 14 'Output:259 gate OutPort PIN 15 'Output:Display RS,74HC164 & 166 serial in,259 D 'Initialization Dispinitlen CON 3 DispInitAddr CON 0 DispInitData DATA $38,$0C,$01,$06 'Need $38(2-line) and use cmd $C0 for second 8 char pos DateInitAddr CON 4 SetDateTime DATA(8) 'Time and analog parameters 'The time values are:Seconds,Minutes,Hours,Date,Month,Year in 0 - 5 'The current is in 6 and 7; the voltage in 8 & 9 TimeDate VAR Byte(10) 'Display parameters Char VAR Byte 'General use DECdata VAR Word 'General use UpperByte VAR DECData.HIGHBYTE LowerByte VAR DECData.LOWBYTE SignBit VAR DECdata.BIT15 div VAR Byte 'dividend used in writing numbers rem VAR Word 'remainder used in writing multiple-digit numbers DispMode VAR Nib 'Controls the way a value is to be displayed, bits 0, 1 = no of digits - 1 DPLoc VAR DispMode.BIT2 '0=1 digit after DP, 1 = 2 DPOnOff VAR DispMode.BIT3 '0 = no decimal point, 1 = DP DSAddr VAR Byte 'DS1302 register address DSData VAR Byte 'DS1302 data is in BCD format Tens VAR DSData.HIGHNIB Units VAR DSData.LOWNIB DigIn1 VAR DSData.LOWNIB.BIT3 DigIn2 VAR DSData.HIGHNIB.BIT0 DigIn3 VAR DSData.HIGHNIB.BIT1 DigIn4 VAR DSData.HIGHNIB.BIT2 DigIn5 VAR DSData.HIGHNIB.BIT3 NoPrompt VAR Bit 'SD interface did not give a prompt BallFlag VAR Bit 'One selects White 'Control variables and External Digital Inputs IOdata VAR Byte 'Data to be either input or output Mode VAR Nib 'Bits 0-2 are the mode switch encoded OldMode VAR Nib Iter VAR Nib 'for loop variable '138 select constants DispEn CON 0 SHLD CON 9 'Also sets gate high since 166 has synchronous load ADCICE CON 2 ADCVCE CON 3 Chime CON 4 CLR259 CON 5 Beep CON 6 '259 select constants Black CON 0 White CON 1 PSEn CON 2 DigOutEn CON 3 DigAOut CON 7 DigBOut CON 5 DIGCOut CON 4 '1302 Parameters WRProtData CON 0 WRProtAddr CON $8E OSCEnAddr CON $80 DSRangeAddr CON $D0 TCHData CON %10100101 TCHAddr CON $90 'Rogue Secure Digital Interface parameters DoneFlag VAR Bit 'Recording has been completed FormatFlag VAR Nib 'Add after the display or record: 0=none,1=space,2=slash,3=colon 'Analog parameters voltoffset CON 4 'Correction for voltage amplifier offset, in counts ampoffset CON 4 'Correction for current amplifier offset, in counts Range VAR Nib 'Index into AmpParams for the selected shunt MaxRange CON 8 'Display value,multiplier,divider,Decimal Display mode AmpParams DATA 1,4,4,$F,2,4,2,$F,3,14,4,$F,4,4,1,$F,5,24,4,$F,6,14,2,$F,10,4,4,$B,12,2,2,$B,20,4,2,$B Start: DIRS = %1101111101000001 Selport = CLR259 LOW En138 LOW En259 PULSOUT En138,10 'Clear the 259 LOW DS1302CE DoneFlag = 1 LOW En138 HIGH En259 DECData = 0 GOSUB InitDisp SelPort = PSen Outport = 1 PULSOUT En259, 10 Outport = 0 SelPort = DigOutEn Outport = 1 PULSOUT En259, 10 Outport = 0 DsAddr = DsRangeAddr + 1 'Restore previous session range GOSUB DS1302OUT Range = Units IF Range > MaxRange THEN range = MaxRange ENDIF Main: 'Main loop GOSUB GetInputData GOSUB GetTimeDate 'Check IF time to record IF TimeDate(0) > $05 THEN DoneFlag = 0 'Permits a new recording ELSEIF (TimeDate(0) < $03) AND (DoneFlag = 0) THEN GOSUB Record ENDIF ' Erase and Return Cursor to left if mode changes, else return cursor Char = 2 IF Mode <> OldMode THEN GOSUB SoundBeep Char = 1 ENDIF GOSUB DispCmd OldMode = Mode SELECT Mode CASE 0 Char = $80 GOSUB DispCmd GOSUB DispAmp Char = $C2 GOSUB DispCmd GOSUB DispVolt CASE 1 Char = $80 GOSUB DispCmd GOSUB Dispdate CASE ELSE Char = $80 GOSUB DispCmd GOSUB DispTime ENDSELECT GOTO main STOP 'subroutines: 'subroutines for Samsung KS0066 LCD display controllers: InitDisp: FOR Iter = 0 TO DispInitLen READ DispInitAddr + Iter,Char GOSUB DispCmd PAUSE 200 NEXT RETURN DispCmd: 'puts a command (IoData) in OutputData into the display SHIFTOUT Outport,CLK,1,[Char\8] 'clocks the instruction into the shift register, MSB first LOW outport 'instruction function is low, IOData does double duty SelPort = DispEn PULSOUT En138,10 'clocks the instruction and the function into the display LOW En138 PAUSE 1 RETURN DispChar: 'puts one character onto the display SHIFTOUT Outport,CLK,1,[Char\8] 'clocks the character into the shift register HIGH outport 'data function is high SelPort = DispEn PULSOUT En138,10 'clocks the instruction and the character into the display LOW En138 RETURN DispDec: 'Displays DECData at current cursor position in Digital IF DispMode = 0 THEN OneDigit IF DispMode = 1 THEN TwoDigit IF DispMode = 2 THEN ThreeDigit ' Only 4-digit can have decimal points div = DECData/1000 rem = DECData//1000 Char = div + "0" GOSUB DispChar DECData = rem ThreeDigit: div = DECData/100 rem = DECData//100 Char = div + "0" GOSUB DispChar IF Dispmode = $F THEN Char = "." GOSUB DispChar ENDIF DecData = rem TwoDigit: div = DECData/10 rem = DECData//10 Char = div + "0" GOSUB DispChar IF Dispmode = $B THEN Char = "." GOSUB DispChar ENDIF DECData = rem OneDigit: Char = DECdata + "0" GOSUB DispChar RETURN DispDS1302: 'Displays the contents of a BCD array DSData = TimeDate(Iter) Char = Tens + "0" 'Converts BCD to 2 ascii GOSUB DispChar Char = Units + "0" GOSUB DispChar SELECT FormatFlag CASE 1 Char = " " CASE 2 Char = "/" CASE 3 Char = ":" CASE ELSE Char = "," ENDSELECT IF Char <> "," THEN GOSUB DispChar ENDIF RETURN DS1302IN: 'Put the byte in DSData into the DsAddr location HIGH DS1302CE SHIFTOUT DS1302IO,CLK,0,[DSAddr\8] SHIFTOUT DS1302IO,CLK,0,[DSData\8] LOW DS1302CE RETURN DS1302OUT: 'Read the contents of DSAddr into DsData HIGH DS1302CE SHIFTOUT DS1302IO,CLK,0,[DSAddr\8] SHIFTIN DS1302IO,CLK,1,[DSdata\8] LOW DS1302CE RETURN GetInputData: 'Rotary Switch and external inputs SelPort = SHLD 'Selects the 74LS166 output of the 74HCT138 HIGH En138 'Enable Load Mode PULSOUT CLK,10 'The 74LS166 uses a synchronous load LOW En138 'Shift mode SHIFTIN InPort,CLK,0,[IOdata\8] 'Shift inputs from the 166 shift register, MSB first Mode = IOdata & $07 RETURN GetTimeDate: 'Reads all of the time and date values ito the byte array FOR Iter = 0 TO 4 'Seconds,Minutes,Hours,Date,Month DSAddr = $81 + (2*Iter) GOSUB DS1302OUT TimeDate(Iter) = DSData NEXT DSAddr = $8D 'Year (day of week NOT READ out) ' GOSUB DS1302OUT TimeDate(5) = DSData LOW DS1302CE RETURN Record: 'Writes the time and date and the analog values into the SD chip SEROUT SDOut,84,2,["S 1 8",CR] '80 ms timeout for missing bytes SERIN SDIn,84,1000,closerecord,[Char] 'Wait for the ">" prompt SEROUT SDOut,84,["O 1 A /02B21.CSV",CR] 'Start with a "/",names need 8.3 format, alpha-numeric only SERIN SDIn,84,1000,closerecord,[Char] 'Wait for the ">" prompt GOSUB DispChar FormatFlag = 2 '"/" Iter = 4 'Month GOSUB WriteSD Iter = 3 'Date GOSUB WriteSD FormatFlag = 0 '"," Iter = 5 'Year GOSUB WriteSD FormatFlag = 3 '":" Iter = 2 'Hour GOSUB WriteSD Iter = 1 'Minute GOSUB WriteSD FormatFlag = 0 '"," Iter = 0 'Second GOSUB WriteSD LowerByte = TimeDate(6) UpperByte = TimeDate(7) SEROUT SDOut,84,["W 1 5",CR,DEC4 Decdata,","] SERIN SDIn,84,1000,closerecord,[Char] 'Wait for the ">" prompt LowerByte = TimeDate(8) UpperByte = TimeDate(9) SEROUT SDOut,84,["W 1 6",CR,DEC4 Decdata,CR,LF] SERIN SDIn,84,1000,closerecord,[Char] 'Wait for the ">" prompt NoPrompt = 0 GOSUB SoundBeep GOTO RecOK closerecord: NoPrompt = 1 RecOK: SEROUT SDOut,84,["C 1",CR] DoneFlag = 1 RETURN WriteSD: 'Gets the byte designated by Iter in the TimeDate and writes it to the SD chip DSData = TimeDate(Iter) 'Get the BCD byte selected by iter UpperByte = Tens + "0" 'Convert the 2 nibbles into 2 ascii in DECdata as scratch LowerByte = Units + "0" SELECT FormatFlag CASE 1 Char = " " CASE 2 Char = "/" CASE 3 Char = ":" CASE ELSE Char = "," ENDSELECT SEROUT SDOut,84,["W 1 3",CR,UpperByte,LowerByte,Char] 'Write all at once SERIN SDIn,84,1000,closewrite,[Char] 'Wait for the ">" prompt closewrite: RETURN DispDate: FormatFlag = 2 Iter = 4 'Month GOSUB DispDS1302 Iter = 3 'Date GOSUB DispDS1302 Iter = 5 'Year FormatFlag = 0 GOSUB DispDS1302 RETURN DispTime: FormatFlag = 3 Iter = 2 'Hour GOSUB DispDS1302 Iter = 1 'Minute GOSUB DispDS1302 FormatFlag = 0 Iter = 0 'Second GOSUB DispDS1302 RETURN SoundChime: Selport = Chime PULSOUT En138, 30 RETURN MoveBall: SelPort = BallFlag HIGH OutPort PULSOUT En259, 10 PAUSE 10 LOW Outport PULSOUT En259, 10 RETURN SoundBeep: SelPort = Beep FREQOUT En138,15,1000 LOW En138 RETURN dispamp: DsAddr = DsRangeAddr IF (UPSW = 0) AND (Range < MaxRange) THEN Range = Range + 1 PAUSE 1000 DsData = Range 'Save this value in the DS1302 GOSUB DS1302IN Range = Units ENDIF IF (DNSW = 0) AND (Range > 0) THEN Range = Range - 1 PAUSE 1000 DsData = Range 'Save this value in the DS1302 GOSUB DS1302IN ENDIF READ AmpParams + (4*Range + 1),Div SelPort = ADCICE DecData = 0 FOR Char = 0 TO Div HIGH En138 rem = 0 SHIFTIN INPort,CLK,MSBPRE,[rem\10] LOW En138 Decdata = rem + Decdata - ampoffset NEXT IF SignBit = 1 THEN DecData = 0 ENDIF READ AmpParams + (4*range + 2),Div Decdata = Decdata >> Div Timedate(6) = UpperByte 'Save the current value in unused values of the array Timedate(7) = LowerByte READ AmpParams + (4*range + 3),DispMode GOSUB DispDec Char = " " GOSUB DispChar READ AmpParams + (4*range),DecData Dispmode = 1 GOSUB DispDec RETURN dispvolt: SelPort = ADCVCE DecData = 0 FOR Iter = 0 TO 1 HIGH En138 rem = 0 SHIFTIN INPort,CLK,MSBPRE,[rem\10] LOW En138 Decdata = rem + Decdata - voltoffset NEXT IF SignBit = 1 THEN DecData = 0 ENDIF Timedate(8) = UpperByte TimeDate(9) = LowerByte DispMode = $F GOSUB DispDec RETURN