// oNMD_Coproc.osc // // Floating-point co-processor routines // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Contributors: // Neil Durant oSPI pak2 = new oSPI; oWord wordX = new oWord; oByte byte8 = new oByte; oMathO highByte = new oMathO; byte byteX; byte status; byte f0; byte f1; byte f2; byte f3; // Constants holding PAK-II commands const CMD_LOADX = &H01; const CMD_LOADY = &H02; const CMD_READX = &H03; const CMD_SWAP = &H04; const CMD_DIGIT = &H05; const CMD_IEEECVT = &H06; const CMD_FLOAT = &H07; const CMD_FLOAT_ALT = &H87; const CMD_COMMCK = &H08; const CMD_FPCVT = &H09; const CMD_CSH = &H0A; const CMD_INT = &H0B; const CMD_INT_ALT = &H8B; const CMD_MUL = &H0C; const CMD_DIV = &H0D; const CMD_SUB = &H0E; const CMD_SUB_ALT = &H8E; const CMD_ADD = &H0F; const CMD_OPT = &H10; const CMD_ABS = &H11; const CMD_STO = &H12; const CMD_RCL = &H13; const CMD_DIRA = &H14; const CMD_DIRB = &H94; const CMD_RIOA = &H15; const CMD_RIOB = &H95; const CMD_WIOA = &H16; const CMD_WIOB = &H96; const CMD_XTOY = &H17; const CMD_YTOX = &H18; const CMD_SQRT = &H19; const CMD_LOG = &H1A; const CMD_LOG10 = &H1B; const CMD_EXP = &H1C; const CMD_EXP10 = &H1D; const CMD_POW = &H1E; const CMD_ROOT = &H1F; const CMD_RECIP = &H20; const CMD_SIN = &H21; const CMD_COS = &H22; const CMD_TAN = &H23; const CMD_ASIN = &H24; const CMD_ACOS = &H25; const CMD_ATAN = &H26; const CMD_POLY = &H27; Sub void main(void) { pak2.IOLineC = 30; // Clock pin on OOPIC pak2.IOLineO = 29; // Data pin on OOPIC pak2.IOLineI = 0; // Indicates input/output on same pin pak2.Width = cv8bit; pak2.Direction = cvMSBFirst; pak2.Mode = 0; // Sample data before clock pak2.Rate = 0; // 12kHz pak2.Operate = cvTrue; wordX.Signed = cvTrue; byte8 = 8; highByte.Input1.Link(wordX); highByte.Input2.Link(byte8); highByte.Mode = 3; // RShift highByte.Operate = cvTrue; } // Reset function for sending the reset sequence to the PAK-II // Sub void Reset(void) { pak2.IOLineC.Low; pak2.IOLineO.Low; pak2.IOLineC.High; pak2.IOLineO.High; pak2.IOLineC.Low; pak2.IOLineO.Low; } // Waits until the data line becomes low. // This can be used to determine when the PAK-II is ready to send // Sub void WaitForDataLow(void) { while(pak2.IOLineO) { } } // Reads a single byte from the PAK-II, // storing the value in byteX // Sub void ReadByte(void) { // The OOPIC oSPI object appears to leave the data pin low // after sending. Because we are using the same pin for // input and output, the pin should be left floating, and // pulled high with a resistor. To force the oSPI object // to allow the pin to go high, we NEED to issue the // following command before being able to read: pak2.IOLineO.High; // Now read the byte byteX = pak2; } ////////////////////////////////////////////////////////////////////// // Functions for sending commands to the PAK-II ////////////////////////////////////////////////////////////////////// // Loads the X-register of the PAK-II // with the values in f0-f3 // Sub void LoadX(byte fx3, byte fx2, byte fx1, byte fx0) { pak2 = CMD_LOADX; pak2 = fx3; pak2 = fx2; pak2 = fx1; pak2 = fx0; } // Loads the Y-register of the PAK-II // with the values in f0-f3 // Sub void LoadY(byte fy3, byte fy2, byte fy1, byte fy0) { pak2 = CMD_LOADY; pak2 = fy3; pak2 = fy2; pak2 = fy1; pak2 = fy0; } // Reads the X register from the PAK-II, // storing the value in f0-f3 // Sub void ReadX(void) { pak2 = CMD_READX; pak2.IOLineO.High; f3 = pak2; f2 = pak2; f1 = pak2; f0 = pak2; } // Swaps the X and Y registers // Sub void Swap(void) { pak2 = CMD_SWAP; } // TODO: Implement Digit() // TODO: Implement IeeeCvt() // Converts the 24 bit integer stored in X to floating point // Sub void Float(void) { pak2 = CMD_FLOAT; pak2.IOLineO.High; status = pak2; } // Converts the 24 bit integer stored in X to floating point // Does not check status // Sub void Float_Alt(void) { pak2 = CMD_FLOAT_ALT; } // Sends the COMMCK command to the PAK-II. // The PAK-II should respond with the byte hex 2B. // The value returned is stored in status. // Sub void COMMCK(void) { pak2 = CMD_COMMCK; pak2.IOLineO.High; status = pak2; } // TODO: Implement FpCvt() // TODO: Implement Chs() // Converts X to a 24 bit integer // Success/failure returned in status // Sub void Int(void) { pak2 = CMD_INT; pak2.IOLineO.High; status = pak2; } // Converts X to a 24 bit integer // Does not check status // Sub void Int_Alt(void) { pak2 = CMD_INT_ALT; } // X = X*Y // Success/failure returned in status // Sub void Mul(void) { pak2 = CMD_MUL; pak2.IOLineO.High; status = pak2; } // X = X/Y // Success/failure returned in status // Sub void Div(void) { pak2 = CMD_DIV; pak2.IOLineO.High; status = pak2; } // X = X - Y // Success/failure returned in status // Sub void Subtract(void) { pak2 = CMD_SUB; pak2.IOLineO.High; status = pak2; } // X = X - Y // Status not checked // Sub void Subtract_Alt(void) { pak2 = CMD_SUB_ALT; } // X = X + Y // Success/failure returned in status // Sub void Add(void) { pak2 = CMD_ADD; pak2.IOLineO.High; status = pak2; } // TODO: Implement Opt() // TODO: Implement Abs() // Store X into a register // Sub void Store(byte regStore) { pak2 = CMD_STO; pak2 = regStore; } // Store register value in X // Sub void Recall(byte regRecall) { pak2 = CMD_RCL; pak2 = regRecall; } // Sets the directions of the I/O pins on port A // 1 = input, 0 = output // Sub void DirA(byte dirabits) { pak2 = CMD_DIRA; pak2 = dirabits; } // Sets the directions of the I/O pins on port B // 1 = input, 0 = output // Sub void DirB(byte dirbbits) { pak2 = CMD_DIRB; pak2 = dirbbits; } // Reads the values of the I/O pins on port A // Returns the value in byteX // Sub void RioA(void) { pak2 = CMD_RIOA; pak2.IOLineO.High; byteX = pak2; } // Reads the values of the I/O pins on port B // Returns the value in byteX // Sub void RioB(void) { pak2 = CMD_RIOB; pak2.IOLineO.High; byteX = pak2; } // Sets the values of the I/O pins on port A // Sub void WioA(byte wioabits) { pak2 = CMD_WIOA; pak2 = wioabits; } // Sets the values of the I/O pins on port B // Sub void WioB(byte wiobbits) { pak2 = CMD_WIOB; pak2 = wiobbits; } // Y = X // Sub void XtoY(void) { pak2 = CMD_XTOY; } // X = Y // Sub void YtoX(void) { pak2 = CMD_YTOX; } // TODO: Implement Sqrt() // TODO: Implement Log() // TODO: Implement Log10() // TODO: Implement Exp() // TODO: Implement Exp10() // TODO: Implement Pow() // TODO: Implement Root() // TODO: Implement Recip() // TODO: Implement Sin() // TODO: Implement Cos() // TODO: Implement Tan() // TODO: Implement ASin() // TODO: Implement ACos() // TODO: Implement ATan() // TODO: Implement Poly() ////////////////////////////////////////////////////////////////////// // Additional PAK-II routines ////////////////////////////////////////////////////////////////////// // Loads the X-register of the PAK-II with the 16-bit signed integer // passed in via wordX // Sub void LoadXFromWord(void) { pak2 = CMD_LOADX; pak2 = 0; // MSB is zero pak2 = (wordX.MSB) * 255; // Insert sign pak2 = highByte; // High byte pak2 = wordX & 255; // Low byte } // Reads the X-register of the PAK-II as a 16-bit unsigned integer. // The value is returned via wordX // Sub void ReadXAsWord(void) { word dummy; pak2 = CMD_READX; pak2.IOLineO.High; // To speed up the operation we can read in two 16-bit words pak2.Width = cv16bit; dummy = pak2; wordX = pak2; if(dummy & 128) { wordX = wordX | &H8000; } pak2.Width = cv8bit; } // End of oNMD_Coproc.osc