I2CSlave test program. I2CSlave library has some improper behavior, so this program is able to watch that. The workaround for this behavior, only for NXP device, is wrote in 'I2CSlave_mod_NXP.cpp'.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2CSlave_mod_NXP.cpp Source File

I2CSlave_mod_NXP.cpp

00001 #include "I2CSlave_mod_NXP.h"
00002 
00003 #define I2C_CONSET(x)       (x->i2c->CONSET)
00004 #define I2C_CONCLR(x)       (x->i2c->CONCLR)
00005 #define I2C_DAT(x)          (x->i2c->DAT)
00006 #define I2C_STAT(x)         (x->i2c->STAT)
00007 
00008 static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
00009     I2C_CONCLR(obj) = (start << 5)
00010                     | (stop << 4)
00011                     | (interrupt << 3)
00012                     | (acknowledge << 2);
00013 }
00014 
00015 // Clear the Serial Interrupt (SI)
00016 static inline void i2c_clear_SI(i2c_t *obj) {
00017     i2c_conclr(obj, 0, 0, 1, 0);
00018 }
00019 
00020 static inline int i2c_status(i2c_t *obj) {
00021     return I2C_STAT(obj);
00022 }
00023 
00024 // Wait until the Serial Interrupt (SI) is set
00025 static int i2c_wait_SI(i2c_t *obj) {
00026     int timeout = 0;
00027     while (!(I2C_CONSET(obj) & (1 << 3))) {
00028         timeout++;
00029         if (timeout > 100000) return -1;
00030     }
00031     return 0;
00032 }
00033 
00034 
00035 I2CSlave_mod::I2CSlave_mod(PinName sda, PinName scl) : I2CSlave(sda, scl) {
00036 }
00037 
00038 
00039 int I2CSlave_mod::read(char *data, int length) {
00040     return i2c_slave_read_mod(&_i2c, data, length) != length;
00041 }
00042 
00043 
00044 int I2CSlave_mod::i2c_slave_read_mod(i2c_t *obj, char *data, int length) {
00045     int count = 0;
00046     int status;
00047     
00048     do {
00049         if((status == 0x80) || (status == 0x90)) {
00050             data[count] = I2C_DAT(obj) & 0xFF;
00051             count++;
00052         }
00053         i2c_clear_SI(obj);
00054         i2c_wait_SI(obj);
00055         status = i2c_status(obj);
00056     } while (((status == 0x80) || (status == 0x90) ||
00057             (status == 0x060) || (status == 0x70)) && (count < length));
00058     
00059     if(status != 0xA0) {
00060         i2c_stop(obj);
00061     }
00062     
00063     i2c_clear_SI(obj);
00064     
00065     return count;
00066 }