' SetTimeDate.bs2 ' Used because lack of program space to keep in 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 parameters TimeDate VAR Byte(9) 'Seconds,Minutes,Hours,Date,Month,Weekday,Year,Write Protect,spare 'Display parameters DECdata VAR Word 'Analog value 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 Char VAR Byte 'For display of one character OldUp VAR Bit 'Previous value of Up switch OldDown VAR Bit 'Previous value of Down switch NoPrompt VAR Bit 'SD interface did not give a prompt BallFlag VAR Bit 'One selects White UPAction VAR Bit 'The UP switch was pressed DNAction VAR Bit 'The UP switch was pressed '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 BurstRD CON $BF '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 amplifier offset ampoffset CON 4 Range VAR Nib 'Index into AmpParams for the selected shunt '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 GOSUB DS1302OUT Range = Units IF Range > 8 THEN range = 8 ENDIF Main: 'Main loop GOSUB GetInputData GOSUB GetTimeDate ' 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 GOSUB Dispdate CASE 5 GOSUB DispSetTimedate IF DNSW = 0 THEN GOSUB ReadTimeDate 'Read the SETTIME.TXT & SETDATE.TXT files on the SD, 'process the values to BCD and store in 1302RAM ELSEIF UPSW = 0 THEN GOSUB InitDS ENDIF CASE ELSE GOSUB DispTime ENDSELECT OldUp = UPSW OldDown = DNSW 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: 'Both Displays and records DSData = TimeDate(Iter) Char = Tens + "0" 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: HIGH DS1302CE SHIFTOUT DS1302IO,CLK,0,[DSAddr\8] SHIFTOUT DS1302IO,CLK,0,[DSData\8] LOW DS1302CE RETURN DS1302OUT: 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 'Synchronous Load HIGH En138 'Enable Load PULSOUT CLK,10 LOW En138 'Shift mode SHIFTIN InPort,CLK,0,[IOdata\8] 'Shift inputs from the shift register, MSB first Mode = IOdata & $07 RETURN GetTimeDate: HIGH DS1302CE DSAddr = BurstRD SHIFTOUT DS1302IO,CLK,0,[DSAddr\8] FOR Iter = 0 TO 7 SHIFTIN DS1302IO,CLK,1,[TimeDate(Iter)\8] NEXT LOW DS1302CE RETURN DispDate: FormatFlag = 2 Iter = 4 'Month GOSUB DispDS1302 Iter = 3 'Date GOSUB DispDS1302 Iter = 6 '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 IF NoPrompt = 1 THEN DSAddr = $c3 GOSUB DispCmd Char = "*" GOSUB DispChar ENDIF RETURN ReadTimeDate: 'Read the SETIME.TXT and SETDATE files on the SD, process and store in DS1302 RAM 'Each file contains 8 numbers 'The most significant nibble, usually the 1o's is before the least, the units. 'There are no separators. Seconds, Minutes, and 24 Hours start at 0 'SetTimeFormat:Tens Secs|Units secs|Tens Minutes|Units Minutes|Tens Hours (24 hr time, 0 -23)|Units Hours|Tens Date'|Units Date (starts 1)| 'SetDateFormat:Tens Month|Units Month(1-12)|0|Day of week (1 = Sunday)|Tens year (No 20)|Units Year|0|0 SEROUT SDOut,84,2,["S 1 5",CR] '50 ms timeout for missing bytes PAUSE 100 'The reading was done in two steps to reduce the array size to that necessary to store the time & date 'Two files were used since SERIN or the Interface was flaky in getting the remaining 8 numbers if in the same file SEROUT SDOut,84,["O 2 R /SETTIME.TXT",CR] PAUSE 200 SEROUT SDOut,84,["R 2",CR] 'The Rogue Secure Digital Interface provides an unwanted space character before the file content. SERIN SDIn,84,50,closeread,[STR TimeDate\9] 'added a byte because SERIN will not accept a single variable before the array 'The numbers are converted to BCD and stored in the DS1302 RAM FOR Iter = 0 TO 3 'Seconds, Minutes, Hours, Date Tens = TimeDate((2*Iter) + 1) - "0" 'The binary value of the Tens Units = TimeDate((2*Iter) + 2) - "0" 'The binary value of the Units DSAddr = (2 * Iter) + $C0 GOSUB DS1302IN NEXT SEROUT SDOut,84,["C 2",CR] PAUSE 100 SEROUT SDOut,84,["O 2 R /SETDATE.TXT",CR] PAUSE 200 SEROUT SDOut,84,["R 2",CR] SERIN SDIn,84,50,closeread,[STR TimeDate\9] 'will not accept a byte variable before the array FOR Iter = 0 TO 2 'Month, Day of week, year: Don't bother with the Write Protect (the 00) Tens = TimeDate((2*Iter) + 1) - "0" 'The binary value of the Tens Units = TimeDate((2*Iter) + 2) - "0" 'The binary value of the Units DSAddr = (2 * Iter) + $C8 GOSUB DS1302IN NEXT closeread: SEROUT SDOut,84,["C 2",CR] RETURN DispSetTimedate: 'Show what was read from the Secure Digital SETTIME.TXT and SETDATE.TXT files Char = $80 GOSUB DispCmd FormatFlag = 2 Iter = 4 'Month GOSUB ReadSet Iter = 3 'Date GOSUB ReadSet FormatFlag = 0 Iter = 6 'Year GOSUB ReadSet Char = $C0 GOSUB DispCmd FormatFlag = 3 Iter = 2 'Hour GOSUB ReadSet Iter = 1 'Minute GOSUB ReadSet FormatFlag = 0 Iter = 0 'Second GOSUB ReadSet RETURN ReadSet: 'Display the BCD values in the first 8 1302 RAM locations DSAddr = (2 * Iter) + $C1 GOSUB DS1302OUT Char = Tens + "0" 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 InitDS: 'Copy the time and date in the RAM to the clock at the right instant DSAddr = WRProtAddr 'Enable writing to clock DSData = WRProtData GOSUB DS1302IN PAUSE 1 DSAddr = TCHAddr 'Set Trickle Charge DSData = TCHData GOSUB DS1302IN PAUSE 1 LOW DS1302CE DSAddr = OSCEnAddr 'Make sure that the oscillator is turned on DSData = $00 GOSUB DS1302IN FOR Iter = 0 TO 6 'Copy first 7 locations from RAM to Clock DSAddr = (2 * Iter)+ $C1 GOSUB DS1302OUT DSAddr = (2 * Iter)+ $80 GOSUB DS1302IN NEXT 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 < 8) THEN Range = Range + 1 PAUSE 1000 DsData = Range GOSUB DS1302IN Range = Units ENDIF IF (DNSW = 0) AND (Range > 0) THEN Range = Range - 1 PAUSE 1000 DsData = Range 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 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 DispMode = $F GOSUB DispDec RETURN