'============================================================================== ' Copyright © Micromega Corporation 2002-2005. All rights reserved ' ' File: demo1-spi.bs2 ' ' This program demonstrates how to use the uM-FPU floating point coprocessor ' connected to the Basic Stamp over an 2-wire SPI interface. It takes ' temperature readings from a DS1620 digital thermometer, converts them to ' floating point and displays them in degrees Celsius and degrees Fahrenheit. ' ' @author Cam Thompson, Micromega Corporation ' @version V2.0 - January 8, 2005 ' changes: ' V2.0 - January 8, 2005 ' - original version ' '{$STAMP BS2sx} '{$PBASIC 2.5} '============================================================================== '============================================================================== '-------------------- uM-FPU definitions (V2.1) ------------------------------- '============================================================================== FpuClk PIN 0 ' SPI clock (connects to SCLK/SCL) FpuOut PIN 1 ' SPI data out (connects to SIN/SDA) FpuIn PIN 1 ' SPI data in (connects to SOUT) #IF ($STAMP = BS2SX) OR ($STAMP = BS2P) OR ($STAMP = BS2PX) #THEN ResetTime CON 625 ' 500 usec reset pulse #ELSE ResetTime CON 250 ' 500 usec reset pulse #ENDIF '-------------------- uM-FPU opcodes ------------------------------------------ SELECTA CON $00 ' select A register SELECTB CON $10 ' select B register FWRITEA CON $20 ' select A and write float to register FWRITEB CON $30 ' select B and write float to register FREAD CON $40 ' read float from register FSET CON $50 ' A = REG LSET CON $50 ' A = REG FADD CON $60 ' A = A + REG (float) FSUB CON $70 ' A = A - REG (float) FMUL CON $80 ' A = A * REG (float) FDIV CON $90 ' A = A / REG (float) LADD CON $A0 ' A = A + REG (long) LSUB CON $B0 ' A = A - REG (long) LMUL CON $C0 ' A = A * REG (long) LDIV CON $D0 ' A = A / REG (long) SQRT CON $E0 ' A = sqrt(A) LOG CON $E1 ' A = ln(A) LOG10 CON $E2 ' A = log(A) EXP CON $E3 ' A = e ** A EXP10 CON $E4 ' A = 10 ** A FSIN CON $E5 ' A = sin(A) radians FCOS CON $E6 ' A = cos(A) radians FTAN CON $E7 ' A = tan(A) radians FLOOR CON $E8 ' A = nearest integer <= A CEIL CON $E9 ' A = nearest integer >= A ROUND CON $EA ' A = nearest integer to A NEGATE CON $EB ' A = -A FABS CON $EC ' A = |A| INVERSE CON $ED ' A = 1 / A DEGREES CON $EE ' A = A / (PI / 180) radians to degrees RADIANS CON $EF ' A = A * (PI / 180) degreees to radians SYNC CON $F0 ' synchronization FLOAT CON $F1 ' copy A to register 0 and float FIX CON $F2 ' copy A to register 0 and fix FCOMPARE CON $F3 ' compare A and B LOADBYTE CON $F4 ' write signed byte to register 0, convert to float LOADUBYTE CON $F5 ' write unsigned byte to register 0, convert to float LOADWORD CON $F6 ' write signed word to register 0, convert to float LOADUWORD CON $F7 ' write unsigned word to register 0, convert to float READSTR CON $F8 ' read zero terminated string ATOF CON $F9 ' convert ASCII to float, store in A FTOA CON $FA ' convert float to ASCII ATOL CON $FB ' convert ASCII to long, store in A LTOA CON $FC ' convert long to ASCII FSTATUS CON $FD ' get the status of A register XOP CON $FE ' extended opcode NOP CON $FF ' nop FUNCTION CON $00 ' (XOP) user functions 0-15 READBYTE CON $90 ' (XOP) read low 8 bits of A (long) READWORD CON $91 ' (XOP) read low 16 bits of A (long) READLONG CON $92 ' (XOP) read 32-bit long value from A READFLOAT CON $93 ' (XOP) read floating point value from A LINCA CON $94 ' (XOP) A = A + 1 (long) LINCB CON $95 ' (XOP) A = A + 1 (long) LDECA CON $96 ' (XOP) A = A - 1 (long) LDECB CON $97 ' (XOP) A = A - 1 (long) LAND CON $98 ' (XOP) A = A AND B (long) LOR CON $99 ' (XOP) A = A OR B (long) LXOR CON $9A ' (XOP) A = A XOR B (long) LNOT CON $9B ' (XOP) A = NOT A (long) LTST CON $9C ' (XOP) status of A AND B (long) LSHIFT CON $9D ' (XOP) shift A by B bits (long) LWRITEA CON $A0 ' (XOP) select A and write long to register LWRITEB CON $B0 ' (XOP) select B and write long to register LREAD CON $C0 ' (XOP) read 32-bit long from register LUDIV CON $D0 ' (XOP) A = A / REG (unsigned long) POWER CON $E0 ' (XOP) A = A ** B ROOT CON $E1 ' (XOP) A = the Bth root of A FMIN CON $E2 ' (XOP) A = minimum of A and B FMAX CON $E3 ' (XOP) A = maximum of A and B FRACTION CON $E4 ' (XOP) load register 0 with the fractional part of A ASIN CON $E5 ' (XOP) A = asin(A) radians ACOS CON $E6 ' (XOP) A = acos(A) radians ATAN CON $E7 ' (XOP) A = atan(A) radians ATAN2 CON $E8 ' (XOP) A = atan(A/B) LCOMPARE CON $E9 ' (XOP) long compare A and B LUCOMPARE CON $EA ' (XOP) unsigned long compare A and B LSTATUS CON $EB ' (XOP) long status LNEGATE CON $EC ' (XOP) A = -A (long) LABS CON $ED ' (XOP) A = |A| (long) LEFT CON $EE ' (XOP) right parenthesis RIGHT CON $EF ' (XOP) left parenthesis LOADZERO CON $F0 ' (XOP) load register 0 with zero LOADONE CON $F1 ' (XOP) load register 0 with 1.0 LOADE CON $F2 ' (XOP) load register 0 with e LOADPI CON $F3 ' (XOP) load register 0 with pi LONGBYTE CON $F4 ' (XOP) write signed byte to register 0, convert to long LONGUBYTE CON $F5 ' (XOP) write unsigned byte to register 0, convert to long LONGWORD CON $F6 ' (XOP) write signed word to register 0, convert to long LONGUWORD CON $F7 ' (XOP) write unsigned word to register 0, convert to long IEEEMODE CON $F8 ' (XOP) set IEEE mode (default) PICMODE CON $F9 ' (XOP) set PIC mode CHECKSUM CON $FA ' (XOP) calculate code checksum BREAK CON $FB ' (XOP) debug breakpoint TRACEOFF CON $FC ' (XOP) turn debug trace off TRACEON CON $FD ' (XOP) turn debug trace on TRACESTR CON $FE ' (XOP) send debug string to trace buffer VERSION CON $FF ' (XOP) get version string SyncChar CON $5C ' sync character '-------------------- uM-FPU variables ---------------------------------------- dataWord VAR Word ' data word dataHigh VAR dataWord.HIGHBYTE ' high byte of dataWord dataLow VAR dataword.LOWBYTE ' low byte of dataLow dataByte VAR dataLow ' (alternate name) opcode VAR dataHigh ' opcode (same as dataHigh) reg VAR dataHigh ' register (same as dataHigh) format VAR dataLow ' format (same as dataLow) status VAR dataLow ' status (same as dataLow) status_Zero VAR status.BIT0 ' Zero status bit (0-not zero, 1-zero) status_Sign VAR status.BIT1 ' Sign status bit (0-positive, 1-negative) status_NaN VAR status.BIT2 ' Not a Number status bit (0-valid number, 1-NaN) status_Inf VAR status.BIT3 ' Infinity status bit (0-not infinite, 1-infinite) datain VAR Word BYTE00 VAR Word BYTE01 VAR Word BYTE02 VAR Word BYTE03 VAR Word '-------------------- uM-FPU register definitions ----------------------------- REG0 CON 0 REG1 CON 1 ' Register 1 REG2 CON 2 ' Register 2 REG3 CON 3 ' Register 3 REG4 CON 4 ' Register 4 REG5 CON 5 ' Register 5 REG6 CON 6 ' Register 6 REG7 CON 7 ' Register 7 REG8 CON 8 ' Register 8 REG9 CON 9 ' Register 9 REG10 CON 10 ' Register 10 REG11 CON 11 ' Register 11 REG12 CON 12 ' Register 12 REG13 CON 13 ' Register 13 REG14 CON 14 ' Register 14 REG15 CON 15 ' Register 15 '==================== end of uM-FPU definitions =============================== '============================================================================== '==================== main definitions ======================================== '============================================================================== '-------------------- DS1620 pin definitions ---------------------------------- DS_RST PIN 2 ' DS1620 reset/enable DS_CLK PIN 0 ' DS1620 clock DS_DATA PIN 3 ' DS1620 data '-------------------- uM-FPU register definitions ----------------------------- DegC CON 1 ' degrees Celsius DegF CON 2 ' degrees Fahrenheit F1_8 CON 3 ' constant 1.8 F32 CON 4 ' constant 32.0 '-------------------- variables ----------------------------------------------- rawTemp VAR Word ' raw temperature reading CS CON 2 CLK CON 0 DIO_n CON 3 config VAR Nib AD VAR Word V1 VAR Word x VAR Word startB VAR config.BIT0 sglDif VAR config.BIT1 oddSign VAR config.BIT2 msbf VAR config.BIT3 '============================================================================== '-------------------- initialization ------------------------------------------ '============================================================================== Reset: DEBUG CLS, "Demo 1: " GOSUB Fpu_Reset ' initialize uM-FPU IF status <> SyncChar THEN DEBUG "uM-FPU not detected." END ELSE GOSUB Print_Version ' display version string ENDIF DEBUG CR, "-------------------" GOSUB Init_DS1620 ' initialize DS1620 ' load floating point constants SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG11, LOADBYTE, 10000, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG12, ATOF, ".000752", 0, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG13, ATOF, ".000234", 0, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG14, ATOF, ".0000000589321", 0, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG15, LOADBYTE, 5, FSET] '============================================================================== '-------------------- main routine -------------------------------------------- '============================================================================== Main: GOSUB Read_DS1620 ' get temperature reading from DS1620 ' send rawTemp to uM-FPU ' convert to floating point ' store in register SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG1, LOADWORD, V1\16, FSET] DEBUG CR, "V1: ", DEC V1, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [LOADWORD, 4095, FDIV] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "After dividing by 4095" DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [LOADBYTE, 5, FMUL] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "After multiplying by 5" DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG2, FSET+REG0] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG1] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "After shifting to REG2" DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [LOADBYTE, 5, FSET] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "After loading5" DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [FSUB+REG2, FSET] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "After Subtracing From5" DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [LOADWORD, 10000, FDIV] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "After Divide by 10K" DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR ' SHIFTOUT FpuOut, FpuClk, MSBFIRST, [LOADBYTE, 5, FDIV+REG2] GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [BYTE00, BYTE01, BYTE02, BYTE03] DEBUG CR, "Byte0: ", DEC BYTE00 DEBUG CR, "Byte1: ", DEC BYTE01 x = Byte00 + Byte01 DEBUG CR, "X: ", DEC X DEBUG CR, "Byte2: ", DEC Byte02 DEBUG CR, "Byte3: ", DEC Byte03, CR DEBUG "Degrees C: ", CR ' display degrees Celsius SHIFTOUT FpuOut, FpuClk, MSBFIRST, [DegC] format = 51 GOSUB Print_FloatFormat DEBUG "Degrees F: " ' display degrees Fahrenheit SHIFTOUT FpuOut, FpuClk, MSBFIRST, [DegF] format = 51 GOSUB Print_FloatFormat PAUSE 2000 ' delay, then get the next reading GOTO Main END '-------------------- Init_DS1620 --------------------------------------------- Init_DS1620: LOW DS_RST ' initialize pin states HIGH DS_CLK PAUSE 100 HIGH DS_RST ' configure for CPU control SHIFTOUT DS_DATA, DS_CLK, LSBFIRST, [$0C, $02] LOW DS_RST PAUSE 100 HIGH DS_RST ' start temperature conversions SHIFTOUT DS_DATA, DS_CLK, LSBFIRST, [$EE] LOW DS_RST PAUSE 1000 ' wait for first conversion RETURN '-------------------- Read_DS1620 --------------------------------------------- Read_DS1620: HIGH CS HIGH DIO_n Again: oddSign = 0 GOSUB Convert DEBUG CR, "Channel ",DEC oddSign, ":", DEC AD,CR PAUSE 500 Convert: config = config | %1011 LOW CS SHIFTOUT DIO_n,CLK,LSBFIRST,[config\4] SHIFTIN DIO_n,CLK,MSBPOST,[AD\12] V1 = AD HIGH CS RETURN '============================================================================== '-------------------- uM-FPU SPI support routines (V2.1) ---------------------- '============================================================================== Fpu_Reset: LOW FpuClk ' set clock and data lines Low LOW FpuOut PULSOUT FpuClk, ResetTime ' send reset pulse to uM-FPU PAUSE 8 ' check for synchronization SHIFTOUT FpuOut, FpuClk, MSBFIRST, [SYNC] SHIFTIN FpuIn, FpuClk, MSBPRE, [status] RETURN Fpu_Wait: INPUT FpuIn ' (required for 2-wire interface) Fpu_Wait2: IF (FpuIn = 1) THEN GOTO Fpu_Wait2 ' wait until uM-FPU is ready RETURN Print_Version: ' get the uM-FPU version string SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, VERSION] GOTO Print_String2 ' print it Print_Float: format = 0 ' set format to zero (free format) ' (fall through to Print_FloatFormat) Print_FloatFormat: opcode = FTOA ' convert floating point to formatted ASCII GOTO Print_String ' print the value Print_Long: format = 0 ' set format to 0 (free format) ' (fall through to Print_LongFormat) Print_LongFormat: opcode = LTOA ' convert long integer to formatted ASCII ' (fall through to Print_String) Print_String: ' send conversion command SHIFTOUT FpuOut, FpuClk, MSBFIRST, [opcode, format] Print_String2: GOSUB Fpu_Wait ' wait until uM-FPU is ready SHIFTOUT FpuOut, FpuClk, MSBFIRST, [READSTR] DO ' display zero terminated string SHIFTIN FpuIn, FpuClk, MSBPRE, [DATAin] IF (DATAin = 0 OR DATAin > 256) THEN EXIT DEBUG datain LOOP RETURN '==================== end of uM-FPU SPI support routines ======================