The iPod controller that I submitted for the mbed challenge

Dependencies:   mbed Motordriver PID

user_interface/async_i2c.h

Committer:
networker
Date:
2011-05-04
Revision:
0:371773dd3dd1

File content as of revision 0:371773dd3dd1:

#ifndef ASYNC_I2C_H
#define ASYNC_I2C_H

enum i2c_status { i2c_ok, i2c_busy, i2c_nack, i2c_pending};
class async_i2c;

class i2c_buffer {
    async_i2c* _intf;
    char _adr;
    char *_data;
    int _size;
    i2c_buffer *_next;
    bool _copy;
    bool (*notification)(i2c_buffer*);
    i2c_status stat;
public:
    i2c_buffer(async_i2c* intf, char adr, char* data, int size, bool copy=false, i2c_buffer *next=0): _intf(intf), _adr(adr), _data(data), _size(size), _copy(copy), _next(next) {
        if (copy) {
            _data = new char[size];
            memcpy(_data, data, size);
        }
        stat = i2c_pending;
        notification = 0;
    }
    ~i2c_buffer() {
        if (_copy) delete[] _data;
        _data = 0;
        if (_next) delete _next;
    }
    void set_notification(bool (*fun)(i2c_buffer*)) {
        if (stat==i2c_pending) notification = fun;
        else fun(this);
    }
    //notify is the callback when the transfer has finished
    bool notify() {
        bool result = true;
        i2c_buffer *buf = _next;
        if (notification)
            result = notification(this);
        if (_intf && _next){
            _intf->process(_next);
            }
        else
            _intf->releasybusy();
        return result;
    }
    friend async_i2c;
};

class async_i2c: public I2C { //for now based on the sync i2c and hence not async, in the future should be bare metal and completely async
public:
    typedef void trans_end(i2c_status stat, char *data, bool stop);
private:
    bool busy, _stop;
    trans_end *_we, *_re;
    i2c_status _stat;
    void process(i2c_buffer*);
public:
    async_i2c(PinName sda, PinName scl): I2C(sda, scl) {
        busy = false;
        _stop = true;
        _we = 0;
        _re = 0;
        _stat = i2c_ok;
    }
    void frequency(int rate) {
        I2C::frequency(rate);
    }
    i2c_status write(char address, char *data, int size, bool stop=true);
    i2c_status read(char address, char *data, int size, bool stop=true);
    i2c_buffer* write(char address, char *data, int size, bool copy=false, i2c_buffer *b=0);
    i2c_buffer* read(char address, char *data, int size, bool copy=false, i2c_buffer *b=0);
    i2c_buffer* read(char address, char reg, char *data, int size, bool copy=false);
    void write_end(trans_end *cb) {
        _we = cb;
    }
    void read_end(trans_end *cb) {
        _re = cb;
    }
    bool isbusy() {
        return busy;
    }

protected:
    bool testbusy() {
        __disable_irq();
        if (busy && _stop) {
            __enable_irq();
            return true;
        }
        busy = true;
        __enable_irq();
        return false;
    }
    void releasebusy(bool stop=true) {
        _stop = stop;
        if (stop) busy = false;
    }
};

#endif