Google weather APIから取得したお天気情報をVFDに表示します。

Dependencies:   NetServices mbed spxml

main.cpp

Committer:
kanpapa
Date:
2011-11-26
Revision:
0:e89d01416461

File content as of revision 0:e89d01416461:

//
// VFD fontx2 weather
//
// 2011/11/26 by @kanpapa
//
// Special thanks: @gingaxx
//

#include "mbed.h"

#include "EthernetNetIf.h"
#include "HTTPClient.h"

#include "spdomparser.hpp"
#include "spxmlnode.hpp"
#include "spxmlhandle.hpp"

#include "vfd_gp1059.h"
/*
=========================
FUTABA VFD GP1059A01(I/O)
-------------------------
p9     1 (D0)  I/O
p10    2 (D1)  I/O
p11    3 (D2)  I/O
p12    4 (D3)  I/O
p13    5 (D4)  I/O
p14    6 (D5)  I/O
p15    7 (D6)  I/O
p16    8 (D7)  I/O
p21    10 (INT) O
p22    11 (WR)  I
p23    12 (RD)  I
p24    13 (CS)  I
p25    14 (C/D) I
*/

VFD_GP1059   vfd(p9, p10, p11, p12, p13, p14, p15, p16,    p21, p22, p23, p24, p25);

LocalFileSystem local("local");

// LED Status
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

unsigned char reverse_bit(unsigned char x){
    const unsigned int bit[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    unsigned char y = 0;
    for (int i = 0; i < 8; i++){
        if ((bit[i] & x) != 0){
            y |= bit[7-i];
        }
    }
    return(y);
}

//
// FONTX2 test routine
// original version @gingaxx
//

//#define  kanji_file    "/local/SHMZN16X.FNT"
//#define  kanji_file  "/local/k12x10.fnt"
//#define kanji_file "/local/J2KZN16A.FNT"
//#define kanji_file "/local/XBGZN16X.TLF"
#define kanji_file "/local/MGOZN16X.TLF"

int cx = 0;
int cy = 0;
//int offsety = 0;
//bool kstate = false;
//unsigned char kbuf;

FILE *fp;   // File open buffer

unsigned short  start[92], end[92]; // table
unsigned char   font[64];           // kanji image read buffer              

char            Identifier[6+1];    // 00-05 "FONTX2"   
char            FontName[8+1];      // 06-13 Font name    
unsigned char   XSize;              // 14            
unsigned char   YSize;              // 15
unsigned char   CodeType;           // 16 0:ASCII, 1:KANJI   
unsigned char   Tnum;               // 17 Table entry number

//#define FONT_XBYTE        ((XSize + 7) >> 3)
//#define FONT_YBYTE        ((YSize + 7) >> 3)

void kanji_init(){ 
    //move cursor 
    fp = fopen(kanji_file , "r");

    if(!fp) {
        printf("File could not be opened!\n");
        led1 = 1;
        exit(1);
    }

    fgets(Identifier,   6+1, fp);    // FONTX2
    fgets(FontName,     8+1, fp);        
    fread(&XSize,       1, 1, fp);        
    fread(&YSize,       1, 1, fp);        
    fread(&CodeType,    1, 1, fp);  
    fread(&Tnum,        1, 1, fp);

    printf("Identifier: %s\n\r",Identifier);
    printf("FontName: %s\n\r",FontName);
    printf("XSize: %d\n\r",XSize);
    printf("YSize: %d\n\r",YSize);
    printf("CodeType: %d\n\r",CodeType);
    printf("Tnum: %d\n\r",Tnum);
    
    // Table read
    for (int a = 0; a < Tnum; a++){
        fread(&start[a], 1, 2, fp);
        fread(&end[a]  , 1, 2, fp);
        printf("Table No.%d start:%04x end:%04x\n\r",a,start[a],end[a]);
    }
}

//Kanji puts  cr = kanji code
void k_puts(int cr){

    const unsigned char bit_chk[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

    // LF code control
    if (cr == '\n') {
        cx = 0;
        cy++;
        return;    
    }
    
    // calculate kanji address
    int c = 0;
    int adrs = 0;
    while(cr > start[c]){
        if (cr > end[c]){
            adrs += end[c] - start[c] + 1;
        } else {
            adrs += cr - start[c];
        }
        c++;
    }
    c--;
    printf("cr=%X, table num=%d, adrs=%d \r\n",cr,c,adrs);
    
    // Kanji image Read
    fseek( fp, Tnum * 4 + 18 + 32 * adrs, SEEK_SET );
    fread( &font, 1, 32, fp);
    
    // debug dump
    //for (int s = 0; s < 32 ; s++){
    //    printf(" %02x ",font[s]);
    //}
    //printf("\r\n"); 

    // kanji put
    c = 0;
    unsigned int vfd_address = cx * 8 * 16 + cy * 2;
    //printf("VFD address: %04x\r\n",vfd_address);

    int n = 0;
    for (int j = 0; j < 2 ; j++) {
        for (int x = 0; x < 8; x++) {
            //printf("set VFD address: %04x\r\n",vfd_address);
            vfd.set_write_read_address(vfd_address);
            int m = 0;
            for (int k = 0; k < 2 ; k++) {
                unsigned int d = 0;      
                for (int i = 0; i < 8; i++) {
                    if (font[m * 2 + j] & bit_chk[x]) {
                        //printf("BIT on!\r\n");
                        d = d | 1;
                    }   
                    if (i < 7) {
                        d = d << 1;
                    }
                    //printf("i:%d, k:%d, m:%d, font:%02x, bit_chk:%02x, data:%02x\r\n",i,k,m,font[m*2+j],bit_chk[x],d);
                    m++;
                }
                //printf("send_data: %02x\r\n",d);
                vfd.send_data(d);
            }
            vfd_address = vfd_address + 8;
        }
        n++;
    }

    // move cursor 
    cx++;
    if (cx >= 15){   //LF control
        cx = 0;
        cy++;
    }
}

void kanji_end(){
    fclose(fp);
}

void display_vfd_space(){
    k_puts(0x8140);
}    

void display_vfd (const char * buf){
    unsigned int kc = 0;
    while (1) {
        // "0" - "9"  0x30-0x39 824f-8258
        // "A" - "Z"  0x41-0x4A 8260-8279
        // "a" - "z"  0x61-0x7a 8281-829a
        printf("check buf= %02x ", *buf);
        if (*buf == 0) break;
        if (*buf >= '0' && *buf <= '9') {
            kc = 0x821f + *buf;
        } else if (*buf >= 'A' && *buf <= 'Z') {
            kc = 0x821f + *buf;
        } else if (*buf >= 'a' && *buf <= 'z') {
            kc = 0x8220 + *buf;
        } else if (*buf == '%') {
            kc = 0x8193;
        } else if (*buf == '/') {
            kc = 0x815e;
        } else if (*buf == ':') {
            kc = 0x8146;
        } else if (*buf == '\n') {
            kc = '\n';
        } else if (*buf >= 0x80) {
            // kanji
            kc = *buf * 256 + *(buf + 1);
            buf++;
        } else {
            kc = 0;
        }
        buf++;
        
        printf("kc: %04x ",kc);       
        if (kc != 0) {
            k_puts(kc);
        }
    }
}

const char tokyo[7] = {0x93, 0x8c, 0x8b, 0x9e, 0x93, 0x73, 0x00};
const char otacity[7] = {0x91, 0xe5, 0x93, 0x63, 0x8b, 0xe6, 0x00};
const char today_weather[7] = {0x82, 0xcc, 0x93, 0x56, 0x8b, 0x43, 0x00};
const char kanji_condition[7] = {0x8b, 0x43, 0x89, 0xb7, 0x81, 0x46, 0x00};
const char kanji_c[3] = {0x81, 0x8e, 0x00};

EthernetNetIf eth;
HTTPClient http;

HTTPResult result;
bool completed = false;
void request_callback(HTTPResult r) {
    result = r;
    completed = true;
}

void blink_LED() {
    for (int i = 0 ; i < 5 ; i++) {
        led4 = 1;
        wait(0.2);
        led4 = 0;
        wait(0.2);
    }
    return;
}

void dispCurrent() {
    display_vfd(tokyo);
    display_vfd(otacity);
    display_vfd(today_weather);
    display_vfd_space();
    return;
}
     
void parseWeather(SP_XmlElementNode *node) {
    SP_XmlHandle handle(node);
    SP_XmlElementNode * condition = handle.getChild( "condition" ).toElement();
    if (condition) {
        printf("current condition=%s\n",condition->getAttrValue("data"));
        display_vfd(condition->getAttrValue("data"));
        display_vfd_space();
    } 
    SP_XmlElementNode * tempc = handle.getChild( "temp_c" ).toElement();
    if (tempc) {
        printf("current temp=%sC\n",tempc->getAttrValue("data"));
        display_vfd(kanji_condition);
        display_vfd(tempc->getAttrValue("data"));
        display_vfd(kanji_c);
        display_vfd_space();
    }
    SP_XmlElementNode * humidity = handle.getChild( "humidity" ).toElement();
    if (humidity) {
        printf("current humidity=%s\n", humidity->getAttrValue("data"));
        display_vfd(humidity->getAttrValue("data"));
        display_vfd_space();
    }
    SP_XmlElementNode * wind_condition = handle.getChild( "wind_condition" ).toElement();
    if (wind_condition) {
        printf("current wind_condition=%s\n",wind_condition->getAttrValue("data"));
        display_vfd(wind_condition->getAttrValue("data"));
    }
}

int main() {
    // the eth and HTTP code has be taken directly from the HTTPStream documentation page
    // see http://mbed.org/cookbook/HTTP-Client-Data-Containers

    // Start Sign
    blink_LED();

    // init VFD
    vfd.cls();
    vfd.set_disp_start_address(0);  // Display address: 000000H
    vfd.luminance_adjustment(0x0f);    // 100%

    // setup FONTX2
    kanji_init();
    printf("kanji_init()\r\n");
    
    printf("LAN setup\n");
    EthernetErr ethErr = eth.setup();
    if (ethErr) {
        printf("Error in LAN setup\n");
        vfd.cls();
        display_vfd("Error in LAN setup");
        // Close FONTX2 file    
        kanji_end();
        printf("kanji_end()\r\n");
        return -1;
    }
    printf("LAN setup ok\n");

    SP_XmlDomParser parser;

    HTTPStream stream;

    char BigBuf[512 + 1] = {0};
    stream.readNext((byte*)BigBuf, 512); //Point to buffer for the first read

    while(1){
        led1 = 1;
        //HTTPResult r = http.get("http://www.google.com/ig/api?weather=Los+Angeles", &stream, request_callback);
        HTTPResult r = http.get("http://www.google.com/ig/api?weather=ota,tokyo&hl=ja", &stream, request_callback);

        while (!completed) {
            Net::poll(); //Polls the Networking stack
            if (stream.readable()) {
                BigBuf[stream.readLen()] = 0; //Transform this buffer in a zero-terminated char* string
            
                parser.append( BigBuf, strlen(BigBuf)); // stream current buffer data to the XML parser
            
                stream.readNext((byte*)BigBuf, 512); //Buffer has been read, now we can put more data in it
            }
        }
        if (result == HTTP_OK) {
            printf("HTTP Read completely\n");
        } else {
            printf("HTTP Error %d\n", result);
            vfd.cls();
            display_vfd("HTTP Error");
            // Close FONTX2 file    
            kanji_end();
            printf("kanji_end()\r\n");
            return -1;
        }

        SP_XmlHandle rootHandle( parser.getDocument()->getRootElement() );
        SP_XmlElementNode * child2 = rootHandle.getChild( "weather" )
                                 .getChild( "current_conditions").toElement();
        led1 = 0;
    
        if ( child2 ) {
            dispCurrent();
            parseWeather(child2);
        }

        if ( NULL != parser.getError() ) {
            printf( "\n\nerror: %s\n", parser.getError() );
        }

        // scrool 30 * (10sec + 1sec * 3 + 10sec)
        led2 = 1;
        for (int loop = 0; loop < 30 ; loop++) {
            uint16_t address = 0;
            vfd.set_disp_start_address(address);
            wait(10);
        
            for (int dot = 0; dot < 3; dot++) {
                vfd.set_disp_start_address(address);
                wait(1);
                address++;
            }
            wait(10);
        }
        led2 = 0;
        
        // END Sign
        blink_LED();    

        //kanji_end();
        //printf("kanji_end()\r\n");

        printf("end\n");

        wait(60);
    }
}