Embedded system Fun Blog
























































Find out all the best information, libraries and circuit about the latest Embedded systems.
Showing posts with label DAC. Show all posts
Showing posts with label DAC. Show all posts

Sunday, 8 January 2012

MBED: RemoteIR and TransmitterIR using DAC

.info: http://mbed.org/users/shintamainjp/libraries/RemoteIR/lg7h90

XxXxXxXxXxXxXxXxXxXxXxXxXxXx ReceiverIR.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXx

/**
 * IR receiver (Version 0.0.4)
 *
 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
 * http://shinta.main.jp/
 */

#include "ReceiverIR.h"

#define LOCK()
#define UNLOCK()

#define InRange(x,y)   ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3)))

/**
 * Constructor.
 *
 * @param rxpin Pin for receive IR signal.
 */
ReceiverIR::ReceiverIR(PinName rxpin) : evt(rxpin) {
    init_state();
    evt.fall(this, &ReceiverIR::isr_fall);
    evt.rise(this, &ReceiverIR::isr_rise);
    evt.mode(PullUp);
    ticker.attach_us(this, &ReceiverIR::isr_wdt, 10 * 1000);
}

/**
 * Destructor.
 */
ReceiverIR::~ReceiverIR() {
}

/**
 * Get state.
 *
 * @return Current state.
 */
ReceiverIR::State ReceiverIR::getState() {
    LOCK();
    State s = work.state;
    UNLOCK();
    return s;
}

/**
 * Get data.
 *
 * @param format Pointer to format.
 * @param buf Buffer of a data.
 * @param bitlength Bit length of the buffer.
 *
 * @return Data bit length.
 */
int ReceiverIR::getData(RemoteIR::Format *format, uint8_t *buf, int bitlength) {
    LOCK();

    if (bitlength < data.bitcount) {
        UNLOCK();
        return -1;
    }

    const int nbits = data.bitcount;
    const int nbytes = data.bitcount / 8 + (((data.bitcount % 8) != 0) ? 1 : 0);
    *format = data.format;
    for (int i = 0; i < nbytes; i++) {
        buf[i] = data.buffer[i];
    }

    init_state();

    UNLOCK();
    return nbits;
}

void ReceiverIR::init_state(void) {
    work.c1 = -1;
    work.c2 = -1;
    work.c3 = -1;
    work.d1 = -1;
    work.d2 = -1;
    work.state = Idle;
    data.format = RemoteIR::UNKNOWN;
    data.bitcount = 0;
    timer.stop();
    timer.reset();
    for (int i = 0; i < sizeof(data.buffer); i++) {
        data.buffer[i] = 0;
    }
}

void ReceiverIR::isr_wdt(void) {
    LOCK();
    static int cnt = 0;
    if ((Idle != work.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3) || (0 <= work.d1) || (0 <= work.d2))) {
        cnt++;
        if (cnt > 50) {
#if 0
            printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
                   work.c1,
                   work.c2,
                   work.c3,
                   work.d1,
                   work.d2,
                   work.state,
                   data.format,
                   data.bitcount);
#endif
            init_state();
            cnt = 0;
        }
    } else {
        cnt = 0;
    }
    UNLOCK();
}

void ReceiverIR::isr_fall(void) {
    LOCK();
    switch (work.state) {
        case Idle:
            if (work.c1 < 0) {
                timer.start();
                work.c1 = timer.read_us();
            } else {
                work.c3 = timer.read_us();
                int a = work.c2 - work.c1;
                int b = work.c3 - work.c2;
                if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 8)) {
                    /*
                     * NEC.
                     */
                    data.format = RemoteIR::NEC;
                    work.state = Receiving;
                    data.bitcount = 0;
                } else if (InRange(a, RemoteIR::TUS_NEC * 16) && InRange(b, RemoteIR::TUS_NEC * 4)) {
                    /*
                     * NEC Repeat.
                     */
                    data.format = RemoteIR::NEC_REPEAT;
                    work.state = Received;
                    data.bitcount = 0;
                    work.c1 = -1;
                    work.c2 = -1;
                    work.c3 = -1;
                    work.d1 = -1;
                    work.d2 = -1;
                } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 4)) {
                    /*
                     * AEHA.
                     */
                    data.format = RemoteIR::AEHA;
                    work.state = Receiving;
                    data.bitcount = 0;
                } else if (InRange(a, RemoteIR::TUS_AEHA * 8) && InRange(b, RemoteIR::TUS_AEHA * 8)) {
                    /*
                     * AEHA Repeat.
                     */
                    data.format = RemoteIR::AEHA_REPEAT;
                    work.state = Received;
                    data.bitcount = 0;
                    work.c1 = -1;
                    work.c2 = -1;
                    work.c3 = -1;
                    work.d1 = -1;
                    work.d2 = -1;
                } else {
                    init_state();
                }
            }
            break;
        case Receiving:
            if (RemoteIR::NEC == data.format) {
                work.d2 = timer.read_us();
                int a = work.d2 - work.d1;
                if (InRange(a, RemoteIR::TUS_NEC * 3)) {
                    data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
                } else if (InRange(a, RemoteIR::TUS_NEC * 1)) {
                    data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
                }
                data.bitcount++;
#if 0
                /*
                 * Length of NEC is always 32 bits.
                 */
                if (32 <= data.bitcount) {
                    data.state = Received;
                    work.c1 = -1;
                    work.c2 = -1;
                    work.c3 = -1;
                    work.d1 = -1;
                    work.d2 = -1;
                }
#else
                /*
                 * Set timeout for tail detection automatically.
                 */
                timeout.detach();
                timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_NEC * 5);
#endif
            } else if (RemoteIR::AEHA == data.format) {
                work.d2 = timer.read_us();
                int a = work.d2 - work.d1;
                if (InRange(a, RemoteIR::TUS_AEHA * 3)) {
                    data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
                } else if (InRange(a, RemoteIR::TUS_AEHA * 1)) {
                    data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
                }
                data.bitcount++;
#if 0
                /*
                 * Typical length of AEHA is 48 bits.
                 * Please check a specification of your remote controller if you find a problem.
                 */
                if (48 <= data.bitcount) {
                    data.state = Received;
                    work.c1 = -1;
                    work.c2 = -1;
                    work.c3 = -1;
                    work.d1 = -1;
                    work.d2 = -1;
                }
#else
                /*
                 * Set timeout for tail detection automatically.
                 */
                timeout.detach();
                timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_AEHA * 5);
#endif
            } else if (RemoteIR::SONY == data.format) {
                work.d1 = timer.read_us();
            }
            break;
        case Received:
            break;
        default:
            break;
    }
    UNLOCK();
}

void ReceiverIR::isr_rise(void) {
    LOCK();
    switch (work.state) {
        case Idle:
            if (0 <= work.c1) {
                work.c2 = timer.read_us();
                int a = work.c2 - work.c1;
                if (InRange(a, RemoteIR::TUS_SONY * 4)) {
                    data.format = RemoteIR::SONY;
                    work.state = Receiving;
                    data.bitcount = 0;
                } else {
                    static const int MINIMUM_LEADER_WIDTH = 150;
                    if (a < MINIMUM_LEADER_WIDTH) {
                        init_state();
                    }
                }
            } else {
                init_state();
            }
            break;
        case Receiving:
            if (RemoteIR::NEC == data.format) {
                work.d1 = timer.read_us();
            } else if (RemoteIR::AEHA == data.format) {
                work.d1 = timer.read_us();
            } else if (RemoteIR::SONY == data.format) {
                work.d2 = timer.read_us();
                int a = work.d2 - work.d1;
                if (InRange(a, RemoteIR::TUS_SONY * 2)) {
                    data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8));
                } else if (InRange(a, RemoteIR::TUS_SONY * 1)) {
                    data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8));
                }
                data.bitcount++;
#if 0
                /*
                 * How do I know the correct length? (6bits, 12bits, 15bits, 20bits...)
                 * By a model only?
                 * Please check a specification of your remote controller if you find a problem.
                 */
                if (12 <= data.bitcount) {
                    data.state = Received;
                    work.c1 = -1;
                    work.c2 = -1;
                    work.c3 = -1;
                    work.d1 = -1;
                    work.d2 = -1;
                }
#else
                /*
                 * Set timeout for tail detection automatically.
                 */
                timeout.detach();
                timeout.attach_us(this, &ReceiverIR::isr_timeout, RemoteIR::TUS_SONY * 4);
#endif
            }
            break;
        case Received:
            break;
        default:
            break;
    }
    UNLOCK();
}

void ReceiverIR::isr_timeout(void) {
    LOCK();
#if 0
    printf("# TIMEOUT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n",
           work.c1,
           work.c2,
           work.c3,
           work.d1,
           work.d2,
           work.state,
           data.format,
           data.bitcount);
#endif
    if (work.state == Receiving) {
        work.state = Received;
        work.c1 = -1;
        work.c2 = -1;
        work.c3 = -1;
        work.d1 = -1;
        work.d2 = -1;
    }
    UNLOCK();
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXx ReceiverIR.h XxXxXxXxXxXxXxXxXxXxXxXxXxXx

/**
 * IR receiver (Version 0.0.4)
 *
 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
 * http://shinta.main.jp/
 */

#ifndef _RECEIVER_IR_H_
#define _RECEIVER_IR_H_

#include <mbed.h>

#include "RemoteIR.h"

/**
 * IR receiver class.
 */
class ReceiverIR {
public:

    /**
     * Constructor.
     *
     * @param rxpin Pin for receive IR signal.
     */
    explicit ReceiverIR(PinName rxpin);
   
    /**
     * Destructor.
     */
    ~ReceiverIR();

    /**
     * State.
     */
    typedef enum {
        Idle,
        Receiving,
        Received
    } State;
   
    /**
     * Get state.
     *
     * @return Current state.
     */
    State getState();
   
    /**
     * Get data.
     *
     * @param format Pointer to format.
     * @param buf Buffer of a data.
     * @param bitlength Bit length of the buffer.
     *
     * @return Data bit length.
     */
    int getData(RemoteIR::Format *format, uint8_t *buf, int bitlength);
   
private:
   
    typedef struct {
        RemoteIR::Format format;
        int bitcount;
        uint8_t buffer[64];
    } data_t;
   
    typedef struct {
        State state;
        int c1;
        int c2;
        int c3;
        int d1;
        int d2;
    } work_t;

    InterruptIn evt;    /**< Interrupt based input for input. */
    Timer timer;        /**< Timer for WDT. */
    Ticker ticker;      /**< Tciker for tick. */
    Timeout timeout;    /**< Timeout for tail. */

    data_t data;
    work_t work;
   
    void init_state(void);

    void isr_wdt(void);
    void isr_fall(void);
    void isr_rise(void);
   
    /**
     * ISR timeout for tail detection.
     */
    void isr_timeout(void);

};

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXx TransmitterIR.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXx

/**
 * IR transmitter (Version 0.0.4)
 *
 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
 * http://shinta.main.jp/
 */

#include "TransmitterIR.h"

#define LOCK()
#define UNLOCK()

/**
 * Constructor.
 *
 * @param txpin Pin for transmit IR signal.
 */
TransmitterIR::TransmitterIR(PinName txpin) : tx(txpin) {
    tx.write(0.0);
    tx.period_us(26.3);

    work.state = Idle;
    work.bitcount = 0;
    work.leader = 0;
    work.data = 0;
    work.trailer = 0;

    data.format = RemoteIR::UNKNOWN;
    data.bitlength = 0;
}

/**
 * Destructor.
 */
TransmitterIR::~TransmitterIR() {
}

/**
 * Get state.
 *
 * @return Current state.
 */
TransmitterIR::State TransmitterIR::getState(void) {
    LOCK();
    State s = work.state;
    UNLOCK();
    return s;
}

/**
 * Set data.
 *
 * @param format Format.
 * @param buf Buffer of a data.
 * @param bitlength Bit length of the data.
 *
 * @return Data bit length.
 */
int TransmitterIR::setData(RemoteIR::Format format, uint8_t *buf, int bitlength) {
    LOCK();
    if (work.state != Idle) {
        UNLOCK();
        return -1;
    }

    work.state = Leader;
    work.bitcount = 0;
    work.leader = 0;
    work.data = 0;
    work.trailer = 0;

    data.format = format;
    data.bitlength = bitlength;
    const int n = bitlength / 8 + (((bitlength % 8) != 0) ? 1 : 0);
    for (int i = 0; i < n; i++) {
        data.buffer[i] = buf[i];
    }

    switch (format) {
        case RemoteIR::NEC:
            ticker.detach();
            ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_NEC);
            break;
        case RemoteIR::AEHA:
            ticker.detach();
            ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_AEHA);
            break;
        case RemoteIR::SONY:
            ticker.detach();
            ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_SONY);
            break;
    }

    UNLOCK();
    return bitlength;
}

void TransmitterIR::tick(void) {
    LOCK();
    switch (work.state) {
        case Idle:
            work.bitcount = 0;
            work.leader = 0;
            work.data = 0;
            work.trailer = 0;
            break;
        case Leader:
            if (data.format == RemoteIR::NEC) {
                /*
                 * NEC.
                 */
                static const int LEADER_NEC_HEAD = 16;
                static const int LEADER_NEC_TAIL = 8;
                if (work.leader < LEADER_NEC_HEAD) {
                    tx.write(0.5);
                } else {
                    tx.write(0.0);
                }
                work.leader++;
                if ((LEADER_NEC_HEAD + LEADER_NEC_TAIL) <= work.leader) {
                    work.state = Data;
                }
            } else if (data.format == RemoteIR::AEHA) {
                /*
                 * AEHA.
                 */
                static const int LEADER_AEHA_HEAD = 8;
                static const int LEADER_AEHA_TAIL = 4;
                if (work.leader < LEADER_AEHA_HEAD) {
                    tx.write(0.5);
                } else {
                    tx.write(0.0);
                }
                work.leader++;
                if ((LEADER_AEHA_HEAD + LEADER_AEHA_TAIL) <= work.leader) {
                    work.state = Data;
                }
            } else if (data.format == RemoteIR::SONY) {
                /*
                 * SONY.
                 */
                static const int LEADER_SONY_HEAD = 4;
                static const int LEADER_SONY_TAIL = 0;
                if (work.leader < LEADER_SONY_HEAD) {
                    tx.write(0.5);
                } else {
                    tx.write(0.0);
                }
                work.leader++;
                if ((LEADER_SONY_HEAD + LEADER_SONY_TAIL) <= work.leader) {
                    work.state = Data;
                }
            } else {
            }
            break;
        case Data:
            if (data.format == RemoteIR::NEC) {
                /*
                 * NEC.
                 */
                if (work.data == 0) {
                    tx.write(0.5);
                    work.data++;
                } else {
                    tx.write(0.0);
                    if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
                        if (3 <= work.data) {
                            work.bitcount++;
                            work.data = 0;
                        } else {
                            work.data++;
                        }
                    } else {
                        if (1 <= work.data) {
                            work.bitcount++;
                            work.data = 0;
                        } else {
                            work.data++;
                        }
                    }
                }
                if (data.bitlength <= work.bitcount) {
                    work.state = Trailer;
                }
            } else if (data.format == RemoteIR::AEHA) {
                /*
                 * AEHA.
                 */
                if (work.data == 0) {
                    tx.write(0.5);
                    work.data++;
                } else {
                    tx.write(0.0);
                    if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
                        if (3 <= work.data) {
                            work.bitcount++;
                            work.data = 0;
                        } else {
                            work.data++;
                        }
                    } else {
                        if (1 <= work.data) {
                            work.bitcount++;
                            work.data = 0;
                        } else {
                            work.data++;
                        }
                    }
                }
                if (data.bitlength <= work.bitcount) {
                    work.state = Trailer;
                }
            } else if (data.format == RemoteIR::SONY) {
                /*
                 * SONY.
                 */
                if (work.data == 0) {
                    tx.write(0.0);
                    work.data++;
                } else {
                    tx.write(0.5);
                    if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
                        if (2 <= work.data) {
                            work.bitcount++;
                            work.data = 0;
                        } else {
                            work.data++;
                        }
                    } else {
                        if (1 <= work.data) {
                            work.bitcount++;
                            work.data = 0;
                        } else {
                            work.data++;
                        }
                    }
                }
                if (data.bitlength <= work.bitcount) {
                    work.state = Trailer;
                }
            } else {
            }
            break;
        case Trailer:
            if (data.format == RemoteIR::NEC) {
                /*
                 * NEC.
                 */
                static const int TRAILER_NEC_HEAD = 1;
                static const int TRAILER_NEC_TAIL = 2;
                if (work.trailer < TRAILER_NEC_HEAD) {
                    tx.write(0.5);
                } else {
                    tx.write(0.0);
                }
                work.trailer++;
                if ((TRAILER_NEC_HEAD + TRAILER_NEC_TAIL) <= work.trailer) {
                    work.state = Idle;
                    //ticker.detach();
                }
            } else if (data.format == RemoteIR::AEHA) {
                /*
                 * AEHA.
                 */
                static const int TRAILER_AEHA_HEAD = 1;
                static const int TRAILER_AEHA_TAIL = 8000 / RemoteIR::TUS_AEHA;
                if (work.trailer < TRAILER_AEHA_HEAD) {
                    tx.write(0.5);
                } else {
                    tx.write(0.0);
                }
                work.trailer++;
                if ((TRAILER_AEHA_HEAD + TRAILER_AEHA_TAIL) <= work.trailer) {
                    work.state = Idle;
                    //ticker.detach();
                }
            } else if (data.format == RemoteIR::SONY) {
                /*
                 * SONY.
                 */
                static const int TRAILER_SONY_HEAD = 0;
                static const int TRAILER_SONY_TAIL = 0;
                if (work.trailer < TRAILER_SONY_HEAD) {
                    tx.write(0.5);
                } else {
                    tx.write(0.0);
                }
                work.trailer++;
                if ((TRAILER_SONY_HEAD + TRAILER_SONY_TAIL) <= work.trailer) {
                    work.state = Idle;
                    //ticker.detach();
                }
            } else {
            }
            break;
        default:
            break;
    }
    UNLOCK();
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXx TransmitterIR.h XxXxXxXxXxXxXxXxXxXxXxXxXxXx

/**
 * IR transmitter (Version 0.0.4)
 *
 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
 * http://shinta.main.jp/
 */

#ifndef _TRANSMITTER_IR_H_
#define _TRANSMITTER_IR_H_

#include <mbed.h>

#include "RemoteIR.h"

/**
 * IR transmitter class.
 */
class TransmitterIR {
public:

    /**
     * Constructor.
     *
     * @param txpin Pin for transmit IR signal.
     */
    explicit TransmitterIR(PinName txpin);

    /**
     * Destructor.
     */
    ~TransmitterIR();

    typedef enum {
        Idle,
        Leader,
        Data,
        Trailer
    } State;

    /**
     * Get state.
     *
     * @return Current state.
     */
    State getState(void);

    /**
     * Set data.
     *
     * @param format Format.
     * @param buf Buffer of a data.
     * @param bitlength Bit length of the data.
     *
     * @return Data bit length.
     */
    int setData(RemoteIR::Format format, uint8_t *buf, int bitlength);

private:

    typedef struct {
        State state;
        int bitcount;
        int leader;
        int data;
        int trailer;
    } work_t;

    typedef struct {
        RemoteIR::Format format;
        int bitlength;
        uint8_t buffer[64];
    } data_t;

    PwmOut tx;
    Ticker ticker;
    data_t data;
    work_t work;

    void tick();

};

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXx RemoteIR.h XxXxXxXxXxXxXxXxXxXxXxXxXxXx

/**
 * IR remote common class (Version 0.0.4)
 *
 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
 * http://shinta.main.jp/
 */

#ifndef _REMOTE_IR_H_
#define _REMOTE_IR_H_

class RemoteIR {
public:

    typedef enum {
        UNKNOWN,
        NEC,
        NEC_REPEAT,
        AEHA,
        AEHA_REPEAT,
        SONY
    } Format;

    static const int TUS_NEC = 562;
    static const int TUS_AEHA = 425;
    static const int TUS_SONY = 600;

private:
    RemoteIR();
};

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXx

Saturday, 7 January 2012

MBED Example: How to play WAV sound file from SDCard using SPI and AnalogOut

.from: https://github.com/leroilion/mbed/blob/master/PlayMusic/Examples/PlayMusic/main.cpp

#include "mbed.h"
#include "SDFileSystem.h"
SDFileSystem sd(11, 12, 13, 14, "sd");
AnalogOut aout(18);
int main() {
int ch; //first read byte
int ch2; //second read byte
int dat; //combined 16 bit word for DtoA
FILE *fp = fopen("/sd/QI2.wav", "r"); //open File to read
if(fp == NULL) {error("Could not open file for write\n");}
while(!feof(fp)) { //Play the music until End Of File
dat = 0;
ch = fgetc(fp); //get first byte
ch2 =fgetc(fp); //get second byte
ch = ch << 8; //shift bits 8 places to left
dat = ch2 | ch; //combine bits to single 16 bit int
aout.write_u16((unsigned short)(dat)); //DtoA conversion
wait_us(88); //set for 11k sample rate
}
fclose(fp); //close the file
}

MBED Example: How to use analog input pin (ADC, AnalogIn)

.from: http://mbed.org/projects/libraries/svn/mbed/trunk/AnalogIn.h

// Print messages when the AnalogIn is greater than 50%

#include "mbed.h"

AnalogIn temperature(p20);

int main() {
 while(1) {
     if(temperature > 0.5) {
         printf("Too hot! (%f)", temperature.read());            
     }
 }
}