// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // IASI2 interface specifically for the BV4113, this is because the // BV4113 uses a diffferent command (2 CRTL B) to show inverted devices. // All of the other IASI-2 devices use command 4 followed by command 1 // This library is use for the new IASI version 2 devices // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // HISTORY: // Dec 2008 Version b of this libraty stored the o/p from the device // or devices to a buffer, i-buffer // REQUIRED: // #URL-lib "http://pin1.org/forthlib/flb/General/soft1.flb" // #URL-lib "http://pin1.org/forthlib/flb/General/strings.flb" // CONSTANTS: &E0010000 constant U1DLL &E0010004 constant U1DLM &E001000C constant U1LCR 62 constant I-ACK // '>' 20 constant BMAX BMAX vspace$ i-buffer // o/p goes into here // ----------------------------------------------------- // Communication set up for UART1 // set baud rate with 1 stop and 8 data // no parity // Baud rates for IASO2 devices are seleceted from // 9600, 14400, 19200 and 38400 : baud1 { rate --- } rate 16 * 10 / // multiply rate by 1.6 PCLK swap / // divide by PCLK 5 + 10 / // round up and div by 10 256 u/mod &83 U1LCR ! // 2 stop 8 bits (&87 is 2 stop bit) U1DLM ! // high divisor U1DLL ! // low devisor &3 U1LCR ! // DLAB=0, 1 stop 8 data ; // ----------------------------------------------------- // returns baud rate for device 1 // ( --- rate ) : baud1@ &83 U1LCR ! // access to U1DLM,LL U1DLM @ // high divisor 256 * U1DLL @ // low devisor + &3 U1LCR ! // DLAB=0, 1 stop 8 data // now calculate from these, baud rate 16 * pclk swap u/mod swap drop ; // ----------------------------------------------------- // used for terminating a command, typical use is // after sending command, example i.' BT"fred"' cr1 : cr1 13 emit1 ; // ----------------------------------------------------- // Send string to IASI device using UART1 // addr is the address of a 0 terminated string // max string length 255 chars : stype1 { addr --- } addr 255 + // end addr // start do i c@ 0= if leave else i c@ emit1 then next ; // ----------------------------------------------------- // This is the same as u. but uses emit1 and // stype1 to print to UART1 // prints n as ASCII // ( n --- ) : iu. <# #s #> stype1 ; // ----------------------------------------------------- // gets a key form UART1 and will time out // if no key is available. This saves complex // code using key1? and prevents system // crashing, set for time out of 50ms. // It also has another purpose in that it will wait for a // device to respond to a command // meant for ASCII, return 0 if not valid // ( --- r-val ) : i-in 0 50000 for key1? if drop key1 leave then next ; // ----------------------------------------------------- // expects I-ACK in input stream, returns true if there : i-ack? ( -- t/f) i-in I-ACK = ; // ----------------------------------------------------- // waits for device to respond and fills i-buffer // returns when ACK is recieved or times out : i-send ( -- [i-buffer] ) int#: bcount 0 0 i-buffer c! // empty buffer begin i-in ?dup 0 <> while dup // for I-ACK test i-buffer bcount + c! // store 1 +> bcount bcount BMAX > if ." buffer full" abort then I-ACK = if 0 i-buffer bcount 1 + + c! // terminate escape then // finished when I_ACK recieved repeat 0 i-buffer bcount 1 + + c! // terminate ; // ----------------------------------------------------- // prints contents of i-buffer if any // contents are terminated by 0 // ( --- ) : i-buff. i-buffer stype ; // ----------------------------------------------------- // clear buffer contents. // ( --- ) : i-cbuff BMAX for 0 i i-buffer + c! next // and hw buffer key1? if begin key1 drop key1? 0= until then ; // ----------------------------------------------------- // sends CR to establish the baud rate and then inverts // all connected devices // ( --- ) : i-autobaud 3 for cr1 10 ms next 10 ms 4 emit1 cr1 // set to non-inverted mode 100 ms // device needs time to set i-cbuff ; // ----------------------------------------------------- // determins number of devices connected // use i-connect for initialisation as this also establishes // the Baud rate *** for BV4113 : i-ndev ( -- #devices ) int#: devices 0 i-cbuff // clear buffer 2 emit1 cr1 // send broadcast *** 780 ms // all device range i-send // now fill buffer -1 // buffer increment begin 1+ dup i-buffer + c@ ?dup 0 <> while I-ACK = if 1 +> devices then // count ack's repeat drop // buffer count devices ; // ----------------------------------------------------- // Initialise, Initialises devices connected, and returns // number of devices connected. i-buffer will contain the // string with the devices in : i-connect ( -- devices) i-autobaud i-ndev ; // ----------------------------------------------------- // determins if a particular device is connected // returns -1 if so // 97 i-device will return 1 if 'a' is connected // 0 otherwise : i-device { address -- 1|0 } int#: found 0 i-ndev // fill buffer if -1 // buffer increment begin 1+ dup i-buffer + c@ ?dup 0 <> while address = if 1 +> found then // count ack's repeat drop // buffer count found // leave result else ." No devices connected" 0 // leave 0 then ; // ----------------------------------------------------- // Command interface // ----------------------------------------------------- // ----------------------------------------------------- // Reset all devices, establish baud rate and return // number of devices connected : i-resetall ( -- devices) 3 emit1 cr1 // reset i-connect // does rest ; // ----------------------------------------------------- // sets address -- only one device should be connected // otherwise this will not work // : i-setaddress { old new -- t/f } i-cbuff old emit1 [char] U emit1 cr1 // unlock // U command does not return I-ACK old emit1 [char] A emit1 new emit1 i-ack? ; // ----------------------------------------------------- // write to EEPROM as text, the command example is // aB10 'hello' // need to supply an address where the text is so this // would work: // 97 10 s" 'hello'" i-commandB : i-commandB { adr eeadr text -- t/f} i-cbuff adr emit1 [char] B emit1 eeadr iu. // send as ASCII coded number text stype1 cr1 i-ack? ; // ----------------------------------------------------- // turn off I-ACK (not a good idea for these commands) : i-commandC ( addr -- t/f) i-cbuff emit1 [char] C emit1 cr1 i-ack? ; // ----------------------------------------------------- // delay device, note ACK does not come back until // after delay so will wait here until ack is returned : i-commandD ( addr -- t/f ) emit1 [char] D emit1 iu. cr1 begin i-ack? -1 = until ; // ----------------------------------------------------- // turn off error reporting : i-commandE ( addr -- t/f) i-cbuff emit1 [char] E emit1 cr1 i-ack? ; // ----------------------------------------------------- // factory reset no re-initialisation is required after // this command // the command is aFYeS : i-commandF ( addr -- t/f) i-cbuff emit1 [char] F emit1 [char] Y emit1 [char] e emit1 [char] S emit1 cr1 i-ack? ; // ----------------------------------------------------- // read from eeprom, the device command is // aG10 3 where 10 is the start address and 3 is the number // of bytes to read. This will put the bytes in the i/p // buffer and can be read by i-in : i-commandG { adr start bytes -- } adr emit1 [char] G emit1 start iu. bytes iu. ; // ----------------------------------------------------- // used for interfacing with device, see i-send // and i-get, this word is not used on its own // it gets and sends to UART1 the text in the TIB // which is the text following the word : (i-ipb) i-cbuff // clear ipb 13 word // get i/p from stream stype1 // send word to uart1 cr1 // get IASI to process it ; // ----------------------------------------------------- // utility for sending and receiving from UART2 // sends text following word, must all be on 1 line // use: I-SENDIT bt"hello" // must be a space following the D of send // ( --- ) : i-sendit (i-ipb) i-buff. // print result cr ; // ----------------------------------------------------- // Report on the connected devices : i-report i-connect cr ." Number of devices connected " u. i-buff. ; // ----------------------------------------------------- // Utilities // ----------------------------------------------------- // ----------------------------------------------------- // gets a decimal number stored in i-buffer and terminated // by I-ACK, e.g. 255> will return 255 // returns number and -1 if there is a number else returns // just 0 : i-gn ( -- num, -1 | 0 ) int: bc num mult 0 => num 1 => mult i-buffer 0 I-ACK instr$ // find ack dup => bc 0 <> // okay if begin -1 +> bc // work backwards bc i-buffer + c@ 48 - // ascii > decimal mult * +> num mult 10 * => mult bc 0= until num -1 else 0 then ; : x i-connect ;