Embedded system Fun Blog
























































Find out all the best information, libraries and circuit about the latest Embedded systems.

Sunday, 8 January 2012

MBED: Super Light Regular Expression library URL

.info: http://mbed.org/users/rolf/programs/slre/53976dc1707a499363b41b66994815bd

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx slre.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
 * All rights reserved
 *
 * "THE BEER-WARE LICENSE" (Revision 42):
 * Sergey Lyubka wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.
 */

#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "slre.h"

enum {END, BRANCH, ANY, EXACT, ANYOF, ANYBUT, OPEN, CLOSE, BOL, EOL,
    STAR, PLUS, STARQ, PLUSQ, QUEST, SPACE, NONSPACE, DIGIT};

static struct {
    const char    *name;
    int        narg;
    const char    *flags;   
} opcodes[] = {
    {"END",        0, ""},        /* End of code block or program    */
    {"BRANCH",    2, "oo"},    /* Alternative operator, "|"    */
    {"ANY",        0, ""},        /* Match any character, "."    */
    {"EXACT",    2, "d"},    /* Match exact string        */
    {"ANYOF",    2, "D"},    /* Match any from set, "[]"    */
    {"ANYBUT",    2, "D"},    /* Match any but from set, "[^]"*/
    {"OPEN ",    1, "i"},    /* Capture start, "("        */
    {"CLOSE",    1, "i"},    /* Capture end, ")"        */
    {"BOL",        0, ""},        /* Beginning of string, "^"    */
    {"EOL",        0, ""},        /* End of string, "$"        */
    {"STAR",    1, "o"},    /* Match zero or more times "*"    */
    {"PLUS",    1, "o"},    /* Match one or more times, "+"    */
    {"STARQ",    1, "o"},    /* Non-greedy STAR,  "*?"    */
    {"PLUSQ",    1, "o"},    /* Non-greedy PLUS, "+?"    */
    {"QUEST",    1, "o"},    /* Match zero or one time, "?"    */
    {"SPACE",    0, ""},        /* Match whitespace, "\s"    */
    {"NONSPACE",    0, ""},        /* Match non-space, "\S"    */
    {"DIGIT",    0, ""}        /* Match digit, "\d"        */
};

/*
 * Commands and operands are all unsigned char (1 byte long). All code offsets
 * are relative to current address, and positive (always point forward). Data
 * offsets are absolute. Commands with operands:
 *
 * BRANCH offset1 offset2
 *    Try to match the code block that follows the BRANCH instruction
 *    (code block ends with END). If no match, try to match code block that
 *    starts at offset1. If either of these match, jump to offset2.
 *
 * EXACT data_offset data_length
 *    Try to match exact string. String is recorded in data section from
 *    data_offset, and has length data_length.
 *
 * OPEN capture_number, CLOSE capture_number
 *    If the user have passed 'struct cap' array for captures, OPEN
 *    records the beginning of the matched substring (cap->ptr), CLOSE
 *    sets the length (cap->len) for respective capture_number.
 *
 * STAR code_offset, PLUS code_offset, QUEST code_offset
 *    *, +, ?, respectively. Try to gobble as much as possible from the
 *    matched buffer, until code block that follows these instructions
 *    matches. When the longest possible string is matched,
 *    jump to code_offset
 *
 * STARQ, PLUSQ are non-greedy versions of STAR and PLUS.
 */

static const char *meta_chars = "|.^$*+?()[\\";

static void
print_character_set(FILE *fp, const unsigned char *p, int len)
{
    int    i;

    for (i = 0; i < len; i++) {
        if (i > 0)
            (void) fputc(',', fp);
        if (p[i] == 0) {
            i++;
            if (p[i] == 0)
                (void) fprintf(fp, "\\x%02x", p[i]);
            else
                (void) fprintf(fp, "%s", opcodes[p[i]].name);
        } else if (isprint(p[i])) {
            (void) fputc(p[i], fp);
        } else {
            (void) fprintf(fp,"\\x%02x", p[i]);
        }
    }
}

void
slre_dump(const struct slre *r, FILE *fp)
{
    int    i, j, ch, op, pc;

    for (pc = 0; pc < r->code_size; pc++) {

        op = r->code[pc];
        (void) fprintf(fp, "%3d %s ", pc, opcodes[op].name);

        for (i = 0; opcodes[op].flags[i] != '\0'; i++)
            switch (opcodes[op].flags[i]) {
            case 'i':
                (void) fprintf(fp, "%d ", r->code[pc + 1]);
                pc++;
                break;
            case 'o':
                (void) fprintf(fp, "%d ",
                    pc + r->code[pc + 1] - i);
                pc++;
                break;
            case 'D':
                print_character_set(fp, r->data +
                    r->code[pc + 1], r->code[pc + 2]);
                pc += 2;
                break;
            case 'd':
                (void) fputc('"', fp);
                for (j = 0; j < r->code[pc + 2]; j++) {
                    ch = r->data[r->code[pc + 1] + j];
                    if (isprint(ch))
                        (void) fputc(ch, fp);
                    else
                        (void) fprintf(fp,"\\x%02x",ch);
                }
                (void) fputc('"', fp);
                pc += 2;
                break;
            }

        (void) fputc('\n', fp);
    }
}

static void
set_jump_offset(struct slre *r, int pc, int offset)
{
    assert(offset < r->code_size);

    if (r->code_size - offset > 0xff) {
        r->err_str = "Jump offset is too big";
    } else {
        r->code[pc] = (unsigned char) (r->code_size - offset);
    }
}

static void
emit(struct slre *r, int code)
{
    if (r->code_size >= (int) (sizeof(r->code) / sizeof(r->code[0])))
        r->err_str = "RE is too long (code overflow)";
    else
        r->code[r->code_size++] = (unsigned char) code;
}

static void
store_char_in_data(struct slre *r, int ch)
{
    if (r->data_size >= (int) sizeof(r->data))
        r->err_str = "RE is too long (data overflow)";
    else
        r->data[r->data_size++] = ch;
}

static void
exact(struct slre *r, const char **re)
{
    int    old_data_size = r->data_size;

    while (**re != '\0' && (strchr(meta_chars, **re)) == NULL)
        store_char_in_data(r, *(*re)++);

    emit(r, EXACT);
    emit(r, old_data_size);
    emit(r, r->data_size - old_data_size);
}

static int
get_escape_char(const char **re)
{
    int    res;

    switch (*(*re)++) {
    case 'n':    res = '\n';        break;
    case 'r':    res = '\r';        break;
    case 't':    res = '\t';        break;
    case '0':    res = 0;        break;
    case 'S':    res = NONSPACE << 8;    break;
    case 's':    res = SPACE << 8;    break;
    case 'd':    res = DIGIT << 8;    break;
    default:    res = (*re)[-1];    break;
    }

    return (res);
}

static void
anyof(struct slre *r, const char **re)
{
    int    esc, old_data_size = r->data_size, op = ANYOF;

    if (**re == '^') {
        op = ANYBUT;
        (*re)++;
    }

    while (**re != '\0')

        switch (*(*re)++) {
        case ']':
            emit(r, op);
            emit(r, old_data_size);
            emit(r, r->data_size - old_data_size);
            return;
            /* NOTREACHED */
            break;
        case '\\':
            esc = get_escape_char(re);
            if ((esc & 0xff) == 0) {
                store_char_in_data(r, 0);
                store_char_in_data(r, esc >> 8);
            } else {
                store_char_in_data(r, esc);
            }
            break;
        default:
            store_char_in_data(r, (*re)[-1]);
            break;
        }

    r->err_str = "No closing ']' bracket";
}

static void
relocate(struct slre *r, int begin, int shift)
{
    emit(r, END);
    memmove(r->code + begin + shift, r->code + begin, r->code_size - begin);
    r->code_size += shift;
}

static void
quantifier(struct slre *r, int prev, int op)
{
    if (r->code[prev] == EXACT && r->code[prev + 2] > 1) {
        r->code[prev + 2]--;
        emit(r, EXACT);
        emit(r, r->code[prev + 1] + r->code[prev + 2]);
        emit(r, 1);
        prev = r->code_size - 3;
    }
    relocate(r, prev, 2);
    r->code[prev] = op;
    set_jump_offset(r, prev + 1, prev);
}

static void
exact_one_char(struct slre *r, int ch)
{
    emit(r, EXACT);
    emit(r, r->data_size);
    emit(r, 1);
    store_char_in_data(r, ch);
}

static void
fixup_branch(struct slre *r, int fixup)
{
    if (fixup > 0) {
        emit(r, END);
        set_jump_offset(r, fixup, fixup - 2);
    }
}

static void
compile(struct slre *r, const char **re)
{
    int    op, esc, branch_start, last_op, fixup, cap_no, level;

    fixup = 0;
    level = r->num_caps;
    branch_start = last_op = r->code_size;

    for (;;)
        switch (*(*re)++) {
        case '\0':
            (*re)--;
            return;
            /* NOTREACHED */
            break;
        case '^':
            emit(r, BOL);
            break;
        case '$':
            emit(r, EOL);
            break;
        case '.':
            last_op = r->code_size;
            emit(r, ANY);
            break;
        case '[':
            anyof(r, re);
            break;
        case '\\':
            last_op = r->code_size;
            esc = get_escape_char(re);
            if (esc & 0xff00) {
                emit(r, esc >> 8);
            } else {
                exact_one_char(r, esc);
            }
            break;
        case '(':
            last_op = r->code_size;
            cap_no = ++r->num_caps;
            emit(r, OPEN);
            emit(r, cap_no);

            compile(r, re);
            if (*(*re)++ != ')') {
                r->err_str = "No closing bracket";
                return;
            }

            emit(r, CLOSE);
            emit(r, cap_no);
            break;
        case ')':
            (*re)--;
            fixup_branch(r, fixup);
            if (level == 0) {
                r->err_str = "Unbalanced brackets";
                return;
            }
            return;
            /* NOTREACHED */
            break;
        case '+':
        case '*':
            op = (*re)[-1] == '*' ? STAR: PLUS;
            if (**re == '?') {
                (*re)++;
                op = op == STAR ? STARQ : PLUSQ;
            }
            quantifier(r, last_op, op);
            break;
        case '?':
            quantifier(r, last_op, QUEST);
            break;
        case '|':
            fixup_branch(r, fixup);
            relocate(r, branch_start, 3);
            r->code[branch_start] = BRANCH;
            set_jump_offset(r, branch_start + 1, branch_start);
            fixup = branch_start + 2;
            r->code[fixup] = 0xff;
            break;
        default:
            (*re)--;
            last_op = r->code_size;
            exact(r, re);
            break;
        }
}

int
slre_compile(struct slre *r, const char *re)
{
    r->err_str = NULL;
    r->code_size = r->data_size = r->num_caps = r->anchored = 0;

    if (*re == '^')
        r->anchored++;

    emit(r, OPEN);    /* This will capture what matches full RE */
    emit(r, 0);

    while (*re != '\0')
        compile(r, &re);

    if (r->code[2] == BRANCH)
        fixup_branch(r, 4);

    emit(r, CLOSE);
    emit(r, 0);
    emit(r, END);

    return (r->err_str == NULL ? 1 : 0);
}

static int match(const struct slre *, int,
        const char *, int, int *, struct cap *);

static void
loop_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
{
    int    saved_offset, matched_offset;

    saved_offset = matched_offset = *ofs;

    while (match(r, pc + 2, s, len, ofs, NULL)) {
        saved_offset = *ofs;
        if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
            matched_offset = saved_offset;
        *ofs = saved_offset;
    }

    *ofs = matched_offset;
}

static void
loop_non_greedy(const struct slre *r, int pc, const char *s,int len, int *ofs)
{
    int    saved_offset = *ofs;

    while (match(r, pc + 2, s, len, ofs, NULL)) {
        saved_offset = *ofs;
        if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
            break;
    }

    *ofs = saved_offset;
}

static int
is_any_of(const unsigned char *p, int len, const char *s, int *ofs)
{
    int    i, ch;

    ch = s[*ofs];

    for (i = 0; i < len; i++)
        if (p[i] == ch) {
            (*ofs)++;
            return (1);
        }

    return (0);
}

static int
is_any_but(const unsigned char *p, int len, const char *s, int *ofs)
{
    int    i, ch;

    ch = s[*ofs];

    for (i = 0; i < len; i++)
        if (p[i] == ch)
            return (0);

    (*ofs)++;
    return (1);
}

static int
match(const struct slre *r, int pc, const char *s, int len,
        int *ofs, struct cap *caps)
{
    int    n, saved_offset, res = 1;

    while (res && r->code[pc] != END) {

        assert(pc < r->code_size);
        assert(pc < (int) (sizeof(r->code) / sizeof(r->code[0])));

        switch (r->code[pc]) {
        case BRANCH:
            saved_offset = *ofs;
            res = match(r, pc + 3, s, len, ofs, caps);
            if (res == 0) {
                *ofs = saved_offset;
                res = match(r, pc + r->code[pc + 1],
                    s, len, ofs, caps);
            }
            pc += r->code[pc + 2];
            break;
        case EXACT:
            res = 0;
            n = r->code[pc + 2];    /* String length */
            if (n <= len - *ofs && !memcmp(s + *ofs, r->data +
                r->code[pc + 1], n)) {
                (*ofs) += n;
                res = 1;
            }
            pc += 3;
            break;
        case QUEST:
            res = 1;
            saved_offset = *ofs;
            if (!match(r, pc + 2, s, len, ofs, caps))
                *ofs = saved_offset;
            pc += r->code[pc + 1];
            break;
        case STAR:
            res = 1;
            loop_greedy(r, pc, s, len, ofs);
            pc += r->code[pc + 1];
            break;
        case STARQ:
            res = 1;
            loop_non_greedy(r, pc, s, len, ofs);
            pc += r->code[pc + 1];
            break;
        case PLUS:
            if ((res = match(r, pc + 2, s, len, ofs, caps)) == 0)
                break;

            loop_greedy(r, pc, s, len, ofs);
            pc += r->code[pc + 1];
            break;
        case PLUSQ:
            if ((res = match(r, pc + 2, s, len, ofs, caps)) == 0)
                break;

            loop_non_greedy(r, pc, s, len, ofs);
            pc += r->code[pc + 1];
            break;
        case SPACE:
            res = 0;
            if (*ofs < len && isspace(((unsigned char *)s)[*ofs])) {
                (*ofs)++;
                res = 1;
            }
            pc++;
            break;
        case NONSPACE:
            res = 0;
            if (*ofs <len && !isspace(((unsigned char *)s)[*ofs])) {
                (*ofs)++;
                res = 1;
            }
            pc++;
            break;
        case DIGIT:
            res = 0;
            if (*ofs < len && isdigit(((unsigned char *)s)[*ofs])) {
                (*ofs)++;
                res = 1;
            }
            pc++;
            break;
        case ANY:
            res = 0;
            if (*ofs < len) {
                (*ofs)++;
                res = 1;
            }
            pc++;
            break;
        case ANYOF:
            res = 0;
            if (*ofs < len)
                res = is_any_of(r->data + r->code[pc + 1],
                    r->code[pc + 2], s, ofs);
            pc += 3;
            break;
        case ANYBUT:
            res = 0;
            if (*ofs < len)
                res = is_any_but(r->data + r->code[pc + 1],
                    r->code[pc + 2], s, ofs);
            pc += 3;
            break;
        case BOL:
            res = *ofs == 0 ? 1 : 0;
            pc++;
            break;
        case EOL:
            res = *ofs == len ? 1 : 0;
            pc++;
            break;
        case OPEN:
            if (caps != NULL)
                caps[r->code[pc + 1]].ptr = s + *ofs;
            pc += 2;
            break;
        case CLOSE:
            if (caps != NULL)
                caps[r->code[pc + 1]].len = (s + *ofs) -
                    caps[r->code[pc + 1]].ptr;
            pc += 2;
            break;
        case END:
            pc++;
            break;
        default:
            printf("unknown cmd (%d) at %d\n", r->code[pc], pc);
            assert(0);
            break;
        }
    }

    return (res);
}

int
slre_match(const struct slre *r, const char *buf, int len,
        struct cap *caps)
{
    int    i, ofs = 0, res = 0;

    if (r->anchored) {
        res = match(r, 0, buf, len, &ofs, caps);
    } else {
        for (i = 0; i < len && res == 0; i++) {
            ofs = i;
            res = match(r, 0, buf, len, &ofs, caps);
        }
    }

    return (res);
}


XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx slre.h XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
 * All rights reserved
 *
 * "THE BEER-WARE LICENSE" (Revision 42):
 * Sergey Lyubka wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.
 */

/*
 * This is a regular expression library that implements a subset of Perl RE.
 * Please refer to http://slre.sourceforge.net for detailed description.
 *
 * Usage example (parsing HTTP request):
 *
 * struct slre    slre;
 * struct cap    captures[4 + 1];  // Number of braket pairs + 1
 * ...
 *
 * slre_compile(&slre,"^(GET|POST) (\S+) HTTP/(\S+?)\r\n");
 *
 * if (slre_match(&slre, buf, len, captures)) {
 *    printf("Request line length: %d\n", captures[0].len);
 *    printf("Method: %.*s\n", captures[1].len, captures[1].ptr);
 *    printf("URI: %.*s\n", captures[2].len, captures[2].ptr);
 * }
 *
 * Supported syntax:
 *    ^        Match beginning of a buffer
 *    $        Match end of a buffer
 *    ()        Grouping and substring capturing
 *    [...]        Match any character from set
 *    [^...]        Match any character but ones from set
 *    \s        Match whitespace
 *    \S        Match non-whitespace
 *    \d        Match decimal digit
 *    \r        Match carriage return
 *    \n        Match newline
 *    +        Match one or more times (greedy)
 *    +?        Match one or more times (non-greedy)
 *    *        Match zero or more times (greedy)
 *    *?        Match zero or more times (non-greedy)
 *    ?        Match zero or once
 *    \xDD        Match byte with hex value 0xDD
 *    \meta        Match one of the meta character: ^$().[*+?\
 */

#ifndef SLRE_HEADER_DEFINED
#define    SLRE_HEADER_DEFINED

/*
 * Compiled regular expression
 */
struct slre {
    unsigned char    code[256];
    unsigned char    data[256];
    int        code_size;
    int        data_size;
    int        num_caps;    /* Number of bracket pairs    */
    int        anchored;    /* Must match from string start    */
    const char    *err_str;    /* Error string            */
};

/*
 * Captured substring
 */
struct cap {
    const char    *ptr;        /* Pointer to the substring    */
    int        len;        /* Substring length        */
};

/*
 * Compile regular expression. If success, 1 is returned.
 * If error, 0 is returned and slre.err_str points to the error message.
 */
int slre_compile(struct slre *, const char *re);

/*
 * Return 1 if match, 0 if no match.
 * If `captured_substrings' array is not NULL, then it is filled with the
 * values of captured substrings. captured_substrings[0] element is always
 * a full matched substring. The round bracket captures start from
 * captured_substrings[1].
 * It is assumed that the size of captured_substrings array is enough to
 * hold all captures. The caller function must make sure it is! So, the
 * array_size = number_of_round_bracket_pairs + 1
 */
int slre_match(const struct slre *, const char *buf, int buf_len,
    struct cap *captured_substrings);

#endif /* SLRE_HEADER_DEFINED */

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx main.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

#include "mbed.h"
#include "slre.h"

DigitalOut led(LED1);
/*
class RegEx {
  RegEx(char *ex);
  match(char *str, Groups *)
}
*/
int main() {
    char *buf = "GET /foo.bar?query=moo HTTP/1.5\r\n";
    struct slre        slre;
    struct cap         captures[4 + 1];

    if (!slre_compile(&slre, "^(GET|POST) (\\S+) HTTP/(\\S+?)\r\n")) {
        printf("Error compiling RE: %s\n", slre.err_str);
    } else if (!slre_match(&slre, buf, strlen(buf), captures)) {
        printf("Not a valid HTTP request\n" );
    } else {
        printf("Request line length: %d\n", captures[0].len);
        printf("Method: %.*s\n", captures[1].len, captures[1].ptr);
        printf("URI: %.*s\n", captures[2].len, captures[2].ptr);
    }
    while(1) {
        led = !led;
        wait(0.2);
    }
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx



MBED: Cool Tiny SMTP Client

.from: http://mbed.org/users/okini3939/programs/TinySMTP/lv1bdk

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinySMTP.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny SMTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny SMTP Client
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "DNSRequest.h"
#include "TinySMTP.h"

#define STATUS_NONE 0
#define STATUS_READABLE 1
#define STATUS_CONNECTED 2
#define STATUS_ERROR 3
#define STATUS_DISCONNECTED 4

static TCPSocket *smtp;
static volatile int tcp_ready, tcp_readable, tcp_writable;
static volatile int dns_status;


// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
int base64enc(const char *input, unsigned int length, char *output, int outputlen) {
  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  unsigned int c, c1, c2, c3;

  if (outputlen < (((length-1)/3)+1)<<2) return -1;

  for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
    c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
    c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
    c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;

    c = ((c1 & 0xFC) >> 2);
    output[j+0] = base64[c];
    c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
    output[j+1] = base64[c];
    c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
    output[j+2] = (length>i+1)?base64[c]:'=';
    c = (c3 & 0x3F);
    output[j+3] = (length>i+2)?base64[c]:'=';
  }
  output[(((length-1)/3)+1)<<2] = '\0';
  return 0;
}


void isr_smtp (TCPSocketEvent e) {

#ifdef DEBUG
    printf("tcp(%d)\r\n", e);
#endif
    switch(e) {
    case TCPSOCKET_CONNECTED:
        tcp_ready = 1;
        break;

    case TCPSOCKET_READABLE: //Incoming data
        tcp_readable = 1;
        break;

    case TCPSOCKET_WRITEABLE: //We can send data
        tcp_writable = 1;
        break;

    case TCPSOCKET_CONTIMEOUT:
    case TCPSOCKET_CONRST:
    case TCPSOCKET_CONABRT:
    case TCPSOCKET_ERROR:
    case TCPSOCKET_DISCONNECTED:
        tcp_ready = 0;
        break;
    }
}

int wait_smtp (int code) {
    Timer timeout;
    int i;
    char buf[1500];

    // wait responce
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < SMTP_TIMEOUT) {
        if (tcp_readable) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_readable) return -1;
    // recv
    i = smtp->recv(buf, sizeof(buf));
    if (i < sizeof(buf) - 1) tcp_readable = 0;
    buf[i] = 0;
#ifdef DEBUG
    printf(buf);
#endif

    // check return code
    if (atoi(buf) == code) return 0;

    return -1;
}

void isr_dns (DNSReply r) {

#ifdef DEBUG
    printf("dns(%d)\r\n", r);
#endif
    if (DNS_FOUND) {
        dns_status = 1;
    } else {
        dns_status = -1;
    }
}

int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd) {
    TCPSocketErr err;
    Timer timeout;
    int ret = -1;

    smtp = new TCPSocket;
    tcp_ready = 0;
    tcp_readable = 0;
    tcp_writable = 0;

    smtp->setOnEvent(isr_smtp);

    // connect
    if (host->getIp().isNull()) {
        DNSRequest dns;
        dns_status = 0;
        dns.setOnReply(isr_dns);
        if (dns.resolve(host) != DNS_OK) goto exit;
        timeout.reset();
        timeout.start();
        while (timeout.read_ms() < SMTP_TIMEOUT) {
            if (dns_status) break;
            Net::poll();
        }
        timeout.stop();
        if (dns_status <= 0) goto exit;
#ifdef DEBUG
        printf("%s [%d.%d.%d.%d]\r\n", host->getName(), (unsigned char)host->getIp()[0], (unsigned char)host->getIp()[1], (unsigned char)host->getIp()[2], (unsigned char)host->getIp()[3]);
#endif
    }
    if (! host->getPort()) {
        host->setPort(SMTP_PORT);
    }

    err = smtp->connect(*host);
    if (err != TCPSOCKET_OK) goto exit;

    // wait connect
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < SMTP_TIMEOUT) {
        if (tcp_ready) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_ready) goto exit;
    if (wait_smtp(220)) goto exit;

    // send request
    wait_ms(100);
    smtp->send("EHLO mbed\r\n", 11);
    if (wait_smtp(250)) goto exit;

    if (user && pwd) {
        // smtp auth
        char tmp[80], buf[100];
        int len;
        snprintf(tmp, sizeof(tmp), "%s%c%s%c%s", user, 0, user, 0, pwd);
        len = strlen(user) * 2 + strlen(pwd) + 2;
        base64enc(tmp, len, buf, sizeof(buf));
        smtp->send("AUTH PLAIN ", 11);
        smtp->send(buf, strlen(buf));
        smtp->send("\r\n", 2);
        if (wait_smtp(235)) goto quit;
    }

    smtp->send("MAIL FROM: ", 11);
    smtp->send(from, strlen(from));
    smtp->send("\r\n", 2);
    if (wait_smtp(250)) goto quit;

    smtp->send("RCPT TO: ", 9);
    smtp->send(to, strlen(to));
    smtp->send("\r\n", 2);
    if (wait_smtp(250)) goto quit;

    smtp->send("DATA\r\n", 6);
    if (wait_smtp(354)) goto quit;

    // mail data
    smtp->send(data, strlen(data));
    smtp->send("\r\n.\r\n", 5);
    if (wait_smtp(250)) goto quit;
    ret = 0;

quit:
    smtp->send("QUIT\r\n", 6);
    if (wait_smtp(221)) goto exit;

exit:
    smtp->resetOnEvent();
    smtp->close();
    delete smtp;

    return ret;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinySMTP.h XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny SMTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny SMTP Client
 */

#ifndef TinySMTP_h
#define TinySMTP_h

#define DEBUG

#define SMTP_PORT 25
#define SMTP_TIMEOUT 15000 // ms

/** send mail
 * @param to mail address
 * @param from mail address
 * @param data mail body
 * @param host mail server
 * @param data mail body
 * @param user auth username (or NULL)
 * @param pwd auth password (or NULL)
 * @return 0:success, -1:failue
 */
int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd);

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx main.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "TinySMTP.h"

#define SMTP "mail.domain.name"
#define PORT 587 // or 25
#define FROM "from@domain.name"
#define TO "to@domain.name"
#define USER "authuser"
#define PWD "password"
#define SUBJECT "mail test"
#define BODY "TEST TEST"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
EthernetNetIf eth;

int main () {
    EthernetErr ethErr;
    Host host;
    int r;
    char data[500];

    myled = 1;

    strcpy(data, "From: " FROM "\r\nTo: " TO "\r\n");
    strcat(data, "Subject: " SUBJECT "\r\n\r\n" BODY "\r\n");

    ethErr = eth.setup();
    if(ethErr) {
        return -1;
    }

    host.setName(SMTP);
    host.setPort(PORT);
    r = sendmail(FROM, TO, data, &host, USER, PWD);

    if (r) {
        printf("error\r\n");
    } else {
        printf("sent\r\n");
    }

    myled = 0;
    return 0;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx


MBED: Tiny HTTP Client

.info: http://mbed.org/users/okini3939/programs/TinyHTTP/lv1tin

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinyHTTP.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny HTTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny HTTP Client
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "DNSRequest.h"
#include "TinyHTTP.h"
#include <ctype.h>


TCPSocket *http;
volatile int tcp_ready, tcp_readable, tcp_writable;
volatile int dns_status;

// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
int base64enc(const char *input, unsigned int length, char *output, int len) {
  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  unsigned int c, c1, c2, c3;

  if (len < ((((length-1)/3)+1)<<2)) return -1;
  for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
    c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
    c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
    c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;

    c = ((c1 & 0xFC) >> 2);
    output[j+0] = base64[c];
    c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
    output[j+1] = base64[c];
    c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
    output[j+2] = (length>i+1)?base64[c]:'=';
    c = (c3 & 0x3F);
    output[j+3] = (length>i+2)?base64[c]:'=';
  }
  output[(((length-1)/3)+1)<<2] = '\0';
  return 0;
}

// Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
int urlencode(char *str, char *buf, int len) {
  static const char to_hex[] = "0123456789ABCDEF";
//  char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
  char *pstr = str, *pbuf = buf;

  if (len < (strlen(str) * 3 + 1)) return -1;
  while (*pstr) {
    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') {
      *pbuf++ = *pstr;
    } else if (*pstr == ' ') {
      *pbuf++ = '+';
    } else {
      *pbuf++ = '%';
      *pbuf++ = to_hex[(*pstr >> 4) & 0x0f];
      *pbuf++ = to_hex[*pstr & 0x0f];
    }
    pstr++;
  }
  *pbuf = '\0';
  return 0;
}


void isr_http (TCPSocketEvent e) {

#ifdef DEBUG
    printf("tcp(%d)\r\n", e);
#endif
    switch(e) {
    case TCPSOCKET_CONNECTED:
        tcp_ready = 1;
        break;

    case TCPSOCKET_READABLE: //Incoming data
        tcp_readable = 1;
        break;

    case TCPSOCKET_WRITEABLE: //We can send data
        tcp_writable = 1;
        break;

    case TCPSOCKET_CONTIMEOUT:
    case TCPSOCKET_CONRST:
    case TCPSOCKET_CONABRT:
    case TCPSOCKET_ERROR:
    case TCPSOCKET_DISCONNECTED:
        tcp_ready = 0;
        break;
    }
}

void createauth (char *user, char *pwd, char *buf, int len) {
    char tmp[80];

    strncpy(buf, "Authorization: Basic ", len);
    snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
    base64enc(tmp, strlen(tmp), &buf[strlen(buf)], len - strlen(buf));
    strncat(buf, "\r\n", len - strlen(buf));
}

void isr_dns (DNSReply r) {

#ifdef DEBUG
    printf("dns(%d)\r\n", r);
#endif
    if (DNS_FOUND) {
        dns_status = 1;
    } else {
        dns_status = -1;
    }
}

int httpRequest (int method, Host *host, char *uri, char *head, char *body) {
    TCPSocketErr err;
    Timer timeout;
    char buf[1500];
    int i, ret = -1;

    http = new TCPSocket;
    tcp_ready = 0;
    tcp_readable = 0;
    tcp_writable = 0;

    http->setOnEvent(isr_http);

    // connect
    if (host->getIp().isNull()) {
        // resolv
        DNSRequest dns;
        dns_status = 0;
        dns.setOnReply(isr_dns);
        if (dns.resolve(host) != DNS_OK) goto exit;
        timeout.reset();
        timeout.start();
        while (timeout.read_ms() < HTTP_TIMEOUT) {
            if (dns_status) break;
            Net::poll();
        }
        timeout.stop();
        if (dns_status <= 0) goto exit;
#ifdef DEBUG
        printf("%s [%d.%d.%d.%d]\r\n", host->getName(), (unsigned char)host->getIp()[0], (unsigned char)host->getIp()[1], (unsigned char)host->getIp()[2], (unsigned char)host->getIp()[3]);
#endif
    }
    if (! host->getPort()) {
        host->setPort(HTTP_PORT);
    }
    err = http->connect(*host);
    if (err != TCPSOCKET_OK) goto exit;

    // wait connect
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < HTTP_TIMEOUT) {
        if (tcp_ready) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_ready) goto exit;

    // send request
    if (method == METHOD_POST) {
        http->send("POST ", 5);
    } else {
        http->send("GET ", 4);
    }
    http->send(uri, strlen(uri));
    http->send(" HTTP/1.1\r\nHost: ", 17);
    http->send(host->getName(), strlen(host->getName()));
    http->send("\r\n", 2);
    http->send("Connection: close\r\n", 19);
    if (head) {
        http->send(head, strlen(head));
    }
    if (method == METHOD_POST) {
        sprintf(buf, "Content-Length: %d\r\n", strlen(body));
        http->send(buf, strlen(buf));
    }
    http->send("\r\n", 2);

    // post method
    if (method == METHOD_POST && body) {
        http->send(body, strlen(body));
    }

    // wait responce
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < HTTP_TIMEOUT) {
        if (tcp_readable) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_readable) goto exit;

    // recv responce
    i = http->recv(buf, sizeof(buf) - 1);
    buf[i] = 0;
    if (i < sizeof(buf) - 1) tcp_readable = 0;
    if (strncmp(buf, "HTTP/", 5) == 0) {
        ret = atoi(&buf[9]);
    }
#ifdef DEBUG
    printf(buf);
#endif

    // recv dummy
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < HTTP_TIMEOUT) {
        if (tcp_readable) {
            i = http->recv(buf, sizeof(buf) - 1);
            buf[i] = 0;
            if (i < sizeof(buf) - 1) tcp_readable = 0;
#ifdef DEBUG
            printf(buf);
#endif
            timeout.reset();
        } else
        if (! tcp_ready) {
            break;
        }
        Net::poll();
    }
    timeout.stop();

exit:
    http->resetOnEvent();
    http->close();
    delete http;

    return ret;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinyHTTP.h XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny HTTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny HTTP Client
 */

#ifndef TinyHTTP_h
#define TinyHTTP_h

#define DEBUG

#define HTTP_PORT 80
#define HTTP_TIMEOUT 15000 // ms

#define METHOD_GET 0
#define METHOD_POST 1

/** send http request
 * @param method METHOD_GET or METHOD_POST
 * @param host http server
 * @param uri URI
 * @param head http header (CR+LF) (or NULL)
 * @param body POST body (or NULL)
 * @return http code, -1:failue
 */
int httpRequest (int method, Host *host, char *uri, char *head, char *body);

void createauth (char *user, char *pwd, char *buf, int len);

int base64enc(const char *input, unsigned int length, char *output, int len);

int urlencode(char *str, char *buf, int len);

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx main.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "TinyHTTP.h"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
EthernetNetIf eth;


int pachube (int feedid, char *apikey, char *buf) {
    Host host;
    char uri[40], head[160];

    // header
    snprintf(head, sizeof(head), "Content-type: text/csv\r\nX-PachubeApiKey: %s\r\n", apikey);

    // uri
    snprintf(uri, sizeof(uri), "/v1/feeds/%d.csv?_method=put", feedid);

    host.setName("api.pachube.com");
    host.setPort(HTTP_PORT);
    return httpRequest(METHOD_POST, &host, uri, head, buf) == 200 ? 0 : -1;
}

int twitter (char *msg, char *user, char *pwd) {
    Host host;
    char buf[300], head[160];

    // header
    createauth(user, pwd, head, sizeof(head));
    strncat(head, "Content-type: application/x-www-form-urlencoded\r\n", sizeof(head) - strlen(head));

    // post data
    strcpy(buf, "status=");
    urlencode(msg, &buf[strlen(buf)], sizeof(buf) - strlen(buf));

    host.setName("api.supertweet.net");
    host.setPort(HTTP_PORT);
    return httpRequest(METHOD_POST, &host, "/1/statuses/update.xml", head, buf) == 200 ? 0 : -1;
}

int main () {
    EthernetErr ethErr;
    Host host;
    int r;

    myled = 1;
//    pc.baud(115200);

    ethErr = eth.setup();
    if(ethErr) {
        return -1;
    }

    host.setName("mbed.org");
    r = httpRequest(METHOD_GET, &host, "/", NULL, NULL);

//    r = twitter("test from #mbed TinyHTTP", "username", "password");

//    r = pachube(99999, "api key", "1000,30,70");

/*
    host.setName("www.domain.name");
    r = httpRequest(METHOD_POST, &host, "/xxx.cgi", "Content-Type: application/x-www-form-urlencoded\r\n", "key=value&key2=value2");
*/
    printf("status %d\r\n", r);

    myled = 0;
    return 0;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx


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