'============================================================================== ' 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) '==================== end of uM-FPU definitions =============================== '============================================================================== '==================== main definitions ======================================== '============================================================================== '-------------------- LTC1298 ADC pin definitions ---------------------------------- DS_RST PIN 2 ' DS1620 reset/enable DS_CLK PIN 3 ' DS1620 clock DS_DATA PIN 4 ' DS1620 data '-------------------- uM-FPU register definitions ----------------------------- 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 '-------------------- 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 BYTE01 VAR Byte Byte02 VAR Byte Byte03 VAR Byte Byte04 VAR Byte startB VAR config.BIT0 sglDif VAR config.BIT1 oddSign VAR config.BIT2 msbf VAR config.BIT3 '============================================================================== '-------------------- initialization ------------------------------------------ '============================================================================== Reset: DEBUG CLS, "Demo 1: ", CR 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, "-------------------", CR GOSUB LTC1298 ' initialize DS1620 ' load floating point constants SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG11, LOADBYTE, 5, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG12, LOADBYTE, 10000, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG13, ATOF, ".000752", 0, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG14, ATOF, ".000234", 0, FSET] SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG15, ATOF, ".0000000589321", 0, FSET] '============================================================================== '-------------------- main routine -------------------------------------------- '============================================================================== Main: GOSUB LTC1298 ' get voltage reading from LTC1298 DEBUG CRSRXY, 0, 3, "LTC1298: ", DEC V1, CR ' send AD to uM-FPU ' convert to floating point ' store in register SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG1, LOADWORD, V1\16, FSET] ' Subtract V1 from 5 to get V2 SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG2, REG11-REG1] ' V2 / 10000 = Current SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG2, REG2/REG12] ' V1 / Current = Thermistor Resistance SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG2, REG1/REG2] ' Natural Log of thermistor resistance SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG3, REG2, LOG] ' Natural Log of thermistor resistance Cubed SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG4, REG3*REG3*REG3] ' Natural Log Cubed + C SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG4, REG4*REG15] ' Natural Log * B SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG5, REG3*REG14] ' Natural Log B + A SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG5, REG5+REG13] ' P1 + P2 SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG6, REG4+REG5] ' Inverse SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG7, REG6, INVERSE] DEBUG CRSRXY, 0, 4, "Reading " ' display degrees Celsius SHIFTOUT FpuOut, FpuClk, MSBFIRST, [REG7] format = 61 GOSUB PRint_FloatFormat GOSUB FPU_WAIT SHIFTOUT FpuOut, FpuClk, MSBFIRST, [XOP, READFLOAT] SHIFTIN FpuOut, FpuClk, MSBPRE, [byte01, BYTE02, BYTE03, BYTE04] DEBUG CR, "Byte01: ", Byte01, CR PAUSE 100 DEBUG CR, "Byte02: ", Byte02, CR PAUSE 100 DEBUG CR, "Byte03: ", Byte03, CR PAUSE 100 DEBUG CR, "Byte04: ", Byte04, CR PAUSE 2000 ' delay, then get the next reading GOTO Main END '-------------------- LTC1298 ADC --------------------------------------------- LTC1298: HIGH CS HIGH DIO_n Again: oddSign = 0 GOSUB Convert DEBUG "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, [dataByte] IF (dataByte = 0 OR dataByte > 127) THEN EXIT DEBUG dataByte LOOP RETURN '==================== end of uM-FPU SPI support routines ======================