From c06553d5fee73beb7fac30be88567307b0b402fe Mon Sep 17 00:00:00 2001 From: Blaze Sanders Date: Fri, 28 Feb 2014 23:31:20 -0500 Subject: [PATCH] Initial Commit Blaze is a NOOB --- Clock.spin | Bin 0 -> 43054 bytes GDB Hello World.spin | Bin 0 -> 7716 bytes GDB-API-V0.1.0.spin | Bin 0 -> 122060 bytes GDB-SerialMirror.spin | Bin 0 -> 36292 bytes I2C_ROMEngine.spin | 1 + L298MotorPwm.spin | 142 +++++++++++ L298SetMotor.spin | 136 ++++++++++ MCP3208.spin | Bin 0 -> 17774 bytes NLAST4051.spin | Bin 0 -> 23334 bytes UAHLunarWormbotTest.spin | 92 +++++++ YourProject.spin | 64 +++++ pasm_i2c_driver.spin | 519 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 954 insertions(+) create mode 100644 Clock.spin create mode 100644 GDB Hello World.spin create mode 100644 GDB-API-V0.1.0.spin create mode 100644 GDB-SerialMirror.spin create mode 100644 I2C_ROMEngine.spin create mode 100644 L298MotorPwm.spin create mode 100644 L298SetMotor.spin create mode 100644 MCP3208.spin create mode 100644 NLAST4051.spin create mode 100644 UAHLunarWormbotTest.spin create mode 100644 YourProject.spin create mode 100644 pasm_i2c_driver.spin diff --git a/Clock.spin b/Clock.spin new file mode 100644 index 0000000000000000000000000000000000000000..a6f36f177f63f6d04c9fdb803cf3cf4fd68d80e7 GIT binary patch literal 43054 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 RW$+&RbE^K7>BBC;{||6@jIaOz literal 0 HcmV?d00001 diff --git a/GDB Hello World.spin b/GDB Hello World.spin new file mode 100644 index 0000000000000000000000000000000000000000..f8ef6bd7c5ea59f171ca9f10ff3d4010748150d8 GIT binary patch literal 7716 zcmdU!S#uLd5Xa{^RrwAZ9*{XKTjmT^d64A;Qy3`AKzK^Yl8hbe!ji#;;;WPVf89Im zffQ86KwMkW&aQfnsD^PENuR+_(xWWxZa9#fN!XW6$C7QL@kpa#c&+bN z=Ejijk~&D7y}RDzfEm zi#MJq%lcu@{2b$;Eh%41?j=Rsv+!J%got#{cTD;_dIlYca*vDq8eRNVmiFQ~T;z(^ zQwtR10n|M-3u0F=D^Wxc2NT5w_=t5QVn&n%O~_7=7)u{(4l@r7aXZ3VP~_XIWZA-X z#jR&OGJ*CP_D4O6HRGmeylQ|LQGRLx6)~~c0#T?XJy8-#BYiu9$MpxIA1LZTmMwAi zYLZ_8PnD(J*NQD!2+5cYPOhsaW6`+2$LYwTl?-$`bUZaaZ}qMv`sjgYdZHS_yCoWs z8WcR#H|y@&Q{PsC$|a>54dsucJ2BAY-uuWxiTbS*8}5g&5Vv0*_XV4SPZ#0pXG)j6|wIUB3yr@lo+-trL{ z^6!4^IB&1Z;Nisl`!Rg9J9$EOR20{A*?aO3nb**GAWzYUf~VvsapAGiOy76RpZL0M zv)kcFA-Y<)t8Zpd1Gm-rzt^2#?yJj-Z{Yuz zaXZTKfeOrlLrvow`iwN@>8>Ho_lyab=~Q_!5E>K9Z^R#&?nu^UyW%~w;i9_tMPU(L zpJRBeUU{oKmD~QI@Ox8s@wIE_i^uZc%k<5%y#e2Lt-Ao-+_G@plAq~0;#;S#hZn-d z9bw_7;bTVM5bchxb9iYEKaWvP7#B;a;T@@j4Yn-{PdJ)j+0f4l_Jv7(JDA zkL6!Buk<@JlO?MDaoBBdrL0#L{H}MwwQ0( zZm%vcZs}KQlq2kyJr6RG#j*0n-l2@D-aWuMYJ;|sI?EY$iC5D1i?RR`EXrof!u6Uy z%lb9ixRS;+I(VN`ln-nn4vUxpf3N)X8stM>D)(T;c5Ye6MtoB97xjr%+-o>EMrEnW z(#4*mDqX#zL-V(&(0xf-+zYo%hh6EmtlSeB8?xw7)JHj8(PLFq+u}m@6N?)f z#WR4u*2f3nA^N&s@b67M=VOAok7QY*I`8?4p5j$ES+kwamNNM6ON?iudx)OQIZRpzg$pAKaBE1GFb(HaZcVfqR`TQNNI=0-Q^1$nv$>rYk zZm}HOacAwjDLQ66;vIJ@XSw+#j1t{YjCG}dM{+Esk?j&)oc8}EQIsRn+z{@9Q|MKc zBcpt5aq76_xK^Z$YkkW-fb>J+B z_2_xgpHGx|TIT0bBacC^v=Vs09xCqQI0f4@9=;R4s$Yn6P|Ejt^z%b;KhPVp+-nKD z>J#<;yajRMc^qf4?5eL7r1X`%lgvDS&-@;HnR#a1oibyVzhm6g>})Thm&cTA0=m(2 zc~$Cswk_2qdz+|7`H^-blJXv&Zo4~EED>X3`i$FCW_%CZ<)bM^5HU6kzs(gDD+RCD~)PR)i^ZD`XF6d7K1$ zPEkW+rf~-Nbl6{bDV{rNkGG(H?xDIaI?3N{uf}e3SNj8~K=tYWL0wHa3!(4hJcE9&_{2HV zTa%8yDeemJJ6+dUXiO9^kMk|=Tk3)Mr-&}Sr)aq%y^Fs7x+d(l`7ejlKvwDL9y_Dh zF;NR#GCyJV{Yup&nCP2*%RsU)_EQ~B@u*8@S`U4}|Gw5g*5#)`-Bbhba^vilMLpGw z%F;TgMqlz-RbC;TOJ1?n(Q0Vt4{lrkCyf))tbWB<@qN=%%Sd$FlNOvrumgi;PwTUv UgGXjP>{89?K(M*= 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 F{|8X;uu1>` literal 0 HcmV?d00001 diff --git a/GDB-SerialMirror.spin b/GDB-SerialMirror.spin new file mode 100644 index 0000000000000000000000000000000000000000..f65e0a87f0170dd504e318a98d48389e40c99100 GIT binary patch literal 36292 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 EAMCB_A^-pY literal 0 HcmV?d00001 diff --git a/I2C_ROMEngine.spin b/I2C_ROMEngine.spin new file mode 100644 index 0000000..9254e58 --- /dev/null +++ b/I2C_ROMEngine.spin @@ -0,0 +1 @@ +{{ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // I2C Electrically Erasable Programmable Read Only Memory Engine // // Author: Kwabena W. Agyeman // Updated: 7/27/2010 // Designed For: P8X32A // Version: 1.1 // // Copyright (c) 2010 Kwabena W. Agyeman // See end of file for terms of use. // // Update History: // // v1.0 - Original release - 8/8/2009. // v1.1 - Added variable pin support - 7/27/2010. // // For each included copy of this object only one spin interpreter should access it at a time. // // Nyamekye, /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // I2C Circuit: // // 3.3V // | // R 10KOHM // | // Data Pin Number --- EEPROM SDA Pin. // // 3.3V // | // R 10KOHM // | // Clock Pin Number --- EEPROM SCL Pin. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }} PUB readByte(EEPROMaddress) '' 18 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Reads a byte from the EEPROM. It is recommended to read the byte on a byte boundary. '' // '' // Returns the byte on success and false on failure. Could return a byte of value 0. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// result &= readPage(EEPROMaddress, @result, 1) PUB writeByte(EEPROMaddress, value) '' 19 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Writes a byte to the EEPROM. It is recommended to write the byte on a byte boundary. '' // '' // Returns true on success and false on failure. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' // Value - Value to write to the EEPROM. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// return writePage(EEPROMaddress, @value, 1) PUB readWord(EEPROMaddress) '' 18 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Reads a word from the EEPROM. It is recommended to read the word on a word boundary. '' // '' // Returns the word on success and false on failure. Could return a word of value 0. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// result &= readPage(EEPROMaddress, @result, 2) PUB writeWord(EEPROMaddress, value) '' 19 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Writes a word to the EEPROM. It is recommended to write the word on a word boundary. '' // '' // Returns true on success and false on failure. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' // Value - Value to write to the EEPROM. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// return writePage(EEPROMaddress, @value, 2) PUB readLong(EEPROMaddress) '' 18 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Reads a long from the EEPROM. It is recommended to read the long on a long boundary. '' // '' // Returns the long on success and false on failure. Could return a long of value 0. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// result &= readPage(EEPROMaddress, @result, 4) PUB writeLong(EEPROMaddress, value) '' 19 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Writes a long to the EEPROM. It is recommended to write the long on a long boundary. '' // '' // Returns true on success and false on failure. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' // Value - Value to write to the EEPROM. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// return writePage(EEPROMaddress, @value, 4) PUB readPage(EEPROMaddress, RAMaddress, byteCount) '' 14 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Reads bytes from the EEPROM. Uses a 19 bit addressing scheme which can acess multiple EERPOMs on a bus. '' // '' // This rountine can only read from the EEPROM selected. Any reads past that EEPROM will warp arround. '' // '' // It is recommended to use the byte/word/long read rountines used on byte/word/long boundaries respectively. '' // '' // Returns true on success and false on failure. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' // RAMaddress - Starting byte address of the data to write to. '' // ByteCount - Number of bytes to read. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// result := eepromPoll(EEPROMaddress) if(result) stopDataTransfer startDataTransfer result and= transmitPacket(constant((10 << 4) | 1) | ((EEPROMaddress >> 15) & $E)) repeat ((byteCount <# (65_536 - (RAMaddress #> 0))) #> 0) byte[RAMaddress++] := receivePacket(--byteCount) stopDataTransfer clearLock PUB writePage(EEPROMaddress, RAMaddress, byteCount) '' 14 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Writes bytes to the EEPROM. Uses a 19 bit addressing scheme which can access multiple EERPOMs on a bus. '' // '' // This rountine can only write to the page of the EEPROM selected. Any writes past that page will warp arround. '' // '' // It is recommended to use the byte/word/long write rountines used on byte/word/long boundaries respectively. '' // '' // Returns true on success and false on failure. '' // '' // EEPROMaddress - Starting byte address of the data to access. '' // RAMaddress - Starting byte address of the data to read from. '' // ByteCount - Number of bytes to write. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// result := eepromPoll(EEPROMaddress) if(result) repeat ((byteCount <# (65_536 - (RAMaddress #> 0))) #> 0) result and= transmitPacket(byte[RAMaddress++]) stopDataTransfer clearLock PUB ROMEngineStart(dataPinNumber, clockPinNumber, lockNumberToUse) '' 9 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Checks out a lock for the driver and changes the I2C Circuit pins. '' // '' // Returns true on success and false on failure. '' // '' // DataPinNumber - Pin to use to drive the SDA data line circuit. '' // ClockPinNumber - Pin to use to drive the SCL clock line circuit. '' // LockNumberToUse - Lock number to use if sharing the I2C bus (0 - 7). -1 to request a new lock number. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ROMEngineStop dataPin := ((dataPinNumber <# 31) #> 0) clockPin := ((clockPinNumber <# 31) #> 0) if((dataPin <> clockPin) and (chipver == 1)) lockNumber := lockNumberToUse if(lockNumberToUse == -1) lockNumber := locknew result or= ++lockNumber PUB ROMEngineStop '' 3 Stack Longs '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// '' // Returns the lock used by the driver. '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(lockNumber) lockret(-1 + lockNumber~) PRI eepromPoll(EEPROMaddress) ' 8 Stack Longs setLock startDataTransfer result := cnt repeat until(transmitPacket(constant(10 << 4) | ((EEPROMaddress >> 15) & $E))) stopDataTransfer startDataTransfer if((||(cnt - result)) > (clkfreq / constant(1_000 / 5))) return false result := transmitPacket(EEPROMaddress >> 8) result and= transmitPacket(EEPROMaddress) PRI transmitPacket(value) ' 4 Stack Longs value := ((!value) >< 8) repeat 8 dira[dataPin] := value dira[clockPin] := false dira[clockPin] := true value >>= 1 dira[dataPin] := false dira[clockPin] := false result := not(ina[dataPin]) dira[clockPin] := true dira[dataPin] := true PRI receivePacket(aknowledge) ' 4 Stack Longs dira[dataPin] := false repeat 8 result <<= 1 dira[clockPin] := false result |= ina[dataPin] dira[clockPin] := true dira[dataPin] := (not(not(aknowledge))) dira[clockPin] := false dira[clockPin] := true dira[dataPin] := true PRI startDataTransfer ' 3 Stack Longs outa[dataPin] := false outa[clockPin] := false dira[dataPin] := true dira[clockPin] := true PRI stopDataTransfer ' 3 Stack Longs dira[clockPin] := false dira[dataPin] := false PRI setLock ' 3 Stack Longs if(lockNumber) repeat while(lockset(lockNumber - 1)) PRI clearLock ' 3 Stack Longs if(lockNumber) lockclr(lockNumber - 1) DAT ' //////////////////////Variable Array///////////////////////////////////////////////////////////////////////////////////////// dataPin byte 29 ' Default data pin. clockPin byte 28 ' Default clock pin. lockNumber byte 00 ' Driver lock number. ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// {{ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TERMS OF USE: MIT License /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the // Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }} \ No newline at end of file diff --git a/L298MotorPwm.spin b/L298MotorPwm.spin new file mode 100644 index 0000000..27a2f92 --- /dev/null +++ b/L298MotorPwm.spin @@ -0,0 +1,142 @@ +{{ + L298MotorsPwm.spin + Tom Doyle + 25 Feb 2007 + + Starts a cog to maintain a PWM signal to the L298 chip + The control pins on the L298 are controlled by the forward and reverse procedures + Speed is controlled by the update procedure + + In normal use it is not necessary to call any of these procedures directly as + they are called by the SetMotor.spin object +}} + +CON + + _clkmode = xtal1 + pll16x + _xinfreq = 5_000_000 + + +VAR + + long duty, period, pPin, dirM, I1pin, I2Pin ' par access + + byte cog + +PUB start(EnPin, In1Pin, In2Pin, pulsesPerCycle) : success + + ' EnPin - L298 Enable Pin + ' In1Pin - L298 Input 1 Pin + ' In2Pin - L298 Input 2 Pin + ' pulsesPerCycle - pulses per PWM cycle = clkfreq/pwmfreq + + pPin := EnPin + I1pin := In1Pin + I2pin := In2Pin + + duty := 0 + period := pulsesPerCycle + + reverse ' initialize dirM + success := cog := cognew(@entry, @duty) + + +PUB stop +{{ set esc PWM pin to off + stop cog }} + + waitpeq(0, |< pPin, 0) + dira[pPin] := 0 + if cog > 0 + cogstop(cog) + +PUB forward + + dirM := !0 + +Pub reverse + + dirM := 0 + + +PUB update(dutyPercent) + + duty := period * dutyPercent / 100 + + +DAT + +entry movi ctra,#%00100_000 + movd ctra,#0 + + mov addr, par + add addr, #8 ' L298 Enable (PWM) pin number + rdword _Enpin, addr ' stored in _EnPin + movs ctra,_Enpin + + mov temp, #1 + shl temp,_Enpin ' L298 Enable (PWM) pin + or dira, temp ' make an output + + mov addr, par + add addr, #16 ' L298 In1 pin + rdlong _In1Pin, addr ' stored in _In1Pin + mov temp, #1 + shl temp,_In1pin ' L298 In1 pin + or dira, temp ' make an output + + mov addr, par + add addr, #20 ' L298 In2 pin + rdlong _In2Pin, addr ' stored in _In2Pin + mov temp, #1 + shl temp,_In2pin ' L298 In2 pin + or dira, temp ' make an output + + + mov frqa,#1 + + mov addr, par + add addr, #4 ' pulses per pwm cycle + rdlong _cntadd, addr + mov cntacc,cnt + add cntacc,_cntadd + +:loop waitcnt cntacc,_cntadd + + mov tempDir, outa + + mov addr, par + add addr, #12 ' dirM + rdlong _dirM, addr ' store in _dirM + + mov tempDir, outa + + mov temp, #1 + shl temp,_In1Pin ' L298 In1 + test _dirM, 1 WZ ' check if direction = 1 + muxz tempDir, temp ' set Input 1 + + mov temp, #1 + shl temp,_In2Pin ' L298 In2 + test _dirM, 1 WZ ' check if direction = 1 + muxnz tempDir, temp ' set Input 2 + + mov outa, tempDir + + rdlong _duty,par + mov temp, par + add temp, #1 + rdlong _duty, temp + neg phsa,_duty + jmp #:loop + +_dirM res 1 ' motor direction 0 or 1 +_In1Pin res 1 ' L298 Input 1 Pin +_In2Pin res 1 ' L298 Input 2 Pin +tempDir res 1 ' temp direction +cntacc res 1 +_duty res 1 +_cntadd res 1 +_Enpin res 1 ' L298 Enable Pin +addr res 1 +temp res 1 \ No newline at end of file diff --git a/L298SetMotor.spin b/L298SetMotor.spin new file mode 100644 index 0000000..386441a --- /dev/null +++ b/L298SetMotor.spin @@ -0,0 +1,136 @@ +{{ + L298SetMotor.spin + Tom Doyle + 25 Feb 2007 + + Control of a DC motor with the L298 motor control chip. + The L298 chip does not use the traditional PWM, Direction and Brake control lines. + It uses what it refers to as the Enable line for PWM input and two lines refered to + as InX and InY for direction, coast and brake functions. The chip contains two controllers + and is readily available in a kit (L298 Compact Motor Driver) for less + than $20. The only deal better than this I have found is the Propeller Proto Board. + + The init procedure initializes local varibles and starts a PWM loop in a new cog + + The setMotor procedure sets the duty cycle (0%-100%), direction and delay per % change in + duty cycle. The delay per % change in duty cycle allows the motor speed to ramp up and down in + a smooth manner. The amount of delay to use will depend on the characteristics of the motor + and the load on the motor. This procedure is operating open loop which means that if the delay + per % change in duty cycle is not long enough you can over run the motor. The procedure keeps + track of the direction of the motor and will ramp the speed to 0 before changing direction. + The setMotor procedure is run in a new cog which waits for any previous operation to quit before + starting the new one. The setMotor cog is released after the new motor setting has been reached. + The pwm loop will run constantly in its own cog to keep the motor running at the set duty cycle. + +}} + +CON + + _clkmode = xtal1 + pll16x ' use crystal x 16 (5 x 16 = 80 Mhz) + _xinfreq = 5_000_000 + + _lcdPin = 0 ' Parallax 4x20 LCD Serial Line + + ' ESC Values + _escForward = 1 ' forward direction + _escReverse = 0 ' reverse direction + + +OBJ + + pwm[2] : "L298MotorPwm" ' Motor PWM object + + +VAR + + long Stack[50] + + WORD dutyCycleOld ' previous duty cycle value for ramp calculations + WORD directionOld ' previous directon value for reverse control + BYTE motorCog ' cog ID for setMotor + WORD escFreq ' ESC Frequency + BYTE pwmIndex ' pwm.spin index + + +PUB init(EnPin, In1, In2, Freq, pIndex) | pulsesPerCycle + +{{ + initialize electronic speed control + start pwm object in a new cog +}} + + escFreq := Freq + pwmIndex := pIndex + dutyCycleOld := 0 + directionOld := _escForward + pulsesPerCycle := clkfreq / escFreq + pwm[pwmIndex].start(EnPin, In1, In2, pulsesPerCycle ) + pwm[pwmIndex].reverse + motorCog := 0 + + +PUB setMotor(duty, Direction, delayPerStep) : success + + ' return value is cog 0-8 where 0 is no cog + + REPEAT + WHILE motorCog > 0 ' wait for end of previous operation + + success := (motorCog := cognew(csetMotor(duty, Direction, delayPerStep, @dutyCycleOld, @directionOld), @Stack) + 1) + + +PRI csetMotor(duty, Direction, delayPerStep, adrDCold, adrDirOld) | tempFreq, tempDuty, lDutyCycleOld, lDirectionOld + + + lDutyCycleOld := word[adrDCold] + lDirectionOld := word[adrDirOld] + + + IF (Direction <> lDirectionOld) AND (lDutyCycleOld > 0) ' stop motor before reversing + + REPEAT + + lDutyCycleOld := lDutyCycleOld - 1 + + tempFreq := escFreq + tempDuty := lDutyCycleOld + + pwm[pwmIndex].update(tempDuty) + + waitcnt(((CLKFREQ/1000) * delayPerStep) + cnt) + + WHILE lDutyCycleOld > 0 + + if Direction == _escForward + pwm[pwmIndex].forward + + if Direction == _escReverse + pwm[pwmIndex].reverse + + lDirectionOld := Direction + + REPEAT + tempFreq := 1000 + + IF lDutyCycleOld < duty + lDutyCycleOld := lDutyCycleOld + 1 + + IF lDutyCycleOld > duty + lDutyCycleOld := lDutyCycleOld - 1 + + tempDuty := lDutyCycleOld + + pwm[pwmIndex].update(tempDuty) + + waitcnt(((CLKFREQ/1000) * delayPerStep) + cnt) + + WHILE lDutyCycleOld <> duty + + lDutyCycleOld := duty + + word[adrDCold] := lDutyCycleOld + word[adrDirold] := lDirectionOld + + cogstop(motorCog~ - 1) ' stop cog and update cog variable + + \ No newline at end of file diff --git a/MCP3208.spin b/MCP3208.spin new file mode 100644 index 0000000000000000000000000000000000000000..30e500403ce126892cc02d58f58d24fd26223b70 GIT binary patch literal 17774 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 literal 0 HcmV?d00001 diff --git a/UAHLunarWormbotTest.spin b/UAHLunarWormbotTest.spin new file mode 100644 index 0000000..34bb1b0 --- /dev/null +++ b/UAHLunarWormbotTest.spin @@ -0,0 +1,92 @@ +{Object_Title_and_Purpose} + + +CON 'Global Constants + +'---Useful constants--- +HIGH = 1 +LOW = 0 +OUTPUT = 1 +INPUT = 0 +AVERAGE = 1 +CURRENT = 0 +FORWARD = 1 +REVERSE = 0 +INFINITY = 1 +ENABLE = 1 +DISABLE = 0 + +HIGH_SPEED_IO0 = 0 +HIGH_SPEED_IO1 = 1 +HIGH_SPEED_IO2 = 2 +HIGH_SPEED_IO3 = 3 +HIGH_SPEED_IO4 = 4 +HIGH_SPEED_IO5 = 5 + + +VAR 'Global variables + +long ExampleVariable + +OBJ 'Additional files you would like imported / included + +'Sol-X API that controls all the GDB hardware function +GDB : "GDB-API-V0.1.0" + +'Used to control clock timing functions +TIMING : "Clock" + +PUB Main 'First method called, like in JAVA + +'' Action: Initializes all the GDB hardware and firmware +'' Parameters: None +'' Results: Prepares the GDB for user interaction +''+Reads/Uses: None +'' +Writes: None +'' Local Vars: None +'' Calls: GDB.Initialize( ), GDB.SendText( ), TIMING.PauseSec( ) +'' GDB.GetNumber( ), and GDB.SetMotorShield( ) functions +'' URL: http://www.solarsystemexpress.com/store.html + +GDB.Initialize + +repeat 'Infinte Loop + + repeat + GDB.SendText(STRING("TYPE 1 and hit enter to extend L-16 actuators.")) + TIMING.PauseSec(5) 'Pause 5 seconds before outputing promote again + until(GDB.GetNumber) + + GDB.SetMotorShield(HIGH_SPEED_IO0, HIGH_SPEED_IO1, HIGH_SPEED_IO2, FORWARD) + GDB.SetMotorShield(HIGH_SPEED_IO3, HIGH_SPEED_IO4, HIGH_SPEED_IO5, FORWARD) + + repeat + GDB.SendText(STRING("TYPE 2 and hit enter to contract L-16 actuators.")) + TIMING.PauseSec(5) 'Pause 5 seconds before outputing promote again + until(GDB.GetNumber) + + GDB.SetMotorShield(HIGH_SPEED_IO0, HIGH_SPEED_IO1, HIGH_SPEED_IO2, REVERSE) + GDB.SetMotorShield(HIGH_SPEED_IO3, HIGH_SPEED_IO4, HIGH_SPEED_IO5, REVERSE) + +{{ See GDB-API-V.0.1 +PUB SetMotorShield(EnablePin, Input1Pin, Input2Pin, Direction) + + Action: More complex function to control actuator movement + Parameters: EnablePin - GDB GPIO pin connected to the "Enable Motor X Connector" on Seeed Studio Motor Driver + Input1Pin - GDB GPIO pin connected to the J7.1 (Channel A) or J7.5 (Channel B) on Seeed Studio Motor Driver + Input2Pin - GDB GPIO pin connected to the J7.4 (Channel A) or J7.6 (Channel B) on Seeed Studio Motor Driver + Direction - Sets direction of actuator movement using contsant FORWARD or REVERSE + Results: Changes the direction of current flow in the Seeed Studio Motor Driver ++Reads/Uses: None + +Writes: None + Local Vars: None + Calls: FullH_BridgeSubroutine( ) + URL: www.seeedstudio.com/wiki/Motor_Shield_V1.0 +}} + +PRI private_method_name + + +DAT +name byte "string_data",0 + \ No newline at end of file diff --git a/YourProject.spin b/YourProject.spin new file mode 100644 index 0000000..a7866ff --- /dev/null +++ b/YourProject.spin @@ -0,0 +1,64 @@ +{Object_Title_and_Purpose} + + +CON 'Global Constants + +'---Useful constants--- +HIGH = 1 +LOW = 0 +OUTPUT = 1 +INPUT = 0 +AVERAGE = 1 +CURRENT = 0 +FORWARD = 1 +REVERSE = 0 +INFINITY = 1 +ENABLE = 1 +DISABLE = 0 + +VAR 'Global variables + +long ExampleVariable + +OBJ 'Additional files you would like imported / included + +'Sol-X API that controls all the GDB hardware function +GDB : "GDB-API-V0.1.0" + +'Used to control clock timing functions +TIMING : "Clock" + +PUB Main 'First method called, like in JAVA + +'' Action: Initializes all the GDB hardware and firmware +'' Parameters: None +'' Results: Prepares the GDB for user interaction and test hardwares +''+Reads/Uses: None +'' +Writes: None +'' Local Vars: None +'' Calls: All the GDB API functions +'' URL: http://www.solarsystemexpress.com/store.html + +GDB.Initialize + +'REMOVE EVERYTHING BELOW HERE TO START WRITING YOUR OWN CODE. HAVE FUN :) + +GDB.UnitTest + +GDB.MeasureAnalogVoltage(0, GDB#AVERAGE, 50) +GDB.OutputAnalogVoltage(4095, 0) +GDB.TurnOffADC_DAC + +GDB.SetMotorDriver(GDB#FULL_H_BRIDGE_U1, GDB#FORWARD) +TIMING.PauseMSec(2000) 'PAUSE TWO SECONDS +GDB.SetMotorDriver(GDB#FULL_H_BRIDGE_U1, GDB#REVERSE) +GDB.SetHighPowerDriverDutyCycle(GDB#FULL_H_BRIDGE_U2, 75, GDB#FORWARD, 2000) + + + +PRI private_method_name + + +DAT +name byte "string_data",0 + \ No newline at end of file diff --git a/pasm_i2c_driver.spin b/pasm_i2c_driver.spin new file mode 100644 index 0000000..9727749 --- /dev/null +++ b/pasm_i2c_driver.spin @@ -0,0 +1,519 @@ +'' PASM I2C Driver Version 1.0 +'' Copyright (c) 2010 Dave Hein +'' June 6, 2010 +'' See end of file for terms of use + +'' This is a PASM version of Mike Green's Basic I2C Driver. The +'' low level I2C routines have been converted to PASM to increase the +'' I/O speed. These routines use the same calling interface as +'' the Basic I2C Driver Version 1.1 in the OBEX, and should be fully +'' compatible with any existing code that uses the Basic I2C Driver. + +'' Just like the Basic I2C Driver, the PASM I2C Driver assumes +'' that the SDA pin is one higher than the SCL pin. It assumes that +'' neither the SDA nor the SCL pins have pullups, so drives both. + +'' This object uses the Initialize method to start up a cog rather than using +'' the start method. This is done to remain consistent with the Basic I2C +'' Driver routines. Initialize must be called at the beginning of the program. +'' This loads the PASM code in a cog, and clocks the I2C bus to initialize +'' the devices on the bus. Subsequent calls may be made to Initialize, and +'' it will not cause the cog to be stopped or reloaded. + +'' The bus I/O speed is controlled by the constant DELAY_CYCLES. This constant +'' is used in the delay routine. The total delay consists of calling the delay +'' routine, performing a waitcnt of CNT + DELAY_CYCLES, and then returning +'' from the delay routine. Therefore, the total delay will be about +'' 12 + DELAY_CYCLES. + +'' The delay time represents the clock high time, and half the clock low time. +'' It is also used to determine the setup and hold times for the data bit for +'' read, write, start and stop operations. DELAY_CYCLES is defined with a +'' value of 52, which gives a total delay of 64 cycles. At 80 MHz, this is +'' 0.8 usecs, which is about one-third of a 400 KHz cycle time. This value +'' should be modified to provide the optimal speed for a particular application. + +'' Please see Mike Green's Basic I2C Driver object for more information on +'' the I2C routines, and on how EEPROMs are addressed + +CON + ACK = 0 ' I2C Acknowledge + NAK = 1 ' I2C No Acknowledge + Xmit = 0 ' I2C Direction Transmit + Recv = 1 ' I2C Direction Receive + + CMD_START = 1 ' Issue a start bit + CMD_STOP = 2 ' Issue a stop bit + CMD_READ = 3 ' Transmit a byte to the I2C bus + CMD_WRITE = 4 ' Read a byte from the I2C bus + CMD_INIT = 5 ' Initialize the I2C bus + CMD_READPAGE = 6 ' Read one or more bytes in the page mode + CMD_WRITEPAGE = 7 ' Write one or more bytes in the page mode + + DELAY_CYCLES = 52 ' I2C Delay time. Must be between 12 and 511 + +DAT + cognum long 0 + cmdbuf long 0, 0 + +PUB Initialize(SCL) +'' Start cog if not started, and initialize the devices on the I2C bus + 'ser.dbprintf1(string("i2c initialize %d\n"), SCL) + cmdbuf[1] := @SCL + cmdbuf := CMD_INIT + ifnot cognum + cognum := cognew(@cmdloop, @cmdbuf) + 1 + repeat while cmdbuf + +PUB Start(SCL) +'' Issue an I2C start command + cmdbuf[1] := @SCL + cmdbuf := CMD_START + repeat while cmdbuf + +PUB Stop(SCL) +'' Issue an I2C stop command + cmdbuf[1] := @SCL + cmdbuf := CMD_STOP + repeat while cmdbuf + +PUB Read(SCL, ackbit) +'' Read in i2c data, Data byte is output MSB first, SDA data line is +'' valid only while the SCL line is HIGH. SCL and SDA left in LOW state. + cmdbuf[1] := @SCL + cmdbuf := CMD_READ + repeat while cmdbuf + result := cmdbuf[1] + +PUB Write(SCL, data) +'' Write i2c data. Data byte is output MSB first, SDA data line is valid +'' only while the SCL line is HIGH. Data is always 8 bits (+ ACK/NAK). +'' SDA is assumed LOW and SCL and SDA are both left in the LOW state. + cmdbuf[1] := @SCL + cmdbuf := CMD_WRITE + repeat while cmdbuf + result := cmdbuf[1] + +PUB ReadPage(SCL, devSel, addrReg, dataPtr, count) : ackbit +'' Read in a block of i2c data. Device select code is devSel. Device starting +'' address is addrReg. Data address is at dataPtr. Number of bytes is count. +'' The device select code is modified using the upper 3 bits of the 19 bit addrReg. +'' Return zero if no errors or the acknowledge bits if an error occurred. + cmdbuf[1] := @SCL + cmdbuf := CMD_READPAGE + repeat while cmdbuf + ackbit := cmdbuf[1] + +PUB WritePage(SCL, devSel, addrReg, dataPtr, count) : ackbit +'' Write out a block of i2c data. Device select code is devSel. Device starting +'' address is addrReg. Data address is at dataPtr. Number of bytes is count. +'' The device select code is modified using the upper 3 bits of the 19 bit addrReg. +'' Most devices have a page size of at least 32 bytes, some as large as 256 bytes. +'' Return zero if no errors or the acknowledge bits if an error occurred. If +'' more than 31 bytes are transmitted, the sign bit is "sticky" and is the +'' logical "or" of the acknowledge bits of any bytes past the 31st. + cmdbuf[1] := @SCL + cmdbuf := CMD_WRITEPAGE + repeat while cmdbuf + ackbit := cmdbuf[1] + +PUB ReadByte(SCL, devSel, addrReg) : data +'' Read in a single byte of i2c data. Device select code is devSel. Device +'' starting address is addrReg. The device select code is modified using the +'' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. + if ReadPage(SCL, devSel, addrReg, @data, 1) + return -1 + +PUB ReadWord(SCL, devSel, addrReg) : data +'' Read in a single word of i2c data. Device select code is devSel. Device +'' starting address is addrReg. The device select code is modified using the +'' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. + if ReadPage(SCL, devSel, addrReg, @data, 2) + return -1 + +PUB ReadLong(SCL, devSel, addrReg) : data +'' Read in a single long of i2c data. Device select code is devSel. Device +'' starting address is addrReg. The device select code is modified using the +'' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. +'' Note that you can't distinguish between a return value of -1 and true error. + if ReadPage(SCL, devSel, addrReg, @data, 4) + return -1 + +PUB WriteByte(SCL, devSel, addrReg, data) +'' Write out a single byte of i2c data. Device select code is devSel. Device +'' starting address is addrReg. The device select code is modified using the +'' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. + if WritePage(SCL, devSel, addrReg, @data, 1) + return true + return false + +PUB WriteWord(SCL, devSel, addrReg, data) +'' Write out a single word of i2c data. Device select code is devSel. Device +'' starting address is addrReg. The device select code is modified using the +'' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. +'' Note that the word value may not span an EEPROM page boundary. + if WritePage(SCL, devSel, addrReg, @data, 2) + return true + return false + +PUB WriteLong(SCL, devSel, addrReg, data) +'' Write out a single long of i2c data. Device select code is devSel. Device +'' starting address is addrReg. The device select code is modified using the +'' upper 3 bits of the 19 bit addrReg. This returns true if an error occurred. +'' Note that the long word value may not span an EEPROM page boundary. + if WritePage(SCL, devSel, addrReg, @data, 4) + return true + return false + +PUB WriteWait(SCL, devSel, addrReg) : ackbit +'' Wait for a previous write to complete. Device select code is devSel. Device +'' starting address is addrReg. The device will not respond if it is busy. +'' The device select code is modified using the upper 3 bits of the 18 bit addrReg. +'' This returns zero if no error occurred or one if the device didn't respond. + devSel |= addrReg >> 15 & %1110 + Start(SCL) + ackbit := Write(SCL, devSel | Xmit) + Stop(SCL) + return ackbit + +DAT + +'*********************************** +'* Assembly language i2c driver * +'*********************************** + + org +' +' +' Entry +' Wait for a non-zero command and process +cmdloop rdlong t1, par wz + if_z jmp #cmdloop + mov parm1, par + add parm1, #4 + rdlong parm1, parm1 ' Get the address of the parameter list + + rdlong t2, parm1 ' SCL is always the first parameter + add parm1, #4 ' Point to the next parameter + mov scl_bit,#1 + shl scl_bit,t2 + mov sda_bit, scl_bit + shl sda_bit, #1 + + cmp t1, #CMD_READPAGE wz + if_z jmp #ReadPage1 + cmp t1, #CMD_WRITEPAGE wz + if_z jmp #WritePage1 + cmp t1, #CMD_READ wz + if_z jmp #read_byte + cmp t1, #CMD_WRITE wz + if_z jmp #write_byte + cmp t1, #CMD_START wz + if_z jmp #start1 + cmp t1, #CMD_STOP wz + if_z jmp #stop1 + cmp t1, #CMD_INIT wz + if_z jmp #initialize1 + neg parm1, #1 + +ReturnParm mov t1, par + add t1, #4 + wrlong parm1, t1 +signal_ready mov t1, #0 + wrbyte t1, par + jmp #cmdloop + +ReadPage1 call #ReadPageFunc + jmp #ReturnParm +WritePage1 call #WritePageFunc + jmp #ReturnParm +read_byte rdlong parm1, parm1 + call #readbytefunc + jmp #ReturnParm +write_byte rdlong parm1, parm1 + call #writebytefunc + jmp #ReturnParm +start1 call #StartFunc + jmp #ReturnParm +stop1 call #StopFunc + jmp #ReturnParm +initialize1 call #InitializeFunc + jmp #ReturnParm + +'' This routine reads a byte and sends the ACK bit. It assumes the clock +'' and data lines have been low for at least the minimum low clock time. +'' It exits with the clock and data low for the minimum low clock time. +readbytefunc mov ackbit1, parm1 ' Get the ACK bit + mov data1, #0 ' Initialize data byte to zero + andn dira, sda_bit ' Set SDA as input + call #delay + mov count1, #8 ' Set loop count for 8 + +:loop call #delay + or outa, scl_bit ' Set SCL HIGH + call #delay + shl data1, #1 ' data byte left one bit + test sda_bit, ina wz + if_nz or data1, #1 ' Set LSB if input bit is HIGH + andn outa, scl_bit ' Set SCL LOW + call #delay + djnz count1, #:loop + + cmp ackbit1, #0 wz + if_z andn outa, sda_bit ' Set SDA LOW if ACK + if_nz or outa, sda_bit ' Set SDA HIGH if NAK + or dira, sda_bit ' Set SDA as output + call #delay + or outa, scl_bit ' Set SCL HIGH + call #delay + andn outa, scl_bit ' Set SCL LOW + call #delay + mov parm1, data1 ' Return the data byte +readbytefunc_ret ret + +'' This routine writes a byte and reads the ACK bit. It assumes that the clock +'' and data are set as outputs, and the clock has been low for at least half the +'' minimum low clock time. It exits with the clock and data set as outputs, and +'' with the clock low for half the minimum low clock time. +writebytefunc mov data1, parm1 ' Get the data byte + mov count1, #8 ' Set loop count for 8 bits + +:loop shl data1, #1 ' Shift left one bit + test data1, #$100 wz ' Check MSB + if_z andn outa, sda_bit ' Set SDA LOW if zero + if_nz or outa, sda_bit ' Set SDA HIGH if not zero + call #delay + or outa, scl_bit ' Set SCL HIGH + call #delay + andn outa, scl_bit ' Set SCL LOW + call #delay + djnz count1, #:loop + + andn dira, sda_bit ' Set SDA as input + call #delay + or outa, scl_bit ' Set SDA HIGH + call #delay + test sda_bit, ina wz ' Check SDA input + if_z mov ackbit1, #0 ' Set to zero if LOW + if_nz mov ackbit1, #1 ' Set to one if HIGH + andn outa, scl_bit ' Set SCL LOW + call #delay + or dira, sda_bit ' Set SDA as output + mov parm1, ackbit1 ' Return the ack bit +writebytefunc_ret ret + +'' This routine transmits the stop sequence, which consists of the data line +'' going from low to high while the clock is high. It assumes that data and +'' clock are set as outputs, and the clock has been low for half the minimum +'' low clock time. It exits with the clock and data floating high for the +'' minimum high clock time. +stopfunc andn outa, sda_bit ' Set SDA LOW + call #delay + or outa, scl_bit ' Set SCL HIGH + call #delay + or outa, sda_bit ' Set SDA HIGH + call #delay + andn dira, scl_bit ' Float SCL HIGH + andn dira, sda_bit ' Float SDA HIGH +stopfunc_ret ret + +'' This routine transmits the start sequence, which consists of the data line +'' going from high to low while the clock is high. It assumes that the clock +'' and data were floating high for the minimum high clock time, and it exits +'' with the clock and data low for half the minimum low clock time. +startfunc or outa, sda_bit ' Set SDA HIGH + or dira, sda_bit ' Set SDA as output + call #delay + or outa, scl_bit ' Set SCL HIGH + or dira, scl_bit ' Set SCL as output + call #delay + andn outa, sda_bit ' Set SDA LOW + call #delay + andn outa, scl_bit ' Set SCL LOW + call #delay +startfunc_ret ret + +'' This routine puts the I2C bus in a known state. It issues up to nine clock +'' pulses waiting for the input to be in a high state. It exits with the clock +'' driven high and the data floating in the high state for the minimum high +'' clock time. +initializefunc andn dira, sda_bit ' Set SDA as input + or outa, scl_bit ' Set SCL HIGH + or dira, scl_bit ' Set SCL as output + call #delay + mov count1, #9 ' Set for up to 9 loops +:loop andn outa, scl_bit ' Set SCL LOW + call #delay + call #delay + or outa, scl_bit ' Set SCL HIGH + call #delay + test sda_bit, ina wz + if_nz jmp #initializefunc_ret ' Quit if input is HIGH + djnz count1, #:loop +initializefunc_ret ret ' Quit after nine clocks + +'' This routine delays for the minimum high clock time, or half the minimum +'' low clock time. This delay routine is also used for the setup and hold +'' times for the start and stop signals, as well as the output data changes. +delay mov delaycnt, cnt + add delaycnt, #DELAY_CYCLES + waitcnt delaycnt, #0 +delay_ret ret + +'PUB ReadPage(SCL, devSel, addrReg, dataPtr, count) : ackbit +readpagefunc rdlong devsel1, parm1 + add parm1, #4 + rdlong addrreg1, parm1 + add parm1, #4 + rdlong dataptr1, parm1 + add parm1, #4 + rdlong count2, parm1 + +'' Read in a block of i2c data. Device select code is devSel. Device starting +'' address is addrReg. Data address is at dataPtr. Number of bytes is count. +'' The device select code is modified using the upper 3 bits of the 19 bit addrReg. +'' Return zero if no errors or the acknowledge bits if an error occurred. +' devSel |= addrReg >> 15 & %1110 + mov t1, addrreg1 + shr t1, #15 + and t1, #%1110 + or devsel1, t1 +' Start(SCL) ' Select the device & send address + call #startfunc +' ackbit := Write(SCL, devSel | Xmit) + mov parm1, devsel1 + or parm1, #Xmit + call #writebytefunc + mov ackbit2, parm1 +' ackbit := (ackbit << 1) | Write(SCL, addrReg >> 8 & $FF) + mov parm1, addrreg1 + shr parm1, #8 + and parm1, #$ff + call #writebytefunc + shl ackbit2, #1 + or ackbit2, parm1 +' ackbit := (ackbit << 1) | Write(SCL, addrReg & $FF) + mov parm1, addrreg1 + and parm1, #$ff + call #writebytefunc + shl ackbit2, #1 + or ackbit2, parm1 +' Start(SCL) ' Reselect the device for reading + call #startfunc +' ackbit := (ackbit << 1) | Write(SCL, devSel | Recv) + mov parm1, devsel1 + or parm1, #Recv + call #writebytefunc + shl ackbit2, #1 + or ackbit2, parm1 +' repeat count - 1 +' byte[dataPtr++] := Read(SCL, ACK) +' byte[dataPtr++] := Read(SCL, NAK) +:loop cmp count2, #1 wz + if_z mov parm1, #NAK + if_nz mov parm1, #ACK + call #readbytefunc + wrbyte parm1, dataptr1 + add dataptr1, #1 + djnz count2, #:loop + +' Stop(SCL) + call #stopfunc +' return ackbit + mov parm1, ackbit2 +readpagefunc_ret ret + +'PUB WritePage(SCL, devSel, addrReg, dataPtr, count) : ackbit +writepagefunc rdlong devsel1, parm1 + add parm1, #4 + rdlong addrreg1, parm1 + add parm1, #4 + rdlong dataptr1, parm1 + add parm1, #4 + rdlong count2, parm1 + +'' Write out a block of i2c data. Device select code is devSel. Device starting +'' address is addrReg. Data address is at dataPtr. Number of bytes is count. +'' The device select code is modified using the upper 3 bits of the 19 bit addrReg. +'' Most devices have a page size of at least 32 bytes, some as large as 256 bytes. +'' Return zero if no errors or the acknowledge bits if an error occurred. If +'' more than 31 bytes are transmitted, the sign bit is "sticky" and is the +'' logical "or" of the acknowledge bits of any bytes past the 31st. +' devSel |= addrReg >> 15 & %1110 + mov t1, addrreg1 + shr t1, #15 + and t1, #%1110 + or devsel1, t1 +' Start(SCL) ' Select the device & send address + call #startfunc +' ackbit := Write(SCL, devSel | Xmit) + mov parm1, devsel1 + or parm1, #Xmit + call #writebytefunc + mov ackbit2, parm1 +' ackbit := (ackbit << 1) | Write(SCL, addrReg >> 8 & $FF) + mov parm1, addrreg1 + shr parm1, #8 + and parm1, #$ff + call #writebytefunc + shl ackbit2, #1 + or ackbit2, parm1 +' ackbit := (ackbit << 1) | Write(SCL, addrReg & $FF) + mov parm1, addrreg1 + and parm1, #$ff + call #writebytefunc + shl ackbit2, #1 + or ackbit2, parm1 +' repeat count ' Now send the data +' ackbit := ackbit << 1 | ackbit & $80000000 ' "Sticky" sign bit +' ackbit |= Write(SCL, byte[dataPtr++]) +:loop shl ackbit2, #1 wc + if_c or ackbit2, signbit + rdbyte parm1, dataptr1 + add dataptr1, #1 + call #writebytefunc + or ackbit2, parm1 + djnz count2, #:loop +' Stop(SCL) + call #stopfunc +' return ackbit + mov parm1, ackbit2 +writepagefunc_ret ret + +signbit long $80000000 +scl_bit res 1 +sda_bit res 1 +count1 res 1 +t1 res 1 +t2 res 1 +data1 res 1 +ackbit1 res 1 +delaycnt res 1 +parm1 res 1 +devsel1 res 1 +addrreg1 res 1 +dataptr1 res 1 +count2 res 1 +ackbit2 res 1 + +{{ + TERMS OF USE: MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +}} \ No newline at end of file