app-board-LCD mbed NXP LPC1768

# app-board-LCD mbed NXP LPC1768
# http://mbed.org/users/chris/code/app-board-LCD/
# http://mbed.org/users/dreschpe/code/C12832_lcd/
import sys
import mbed

class C12832_LCD:
    def __init__(self):
        self._spi = mbed.SPI('p5','NC','p7')
        self._reset = mbed.DigitalOut('p6')
        self._A0 = mbed.DigitalOut('p8')
        self._CS =mbed.DigitalOut('p11')
        self.lcd_reset()

    def lcd_reset(self):
        self._spi.format(8,3)         # 8 bit spi mode 3
        self._spi.frequency(20000000) # 19,2 Mhz SPI clock
        self._A0.write(0)
        self._CS.write(1)
        self._reset.write(0) # display reset
        sys.wait(1) # wait 50us
        self._reset.write(1) # end reset
        sys.wait(5)
        # Start Initial Sequence ----------------------------------------------------
        self.wr_cmd(0xAE)   # display off
        self.wr_cmd(0xA2)   # bias voltage
        self.wr_cmd(0xA0)
        self.wr_cmd(0xC8)   # colum normal
        self.wr_cmd(0x22)   # voltage resistor ratio
        self.wr_cmd(0x2F)   # power on
        #wr_cmd(0xA4)   # LCD display ram
        self.wr_cmd(0x40)   # start line = 0
        self.wr_cmd(0xAF)   # display ON
        self.wr_cmd(0x81)   # set contrast
        self.wr_cmd(0x17)   # set contrast
        self.wr_cmd(0xA6)   # display normal

    def buf_to_lcd(self, page, colum, buffer):
        self.wr_cmd(0x00 + (colum & 0xf))     # set column low nibble
        self.wr_cmd(0x10 + ((colum>>4)&0x0f)) # set column hi  nibble
        self.wr_cmd(0xB0+page)  # set page address
        for d in buffer:
            self.wr_dat(d)

    def wr_cmd(self, cmd):
        self._A0.write(0)
        self._CS.write(0)
        self._spi.write(cmd)
        self._CS.write(1)

    def wr_dat(self, dat):
        self._A0.write(1)
        self._CS.write(0)
        self._spi.write(dat)
        self._CS.write(1)

    def cls(self, data=0):
        for page  in range(4):
            colum = 0
            while colum < 128:
                self.buf_to_lcd(page, colum, [data])
                colum += 1
        self.locate(0, 0)

    def locate(self, row, colum):
        self.page = row
        self.colum = colum * 4

    def crlf(self):
        self.colum = 0
        self.page += 1
        if self.page >= 4:
            self.page = 0

    def puts(self, s):
        for c in s:
            self.putc(c)

    def putc(self, c):
        if c == "\n":
            self.crlf()
            return
        font = self.get_font(c)
        self.buf_to_lcd(self.page, self.colum, font)
        self.colum += len(font)
        if self.colum >= 128:
            self.crlf()            

    def get_font(self, c):
        # misaki_bdf_b11a.tar.gz misaki_4x8_jisx0201.bdf
        font = (
            0,6016,49155,1034559,434070,590866,695986,130,1072896,8001,164746,139016,
            532480,132104,4096,66576,464156,532260,595250,333090,1018392,300334,300316,
            105730,333076,464164,2560,2592,559624,330260,133666,103554,496786,1017022,
            430783,544926,495807,545471,17087,938142,1033279,548769,512016,967231,528447,
            1033023,1015999,495774,99519,1544350,885951,414370,24449,1036351,247871,
            1035327,837171,56835,579249,1081216,352021,16321,32898,1056832,32896,987672,
            397887,594456,1036824,726552,89988,993864,918079,7808,7872,853055,8065,
            921148,918076,397848,397948,2036248,66620,335400,597764,987196,198716,989244,
            592932,993356,727588,1071880,16256,138049,16513,
            )
        i = ord(c) - 0x20
        if i < 0 or i > len(font):
            i = 0
        return(font[i]&0x7f,(font[i]>>7)&0x7f,(font[i]>>14)&0x7f, 0)


lcd = C12832_LCD()
lcd.cls()
lcd.locate(0, 3)
lcd.puts("mbed application board!")
j = 0
while 1:
    lcd.locate(1, 15)
    lcd.puts("Counting : %d" % j);
    j += 1
    sys.wait(1*1000)

FRDM_MMA8451Q

# FRDM_MMA8451Q
# http://mbed.org/users/mbed_official/code/FRDM_MMA8451Q/
import mbed
import sys

def float(n):
    s = 1.0
    if n < 0:
        s = -1.0
        n *= -1
    f = 0.0
    a = 1.0
    while n:
        if n & 1:
            f += a
        n >>= 1
        a *= 2.0
    f *= s
    return f

def abs(a):
    if a < 0:
        return -a
    return a
    
class MMA8451Q:
    REG_WHO_AM_I=0x0D
    REG_CTRL_REG_1=0x2A
    REG_OUT_X_MSB=0x01
    REG_OUT_Y_MSB=0x03
    REG_OUT_Z_MSB=0x05
    UINT14_MAX=16383

    def __init__(self, sda, scl, addr):
        self._i2c = mbed.I2C(sda, scl)
        self._addr = addr
        data = chr(self.REG_CTRL_REG_1)+chr(0x01)
        self.writeRegs(data)

    def getAccX(self):
        return float(self.getAccAxis(self.REG_OUT_X_MSB)) / 4096.0

    def getAccY(self):
        return float(self.getAccAxis(self.REG_OUT_Y_MSB)) / 4096.0
        
    def getAccZ(self):
        return float(self.getAccAxis(self.REG_OUT_Z_MSB)) / 4096.0
        
    def getWhoAmI(self):
        who_am_i = chr(0)
        self.readRegs(self.REG_WHO_AM_I, who_am_i);
        return ord(who_am_i)
    
    def getAccAxis(self, addr):
        res = chr(0)+chr(0)
        self.readRegs(addr, res)
        acc = (ord(res[0]) << 6) | (ord(res[1]) >> 2)
        if acc > (self.UINT14_MAX/2):
            acc -= self.UINT14_MAX;
        return acc

    def readRegs(self, addr, data):
        self._i2c.write(self._addr, chr(addr), 1, 1)
        self._i2c.read(self._addr, data, len(data), 0)

    def writeRegs(self, data):
        self._i2c.write(self._addr, data, len(data), 0)

MMA8451_I2C_ADDRESS=(0x1d<<1)

acc = MMA8451Q('PTE25', 'PTE24', MMA8451_I2C_ADDRESS)
rled = mbed.PwmOut('LED_RED')
gled = mbed.PwmOut('LED_GREEN')
bled = mbed.PwmOut('LED_BLUE');
    
while 1:
    rled.write(1.0 - abs(acc.getAccX()))
    gled.write(1.0 - abs(acc.getAccY()))
    bled.write(1.0 - abs(acc.getAccZ()))
    sys.wait(100) # 100ms
    #print sys.heap()
    #sys.wait(1000)

websocket clientのテスト

# wsbench.py 2013/2/21
# coding: utf-8
#
import websocket
import base64
import time
import argparse

channel = "public-ch"
url = "ws://sockets.mbed.org/ws/" + channel + "/rw";
CHUNK=2*30

def buf_to_websocket(buf, ws=None):
    print "image size: %d bytes" % len(buf)
    st = time.time()
    ws_send = 0
    for i in range(0, len(buf), CHUNK):
        chunk_len = min(len(buf) - i, CHUNK)
        s = buf[i:i+chunk_len]
        d = base64.b64encode(s)
        print d
        if ws:
            ws.send(d)
        ws_send += len(d)
    d = "."
    print d
    if ws:
        ws.send(d)
    ms = (time.time() - st) * 1000
    print "websocket: send: %d bytes %d ms" % (ws_send, ms)

if __name__ == '__main__':
    ws = websocket.create_connection(url)
    #ws = None

    parser = argparse.ArgumentParser()
    parser.add_argument('infiles', nargs='*', help=u"image file")
    args = parser.parse_args()
    for i, filename in enumerate(args.infiles):
        with open(filename, "rb") as f:
            data = f.read()
        print("input: %s %d bytes" % (filename, len(data)))
        buf_to_websocket(data, ws)

QcamOrbitAFのモータ制御をする。

// BaseJpegDecode_example/main_QcamOrbitAF.cpp 2013/2/16
// simple color tracking for Logitech Qcam Orbit AF
//
#include "mbed.h"
#include "rtos.h"
#include "BaseUsbHost.h"
#include "UvcCam.h"
#include "BaseJpegDecode.h"
#include "Terminal.h"
#include "MyThread.h"

#define WIDTH  160
#define HEIGHT 120

#define THRESHOLD 200

DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
Terminal term(USBTX, USBRX);

class CalcCenter : public MyThread, public BaseJpegDecode {
public:
    int y_center, x_center;
    int m_x_sum, m_y_sum, m_sum;
    uint32_t EOI_count;
    int16_t buf_Cb[WIDTH/16*HEIGHT/8]; // debug
    int16_t buf_Cr[WIDTH/16*HEIGHT/8]; // debug
    CalcCenter(BaseUvc* cam) {
        m_cam = cam;
        m_cam->setOnResult(this, &CalcCenter::callback_motion_jpeg);
        EOI_count = 0;
    }
protected:
    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
        input(buf+12, len-12);
        if (buf[1]&1) { // FID
            led1 = !led1;
        }
    }
    
    virtual void outputDC(int mcu, int block, int value) {
        if (mcu >= (WIDTH/16*HEIGHT/8)) {
            return;
        }
        if (block == 2) {
            buf_Cb[mcu] = value * qt[1][0];
        } else if (block == 3) { // 0-1:Y 2:Cb 3:Cr
            buf_Cr[mcu] = value * qt[1][0];
            value *= qt[1][0];
            if (value >= THRESHOLD) { // red
                m_x_sum += value*(mcu%(WIDTH/16));
                m_y_sum += value*(mcu/(WIDTH/16));
                m_sum += value;
            }
        }
    }
    virtual void outputAC(int mcu, int block, int scan, int value){};
    virtual void outputMARK(uint8_t c){
        if (c == 0xd9) { // EOI
            if(m_sum == 0) {
                x_center = y_center = -1; // not found
            } else {
                x_center = m_x_sum / m_sum;
                y_center = m_y_sum / m_sum;
            }
            m_x_sum = m_y_sum = m_sum = 0; // reset
            EOI_count++;
            led3 = !led3;
        }
    }

    virtual void run() {
        while(true) {
            if (m_cam) {
                m_cam->poll();
            }
        }
    }
    BaseUvc* m_cam;
};

BaseUvc* cam = NULL;
CalcCenter* calc = NULL;

class display_Thread : public MyThread {
    virtual void run() {
        term.cls();
        int fg, old_fg = 0xffffff;
        while(1) {
            int column = 0;
            for(int y = 0; y < HEIGHT/8; y++) {
                term.locate(0, column++);
                for(int x = 0; x < WIDTH/16; x++) {
                    int value = calc->buf_Cr[y*WIDTH/16+x];
                    if (value >= THRESHOLD) {
                        fg = 0xff0000; // red
                    } else {
                        fg = 0xffffff; // white
                    }
                    if (fg != old_fg) {
                        term.foreground(fg);
                        old_fg = fg;
                    }
                    term.printf("%+4d,", value);
                    Thread::yield();
                }
            }
            term.locate(0, column++);
            term.printf("Cr:(%d,%d)", calc->x_center, calc->y_center);

            term.locate(0, column++);
            term.printf("width=%d height=%d yblock=%d EOI: %u]\nCC:", 
                         calc->width, calc->height, calc->yblock, calc->EOI_count);
            for(int i = 0; i < 16; i++) {
                term.printf(" %u", cam->report_cc_count[i]); 
            }
            term.printf("]\nPS:"); 
            for(int i = 0; i < 16; i++) {
                term.printf(" %u", cam->report_ps_cc_count[i]); 
            }
            term.printf("]\n");
            Thread::wait(150);
            led2 = !led2;
        }
    }
};

#define KP 80

void QcamOrbitAF_Control(BaseUvc* cam, CalcCenter* calc) {
    Thread::wait(10*1000);
    int unit = 9;
    int cs = 1;    
    struct PanTiltR {
        int16_t pan;
        int16_t tilt;
    } ptr = {0, 0};
    while(1) {
        if (calc->x_center != (-1)) {
            ptr.pan = ((calc->width/16/2) - calc->x_center) * KP;
            int rc = cam->Control(SET_CUR, cs, unit<<8, reinterpret_cast<uint8_t*>(&ptr), sizeof(PanTiltR));
        }
        Thread::wait(50);
        led4 = !led4;
    }
}

void no_memory () {
  error("Failed to allocate memory!\n");
}

int main() {
    term.baud(921600);
    term.printf("%s\n", __FILE__);
    set_new_handler(no_memory);

    BaseUsbHost* UsbHost = new BaseUsbHost;
    ControlEp* ctlEp = new ControlEp; // root hub
    if (UsbHub::check(ctlEp)) { // hub?
        UsbHub* hub = new UsbHub(ctlEp);
        ctlEp = hub->search<UvcCam>();
    }
    if (!UvcCam::check(ctlEp)) {
        error("UVC camera is not connected\n");
    }
    cam = new UvcCam(UVC_MJPEG, UVC_160x120, _15FPS, ctlEp); 
    calc = new CalcCenter(cam);
    calc->start();

    display_Thread* display_th = new display_Thread;
    display_th->start(osPriorityBelowNormal);

    QcamOrbitAF_Control(cam, calc);
    //Thread::wait(osWaitForever);
}

ExtensionUnitのテストプログラム

class ExtensionUnit : public RPC {
public:
    ExtensionUnit(int cam, int UnitID = 9, const char* name = NULL):RPC(name), _UnitID(UnitID) {
        _cam = reinterpret_cast<BaseUvc*>(cam);
    }
    
    int PanTilt(int pan, int tilt) {
        struct PanTiltR {
            int16_t pan;
            int16_t tilt;
        } ptr;
        ptr.pan = pan;
        ptr.tilt = tilt;
        _cs = 1;
        return _cam->Control(SET_CUR, _cs, _UnitID<<8, reinterpret_cast<uint8_t*>(&ptr), sizeof(PanTiltR));
    }
    
    int Reset(int pan, int tilt) {
        uint8_t param[1];
        param[0] = 0x00;
        if (pan) {
            param[0] |= 0x01;
        }
        if (tilt) {
            param[0] |= 0x02;
        }
        _cs = 2;
        return _cam->Control(SET_CUR, _cs, _UnitID<<8, param, sizeof(param)); 
    }

    void Control(Arguments *arg, Reply *r) {
        int unit = arg->getArg<int>();
        int cs = arg->getArg<int>();
        pc.printf("unit=%d cs=%d\n", unit, cs);
        uint8_t param[RPC_MAX_ARGS];
        int size = arg->argc-2;
        for(int i = 0; i < size; i++) {
            param[i] = arg->getArg<int>();
            pc.printf("param[%d]=%02X\n", i, param[i]); 
        }
        int rc = _cam->Control(SET_CUR, cs, unit<<8, param, size);
        r->putData<int>(rc);
    }
    
    virtual const struct rpc_method *get_rpc_methods() {
        static const rpc_method rpc_methods[] = {
            {"PanTilt", rpc_method_caller<int, ExtensionUnit, int, int, &ExtensionUnit::PanTilt>},
            {"Reset", rpc_method_caller<int, ExtensionUnit, int, int, &ExtensionUnit::Reset>},
            {"Control", rpc_method_caller<ExtensionUnit, &ExtensionUnit::Control>},
            RPC_METHOD_SUPER(RPC)
        };
        return rpc_methods;
    }
    
private:    
    int _UnitID;
    int _cs;
    BaseUvc* _cam;
};