早いもので、2016年から2017年に突入しようとしている
いろいろなことがあった。
まずは「Amis!」
これは、温湿度・デジタル入力変化をトリガーにメール通知(今はSlackに移行)するもの。
DD-Wrt化したBuffaloルーターに
・ARMクロスコンパイル環境の構築
・USB内臓PICの接続
・Node.jsを使ったメール通知
・iModelaにて基板切削
を行った。
次に「FON2405E拡張(シリアル通信)」
まだ実験段階だけど。
・下準備のためにラズベリー・パイのカーネルコンパイルやGPIO操作、ドライバ作成
・RalinkSDKを使用して上記を移植
・OpenWrtのtftpboot
を行った。
OpenWrtを入れるためにSPIFlashの載せ替えをするところで、年末を迎えてしまっていた。
その他
・Electronを使う機会もあり、簡易的なGUI環境を作れるようになった。
なんとなくJSを使う機会が増えたね。
・git(gogs)をいろいろ使い始めた
・親友が地元に戻り、実家を継いだ。 そして、結婚した。
・投資は目標クリア! 来年も頑張ろう
上半期は仕事が落ち着いていたので、安定的に時間をとれた気がする。
下半期は、忙しくて、なかなか時間が取れなかったかな。
でも、なんとか時間を確保して少しずつ前進できたと思う。
来年も引き続き家庭も仕事も充実するといいな。
ブログ的には
・目標探し
・楽しい教育
・投資を戦略的に行う
・「巨人の肩に乗る」
・「ググるよりもググられたい」
かな。
ちなみに年初の目標は
・Electon(NW.jsもか)を使った開発 → ×
・PICマイコンを使った開発をもっと行う → ○
・投資も頑張る → ◎
といった感じ。
2016年12月31日土曜日
2016年12月25日日曜日
ラズベリー・パイでSST26VF032の読み書き
11月の末頃にFONのフラッシュ容量拡張のために
SST26VF032Bを入手した。
microchipのオンラインストアから注文できるし、3日程度で到着した気がする。
しかし、そのまま交換してもフラッシュに書き込みができなかった。Orz
注意
SST26VF032はSPIモードでの書き込みに対応していないので、「B」有りが必要。
http://www.microchip.co.jp/support/faq_sst-fm.html
このあたりをあまり気にせずに購入していた。危なかった。。。
基礎知識
をあまり持っていなかったので、他の型番の日本語のデータシートなどを読んで雰囲気を学習
http://www.onsemi.jp/pub_link/Collateral/ENA2097JP-D.PDF
http://japan.xilinx.com/xcell/xl55/jp55xcell_13.pdf
そしてSST26VF032Bについて
・データシート
http://ww1.microchip.com/downloads/jp/DeviceDoc/jp566514.pdf
・サンプルプログラム
http://www.microchip.com/wwwproducts/jp/SST26VF032B
→末尾のソフトウェア
初期化
Quad I/Oとか特殊なものを使わないのであれば、初期化すべき項目は少ないと思う。
01H WRSRでIOCとWPENの設定くらい
JEDEC-IDを読んで対象のデバイスかどうかを確認しておく
読み込み方法
03H Readですんなりと読み出すことができる
書き込み方法
一番手こずった
PinのWriteProtectや06H WREN、そしてBlockProtectなんてものもあるOrz
最後のBlockProtectを失念していたために半月くらい悩んだ。
前述のサンプルプログラムを最初から見ておけばよかった。
こんな流れ
1.06H WREN WriteEnable
2.42H WBPR BlockProtection解除
3.02H PP PageProgram
4.05H RDSR BUSYチェック
こんな感じ。
SST26VF032Bを入手した。
microchipのオンラインストアから注文できるし、3日程度で到着した気がする。
しかし、そのまま交換してもフラッシュに書き込みができなかった。Orz
注意
SST26VF032はSPIモードでの書き込みに対応していないので、「B」有りが必要。
http://www.microchip.co.jp/support/faq_sst-fm.html
このあたりをあまり気にせずに購入していた。危なかった。。。
基礎知識
をあまり持っていなかったので、他の型番の日本語のデータシートなどを読んで雰囲気を学習
http://www.onsemi.jp/pub_link/Collateral/ENA2097JP-D.PDF
http://japan.xilinx.com/xcell/xl55/jp55xcell_13.pdf
そしてSST26VF032Bについて
・データシート
http://ww1.microchip.com/downloads/jp/DeviceDoc/jp566514.pdf
・サンプルプログラム
http://www.microchip.com/wwwproducts/jp/SST26VF032B
→末尾のソフトウェア
初期化
Quad I/Oとか特殊なものを使わないのであれば、初期化すべき項目は少ないと思う。
01H WRSRでIOCとWPENの設定くらい
JEDEC-IDを読んで対象のデバイスかどうかを確認しておく
読み込み方法
03H Readですんなりと読み出すことができる
書き込み方法
一番手こずった
PinのWriteProtectや06H WREN、そしてBlockProtectなんてものもあるOrz
最後のBlockProtectを失念していたために半月くらい悩んだ。
前述のサンプルプログラムを最初から見ておけばよかった。
こんな流れ
1.06H WREN WriteEnable
2.42H WBPR BlockProtection解除
3.02H PP PageProgram
4.05H RDSR BUSYチェック
こんな感じ。
2016年12月8日木曜日
FON2405E カスタムファーム用のドライバ開発
前回、準備としてなんちゃってドライバを作成して、insmodするところまでいけた。
次は自力シリアル通信ドライバを作成(ラズベリー・パイ用に作った奴の移植)をしてみる。
1.概要
ドライバ名はMy2nd(まだ名称が決まってないOrz)コードは末尾に記載。
Makefileは前回からドライバ名のみ変更した。
2.導入
nfsマウント
mount -o nolock 10.10.10.3:/var/lib/tftpboot /mnt
insmodしてみる
メッセージのメジャー番号が253 マイナー番号が0が重要で、コレがないと/dev/●●が作成できない。
カーネルのバージョンがアレなので、手動でスペシャルファイル?を作成する必要がある。
mknod /dev/My2nd0 c 253 0
とするとMy2nd0というデバイスファイルが作成できる。
3.テスト
作成したMy2nd0に対してechoで文字列を送ってみる。
echo -n HelloWorld!! > /dev/My2nd0
するとPIC側のコンソールに表示される。
やったーうまくいった!
4.コード
こんな感じ
次は自力シリアル通信ドライバを作成(ラズベリー・パイ用に作った奴の移植)をしてみる。
1.概要
ドライバ名はMy2nd(まだ名称が決まってないOrz)コードは末尾に記載。
Makefileは前回からドライバ名のみ変更した。
2.導入
nfsマウント
mount -o nolock 10.10.10.3:/var/lib/tftpboot /mnt
insmodしてみる
メッセージのメジャー番号が253 マイナー番号が0が重要で、コレがないと/dev/●●が作成できない。
カーネルのバージョンがアレなので、手動でスペシャルファイル?を作成する必要がある。
mknod /dev/My2nd0 c 253 0
とするとMy2nd0というデバイスファイルが作成できる。
3.テスト
作成したMy2nd0に対してechoで文字列を送ってみる。
echo -n HelloWorld!! > /dev/My2nd0
するとPIC側のコンソールに表示される。
やったーうまくいった!
4.コード
こんな感じ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __MY2ND_KM_H__ | |
#define __MY2ND_KM_H__ | |
#include <asm/rt2880/rt_mmap.h> | |
/* | |
* Address of RALINK_ Registers | |
*/ | |
#define RALINK_PRGIO_ADDR RALINK_PIO_BASE // Programmable I/O | |
#define RALINK_REG_PIODATA (RALINK_PRGIO_ADDR + 0x20) | |
#define RALINK_REG_PIODIR (RALINK_PRGIO_ADDR + 0x24) | |
#define RALINK_REG_PIOSET (RALINK_PRGIO_ADDR + 0x2C) | |
#define RALINK_REG_PIORESET (RALINK_PRGIO_ADDR + 0x30) | |
#define RALINK_GPIO(x) (1 << x) | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/moduleparam.h> | |
#include <linux/kernel.h> | |
#include <linux/fs.h> | |
#include <linux/types.h> | |
#include <linux/kdev_t.h> | |
#include <linux/errno.h> | |
#include <linux/cdev.h> | |
#include <linux/sched.h> | |
#include <linux/stat.h> | |
#include <linux/io.h> | |
#include <linux/ioport.h> | |
#include <linux/init.h> | |
#include <linux/version.h> | |
#include <linux/device.h> | |
#include <linux/slab.h> | |
#include <linux/delay.h> | |
#include <asm/uaccess.h> | |
#include <linux/timer.h> | |
#include "my2nd.h" | |
MODULE_AUTHOR("Adeno"); | |
MODULE_LICENSE("Dual BSD/GPL"); | |
#define MYSFR9_VERSION "0.4" | |
#define MYSFR9_NUM_DEVS 1 /* このドライバが制御するデバイスの数 */ | |
#define MYSFR9_DEVNAME "My2nd" /* このデバイスドライバの名称 */ | |
#define MYSFR9_MAJOR 0 /* メジャー番号だが自動設定なので0 */ | |
#define MYSFR9_MINOR 0 /* マイナー番号のベース番号 */ | |
#define GPIONO_CLKOUT 11 //LAN-LED output | |
#define GPIONO_DATAOUT 12 //NET-LED output rev | |
#define GPIONO_DATAIN 14 //WPS-LED input | |
#define UDELAY 50 //us | |
#define CHARDELAY 592 //us | |
#define RCVPOLL 10000 //us | |
#define DEFAULT_RCV_QUEUE_SIZE 8 //SFR -> | |
#define DEFAULT_SND_QUEUE_SIZE 8 // -> SFR | |
static int _mysfr9_major = MYSFR9_MAJOR; | |
static int _mysfr9_minor = MYSFR9_MINOR; | |
static struct cdev *mysfr9_cdev_array = NULL; | |
static struct class *mysfr9_class = NULL; | |
static struct timer_list poll_timer; | |
//RCV関係 SFR -> | |
static int rcv_queue_size = DEFAULT_RCV_QUEUE_SIZE; | |
static unsigned char ircv,rcv; | |
static unsigned char *rcv_queue = NULL; | |
static int rq_head, rq_tail; | |
//SND関係 -> SFR | |
static int snd_queue_size = DEFAULT_SND_QUEUE_SIZE; | |
static unsigned char isnd,snd; | |
static unsigned char *snd_queue = NULL; | |
static int sq_head, sq_tail; | |
/*プロトタイプ宣言*/ | |
//GPIO関係 | |
static void mysfr9_gpio_setup(void); | |
static int mysfr9_gpio_getpin(int pin); | |
static void mysfr9_gpio_setpin(int pin,uint32_t val); | |
static void gpio_put_msb(unsigned char isend ,unsigned char send, unsigned char *ircv,unsigned char *rcv); | |
//カーネルへの登録関係 | |
static int mysfr9_register_dev(void); | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep); | |
static int mysfr9_release(struct inode *inode, struct file *filep); | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos); | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos); | |
//File Operations構造体 | |
struct file_operations mysfr9_fops = { | |
.open = mysfr9_open, | |
.release = mysfr9_release, | |
.write = mysfr9_write, | |
.read = mysfr9_read, | |
}; | |
//タイマー関係 | |
static void register_poll_timer(void); | |
static void poll_timer_handler(unsigned long data); | |
//QUEUE関係 | |
static int ArrayEnqueue(unsigned char *queue, int data, int *head, int *tail, size_t n); | |
static unsigned char ArrayDequeue(unsigned char *queue, int *head, int *tail, size_t n); | |
//Sleep | |
static DECLARE_WAIT_QUEUE_HEAD(wq); | |
static int wq_flg = 0; | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがロードされた時の処理 | |
static int mysfr9_init(void) | |
{ | |
int retval,i; | |
/* 開始のメッセージ */ | |
printk(KERN_INFO "%s Ver.%s loading...\n", MYSFR9_DEVNAME,MYSFR9_VERSION ); | |
/* queue */ | |
sq_head=0, sq_tail=0; | |
rq_head=0, rq_tail=0; | |
if(!(rcv_queue_size > 0 && rcv_queue_size < 65536)){ | |
rcv_queue_size = DEFAULT_RCV_QUEUE_SIZE; | |
} | |
rcv_queue = kmalloc(rcv_queue_size, GFP_KERNEL); | |
if (!rcv_queue) return -ENOMEM; | |
if(!(snd_queue_size > 0 && snd_queue_size < 65536)){ | |
snd_queue_size = DEFAULT_SND_QUEUE_SIZE; | |
} | |
snd_queue = kmalloc(rcv_queue_size, GFP_KERNEL); | |
if (!snd_queue) return -ENOMEM; | |
/* デバイスドライバをカーネルに登録 */ | |
retval = mysfr9_register_dev(); | |
if( retval != 0 ) { | |
printk( KERN_ALERT "[%s] driver register failed.\n",MYSFR9_DEVNAME); | |
return retval; | |
} | |
printk( KERN_INFO "[%s] driver register sccessed.\n",MYSFR9_DEVNAME); | |
/* GPIO初期化 */ | |
mysfr9_gpio_setup(); | |
//for(i=0;i<10;i++){ | |
isnd=1; snd='I'; | |
ircv=0; rcv=0; | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
//} | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがアンロードされた時の処理 | |
static void mysfr9_exit(void) | |
{ | |
int i; | |
dev_t devno; | |
del_timer_sync(&poll_timer); | |
/* キャラクタデバイスの登録解除 */ | |
for( i = 0; i < MYSFR9_NUM_DEVS; i++ ) { | |
cdev_del(&(mysfr9_cdev_array[i])); | |
devno = MKDEV(_mysfr9_major, _mysfr9_minor+i); | |
device_destroy(mysfr9_class, devno); | |
} | |
/* メジャー番号/マイナー番号を取り除く */ | |
devno = MKDEV(_mysfr9_major,_mysfr9_minor); | |
unregister_chrdev_region(devno, MYSFR9_NUM_DEVS); | |
/* デバイスノードを取り除く */ | |
class_destroy(mysfr9_class); | |
kfree(mysfr9_cdev_array); | |
/* queue */ | |
kfree(rcv_queue); | |
kfree(snd_queue); | |
printk( KERN_INFO "[%s] driver unregister sccessed.\n",MYSFR9_DEVNAME); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep) | |
{ | |
printk(KERN_INFO "[%s] Device open sccessed.\n",MYSFR9_DEVNAME); | |
printk( KERN_INFO "[%s] FON HZ = %d\n",MYSFR9_DEVNAME,HZ); | |
register_poll_timer(); | |
return 0; | |
} | |
static int mysfr9_release(struct inode *inode, struct file *filep) | |
{ | |
//まだSFRに送信できていないないものがあるので、待ってみる | |
while ( sq_tail - sq_head ) { | |
//udelay(UDELAY); | |
msleep(1); | |
} | |
del_timer_sync(&poll_timer); | |
printk(KERN_INFO "[%s] Device release sccessed.\n",MYSFR9_DEVNAME); | |
return 0; | |
} | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos) | |
{ | |
unsigned char c; | |
if(count > 0) { | |
if(copy_from_user( &c, buf, sizeof(char) )) { | |
return -EFAULT; | |
} | |
while(ArrayEnqueue(snd_queue, c, &sq_head, &sq_tail, snd_queue_size) == 0){ | |
//udelay(UDELAY); | |
msleep(1); | |
} | |
return sizeof(char); | |
} | |
return 0; | |
} | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos){ | |
unsigned char c; | |
//printk( KERN_INFO "RCV READ cont=%d, RCVQ=%d\n",count,(rq_tail - rq_head)); | |
if(count > 0) { | |
if((rq_tail - rq_head) == 0){ | |
printk( KERN_INFO "[%s] <read> Process %i (%s) going to sleep.\n", | |
MYSFR9_DEVNAME,current->pid,current->comm); | |
wait_event_interruptible(wq,wq_flg != 0); | |
wq_flg = 0; | |
printk( KERN_INFO "[%s] <read> Awoken Process %i (%s).\n", | |
MYSFR9_DEVNAME,current->pid,current->comm); | |
} | |
c = ArrayDequeue(rcv_queue, &rq_head, &rq_tail, rcv_queue_size); | |
if(copy_to_user( buf,&c, sizeof(char) )) { | |
return -EFAULT; | |
} | |
return sizeof(char); | |
} | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//カーネルへの登録 | |
static int mysfr9_register_dev(void) | |
{ | |
int retval; | |
dev_t dev; | |
size_t size; | |
int i; | |
/* 空いているメジャー番号を使ってメジャー& | |
マイナー番号をカーネルに登録する */ | |
retval = alloc_chrdev_region( | |
&dev, /* 結果を格納するdev_t構造体 */ | |
MYSFR9_MAJOR, /* ベースマイナー番号 */ | |
MYSFR9_NUM_DEVS, /* デバイスの数 */ | |
MYSFR9_DEVNAME /* デバイスドライバの名前 */ | |
); | |
if( retval < 0 ) { | |
printk(KERN_ERR "[%s] alloc_chrdev_region failed.\n",MYSFR9_DEVNAME); | |
return retval; | |
} | |
_mysfr9_major = MAJOR(dev); | |
//printk(KERN_INFO "[%s] alloc_chrdev_region sccessed.\n",MYSFR9_DEVNAME); | |
/* デバイスクラスを作成する */ | |
mysfr9_class = class_create(THIS_MODULE,MYSFR9_DEVNAME); | |
if(IS_ERR(mysfr9_class)) | |
return PTR_ERR(mysfr9_class); | |
/* cdev構造体の用意 */ | |
size = sizeof(struct cdev) * MYSFR9_NUM_DEVS; | |
mysfr9_cdev_array = (struct cdev*)kmalloc(size, GFP_KERNEL); | |
/* デバイスの数だけキャラクタデバイスを登録する */ | |
/* ただしデバイスは1個しかない */ | |
for( i = 0; i < MYSFR9_NUM_DEVS; i++ ) { | |
dev_t devno = MKDEV(_mysfr9_major, _mysfr9_minor+i); | |
/* キャラクタデバイスとしてこのモジュールをカーネルに登録する */ | |
cdev_init(&(mysfr9_cdev_array[i]), &mysfr9_fops); | |
mysfr9_cdev_array[i].owner = THIS_MODULE; | |
if( cdev_add( &(mysfr9_cdev_array[i]), devno, 1) < 0 ) { | |
/* 登録に失敗した */ | |
printk(KERN_ERR "[%s] cdev_add failed minor = %d\n",MYSFR9_DEVNAME, _mysfr9_minor+i ); | |
} | |
else { | |
printk(KERN_INFO "[%s] cdev_add major = %d minor = %d.\n",MYSFR9_DEVNAME,_mysfr9_major,_mysfr9_minor+i); | |
/* デバイスノードの作成 */ | |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) | |
device_create( | |
mysfr9_class, | |
NULL, | |
devno, | |
NULL, | |
MYSFR9_DEVNAME"%u",_mysfr9_minor+i | |
); | |
#else | |
device_create( | |
mysfr9_class, | |
NULL, | |
devno, | |
MYSFR9_DEVNAME"%u",_mysfr9_minor+i | |
); | |
#endif | |
} | |
} | |
return 0; | |
} | |
////////////////////////////////////////////////////////////////////////////////////////////////// | |
//GPIO関係 | |
static void mysfr9_gpio_setup(void) | |
{ | |
//入出力の設定 | |
//RALINK_GPIO_SET_DIR: Bit 1 means output | |
//GPIONO_CLKOUT | |
//GPIONO_DATAOUT | |
//GPIONO_DATAIN | |
unsigned long tmp; | |
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODIR)); | |
tmp |= cpu_to_le32(RALINK_GPIO(GPIONO_CLKOUT)); | |
tmp |= cpu_to_le32(RALINK_GPIO(GPIONO_DATAOUT)); | |
tmp &= ~cpu_to_le32(RALINK_GPIO(GPIONO_DATAIN)); | |
*(volatile u32 *)(RALINK_REG_PIODIR) = tmp; | |
printk(KERN_INFO "[%s] Setup GPIO ...%ld\n", MYSFR9_DEVNAME,tmp); | |
//CLKとDATAOUT | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,1); | |
udelay(1); //debug用 200ns程度しか無いから | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,0); | |
} | |
static int mysfr9_gpio_getpin(int pin){ | |
volatile unsigned long arg,tmp; | |
arg = RALINK_GPIO(pin); | |
tmp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIODATA)); | |
tmp &= RALINK_GPIO(pin); | |
return (tmp > 0 ? 1 : 0); | |
} | |
static void mysfr9_gpio_setpin(int pin,uint32_t val){ | |
unsigned long arg; | |
arg = RALINK_GPIO(pin); | |
if(val > 0) | |
*(volatile u32 *)(RALINK_REG_PIOSET) = cpu_to_le32(arg); | |
else | |
*(volatile u32 *)(RALINK_REG_PIORESET) = cpu_to_le32(arg); | |
} | |
static void gpio_put_msb(unsigned char isend ,unsigned char send, unsigned char *ircv,unsigned char *rcv) | |
{ | |
volatile int i=0; | |
volatile unsigned char _rcv = 0; | |
volatile unsigned char _send = send; | |
unsigned int _ircv = 0; | |
unsigned int rcvbit=0; | |
//D0 データ有無ビット | |
//--DATA | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,isend); | |
udelay(1); //debug用 200ns程度しか無いから | |
//--CLK=H | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,0); | |
udelay(UDELAY); | |
//--データ有無ビット入力 | |
_ircv = mysfr9_gpio_getpin((volatile u32)GPIONO_DATAIN); | |
//--CLK=L | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,1); | |
udelay(UDELAY); | |
//printf("データ有無\t送信:%d(%c)\t受信:%d(%c)\n",isend,((isend>0) ? 'X':'-'),_ircv,((_ircv>0) ? 'X':'-')); | |
for(i=0;i<8;i++){ | |
//D1-9 データビット | |
//--データ出力 | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,((v & 0x80) == 0x80 ? 1 : 0)); | |
//printf("%d",((v & 0x80) == 0x80 ? 1 : 0)); | |
if((_send & 0x80) == 0x80){ | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,1); | |
}else{ | |
mysfr9_gpio_setpin((volatile u32)GPIONO_DATAOUT,0); | |
} | |
udelay(1); //debug用 200ns程度しか無いから | |
//--CLK=H | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,0); | |
udelay(UDELAY); | |
//--データ入力 | |
_rcv = _rcv << 1 ; | |
rcvbit = mysfr9_gpio_getpin((volatile u32)GPIONO_DATAIN); | |
if(rcvbit > 0){ | |
_rcv = _rcv | 0x01; | |
} | |
_send=_send<<1; | |
//--CLK=L | |
mysfr9_gpio_setpin((volatile u32)GPIONO_CLKOUT,1); | |
udelay(UDELAY); | |
} | |
*ircv = _ircv; | |
*rcv = _rcv; | |
//printf("----------------------------------------------------------------------------------------------------\n"); | |
/*printk(KERN_INFO "### Send:%c = %c(%#x) Rcv:%c = %c(%#x) \n", | |
((isend>0) ? 'O':'X'),((isend>0) ? send:' '),((isend>0) ? send:0x00), | |
((_ircv>0) ? 'O':'X'),((_ircv>0) ? _rcv:' '),((_ircv>0) ? _rcv:0x00));*/ | |
udelay(CHARDELAY); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//タイマー処理関係 | |
static void register_poll_timer(void) | |
{ | |
init_timer(&poll_timer); | |
//poll_timer.expires = jiffies + HZ; | |
poll_timer.expires = jiffies + (HZ * RCVPOLL) / 1000000; | |
/* 最短のTickより短い場合は最短のTickに */ | |
if( poll_timer.expires == 0 ) poll_timer.expires = jiffies + 1; | |
poll_timer.data = jiffies; | |
poll_timer.function = poll_timer_handler; | |
add_timer(&poll_timer); | |
} | |
static void poll_timer_handler(unsigned long data) | |
{ | |
do{ | |
if(sq_tail - sq_head){ | |
isnd = 1; | |
snd = ArrayDequeue(snd_queue, &sq_head, &sq_tail, snd_queue_size); | |
}else{ | |
isnd = 0; | |
} | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
if(ircv > 0){ | |
//printk( KERN_INFO "RCV %c \n",rcv); | |
if(ArrayEnqueue(rcv_queue, rcv, &rq_head, &rq_tail, rcv_queue_size) > 0){ | |
wq_flg = 1; | |
wake_up_interruptible(&wq); | |
}else{ | |
printk( KERN_ALERT "[%s] RCV Buffer Full.\n",MYSFR9_DEVNAME); | |
} | |
} | |
}while ((sq_tail - sq_head) || (ircv > 0)); | |
register_poll_timer(); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//Queue | |
static int ArrayEnqueue(unsigned char *queue, int data, int *head, int *tail, size_t n) { | |
if (*head % n != (*tail + 1) % n) { | |
queue[(*tail)++ % n] = data; | |
return *tail - *head; | |
} else { | |
return 0; | |
} | |
} | |
static unsigned char ArrayDequeue(unsigned char *queue, int *head, int *tail, size_t n) { | |
if (*head != *tail) { | |
return queue[(*head)++ % n]; | |
} else { | |
return (unsigned char)0; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//initの登録 | |
module_init(mysfr9_init); | |
//exitの登録 | |
module_exit(mysfr9_exit); | |
2016年11月28日月曜日
FON2405Eのフラッシュメモリを交換→失敗
魔が差して、フラッシュメモリの交換をしてしまった。
MX25L8006EからSST26VF032へ。
しかし、書き込みで失敗してしまう。。。
Unlocking Kernel ...
Writing from /var/cgi9yh6g9 to Kernel ... [w]Post-Write check failed.
やっぱりよく調べてからじゃないといけないね。
せめて同じメーカーとかにしておけばよかった。
酩酊買いしたので、あと20個近くある!
不良在庫にしないためにも何とか解決したいものだ。
とりあえず、ロジアナ使って、SPIモードでJEDEC-ID は読めた。
さてこれからどうしようか・・。
MX25L8006EからSST26VF032へ。
しかし、書き込みで失敗してしまう。。。
Unlocking Kernel ...
Writing from /var/cgi9yh6g9 to Kernel ... [w]Post-Write check failed.
やっぱりよく調べてからじゃないといけないね。
せめて同じメーカーとかにしておけばよかった。
酩酊買いしたので、あと20個近くある!
不良在庫にしないためにも何とか解決したいものだ。
とりあえず、ロジアナ使って、SPIモードでJEDEC-ID は読めた。
さてこれからどうしようか・・。
2016年11月16日水曜日
FON2405E カスタムファーム用のドライバ開発(準備)
FON2405EのGPIOを使ってシリアル通信をさせるため、いろいろ回り道をしながら挑戦を続けてきた。
今回は、RalinkSDKで作った FON2405E用カスタムファームに向けたドライバ開発について。
1.カスタムファームの変更
まずは、カーネルコンフィングの変更
[make menuconfig]で、[Loadable module support]以降を適当に有効化しておく
Enable loadable module supportとか。
これを忘れていて、make時にprintkとかが定義されていないと怒られた。ハマった。
http://stackoverflow.com/questions/31195516/error-building-android-kernel-module-on-ubuntu-14-04
その他に、insmodとかlsmodとか必要に応じで、有効にしておく。
ファームができたら、FONに入れておく。
2.テスト用ドライバの作成
とりあえず、準備なので何でも良い。やっつけコードを、末尾に記載。
3.Makefileの準備
ここがいろいろ試行錯誤した。
4.いざ、Make
一撃! うれしい!! 未使用変数の注意が出ているけど、知っているやつなので、放置。
これで、my1st.koができた。
5.NFSマウント
SDKのマニュアルどおり。
mount -o nolock 10.10.10.3:/var/lib/tftpboot /mnt
でOK
6.insmodしてみる
作成したmy1st.koをinsmodすると・・・。
よかったーーー。 ちゃんとprintkも動いている。
あきらめずに続けてよかった。
ラズベリー・パイで下準備しておいて本当によかった。
今回は、RalinkSDKで作った FON2405E用カスタムファームに向けたドライバ開発について。
1.カスタムファームの変更
まずは、カーネルコンフィングの変更
[make menuconfig]で、[Loadable module support]以降を適当に有効化しておく
Enable loadable module supportとか。
これを忘れていて、make時にprintkとかが定義されていないと怒られた。ハマった。
http://stackoverflow.com/questions/31195516/error-building-android-kernel-module-on-ubuntu-14-04
その他に、insmodとかlsmodとか必要に応じで、有効にしておく。
ファームができたら、FONに入れておく。
2.テスト用ドライバの作成
とりあえず、準備なので何でも良い。やっつけコードを、末尾に記載。
3.Makefileの準備
ここがいろいろ試行錯誤した。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
HOME:= /home/adeno/fongpio/sdk3301/RT288x_SDK | |
ARCH := mips | |
CROSS_COMPILE := /opt/buildroot-gcc342/bin/mipsel-linux- | |
KPATH := $(HOME)/source/linux-2.6.21.x | |
obj-m += my1st.o | |
all: | |
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KPATH) M=$(PWD) modules | |
clean: | |
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KPATH) M=$(PWD) clean |
4.いざ、Make
一撃! うれしい!! 未使用変数の注意が出ているけど、知っているやつなので、放置。
これで、my1st.koができた。
5.NFSマウント
SDKのマニュアルどおり。
mount -o nolock 10.10.10.3:/var/lib/tftpboot /mnt
でOK
6.insmodしてみる
作成したmy1st.koをinsmodすると・・・。
よかったーーー。 ちゃんとprintkも動いている。
あきらめずに続けてよかった。
ラズベリー・パイで下準備しておいて本当によかった。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/moduleparam.h> | |
#include <linux/kernel.h> | |
#include <linux/fs.h> | |
#include <linux/types.h> | |
#include <linux/kdev_t.h> | |
#include <linux/errno.h> | |
#include <linux/cdev.h> | |
#include <linux/sched.h> | |
#include <linux/stat.h> | |
#include <linux/io.h> | |
#include <linux/ioport.h> | |
#include <linux/init.h> | |
#include <linux/version.h> | |
#include <linux/device.h> | |
#include <linux/slab.h> | |
#include <linux/delay.h> | |
#include <asm/uaccess.h> | |
#include <linux/timer.h> | |
MODULE_AUTHOR("Adeno"); | |
MODULE_LICENSE("Dual BSD/GPL"); | |
#define MYSFR9_VERSION "0.1" | |
#define MYSFR9_NUM_DEVS 1 /* このドライバが制御するデバイスの数 */ | |
#define MYSFR9_DEVNAME "My1st" /* このデバイスドライバの名称 */ | |
#define MYSFR9_MAJOR 0 /* メジャー番号だが自動設定なので0 */ | |
#define MYSFR9_MINOR 0 /* マイナー番号のベース番号 */ | |
static int _mysfr9_major = MYSFR9_MAJOR; | |
static int _mysfr9_minor = MYSFR9_MINOR; | |
static struct cdev *mysfr9_cdev_array = NULL; | |
static struct class *mysfr9_class = NULL; | |
/*プロトタイプ宣言*/ | |
//カーネルへの登録関係 | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep); | |
static int mysfr9_release(struct inode *inode, struct file *filep); | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos); | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos); | |
//File Operations構造体 | |
struct file_operations mysfr9_fops = { | |
.open = mysfr9_open, | |
.release = mysfr9_release, | |
.write = mysfr9_write, | |
.read = mysfr9_read, | |
}; | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがロードされた時の処理 | |
static int mysfr9_init(void) | |
{ | |
/* 開始のメッセージ */ | |
printk(KERN_INFO "%s Ver.%s loading...\n", MYSFR9_DEVNAME,MYSFR9_VERSION ); | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがアンロードされた時の処理 | |
static void mysfr9_exit(void) | |
{ | |
printk( KERN_INFO "[%s] driver unregister sccessed.\n",MYSFR9_DEVNAME); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep) | |
{ | |
printk(KERN_INFO "[%s] Device open sccessed.\n",MYSFR9_DEVNAME); | |
return 0; | |
} | |
static int mysfr9_release(struct inode *inode, struct file *filep) | |
{ | |
printk(KERN_INFO "[%s] Device release sccessed.\n",MYSFR9_DEVNAME); | |
return 0; | |
} | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos) | |
{ | |
return 0; | |
} | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos){ | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//initの登録 | |
module_init(mysfr9_init); | |
//exitの登録 | |
module_exit(mysfr9_exit); | |
2016年11月14日月曜日
FON2405EにOpenwrt導入の挑戦
約2年ほど前、FON2405Eにカスタムファーム導入に挑戦した。
http://continue-to-challenge.blogspot.jp/2015/01/fon2405e.html
その時は、Openwrtはサイズが2MB以上になってしまい、
結局 RalinkSDK的なものを使ったカスタムファームを導入することにした。
http://continue-to-challenge.blogspot.jp/2015/01/fon2405e_24.html
http://continue-to-challenge.blogspot.jp/2015/01/fon2405e_27.html
でも、最近になって、FONのGPIOでシリアル通信をやらせたいと考えるなかで、
SDKのバージョンも古いし、FONのフラッシュ2MBしか無いのが不満に思えてきた。
いまさらだけど、フラッシュメモリを載せ替えたら幸せになれるんじゃないかと思えてきた。すでにやっている方もいるみたいだし。
https://awaitingstock.wordpress.com/2013/01/11/fon2405efonara-simpl-flsah%E8%BC%89%E3%81%9B%E6%9B%BF%E3%81%88/
そのための準備として、最新のOpenwrtはFON2405E でも動くのか?というのを確認した。
手順1 Openwrtのカーネルソース入手
基本的には、以下の手順だけど、 別にtrunkじゃなくて、安定版が欲しい時は、
https://wiki.openwrt.org/jp/doc/howto/buildroot.exigence
https://dev.openwrt.org/wiki/GetSource
「make menuconfig」後の話
Tartget System = Ralink RT288x/RT3xxx
Subtarget = RT3x5x/RT5350 based boards
ほかは必要に応じて変更
pppやusb関係が不要なら削除など。
手順3 FON2405Eにお試しインストール
先の手順で、bin/ramips/以下にバイナリイメージがたくさん作成される。
そのなかで、これを試してみる
2369793 bin/ramips/openwrt-ramips-rt305x-rt-g32-b1-initramfs-uImage.bin
なぜお試しかというと、イメージサイズが、2MB以上だからOrz
インストールできない!!
作成したイメージをTFTPサーバー上においておく、名前は適当に今回はuImage.bin。
このサーバーのIPは10.10.10.3とした(FONのU-Bootのデフォルトがそうだから) 。
FONはリセットボタンを押しながら電源ONして、U-Bootの起動オプションで3を選択!
その後、 コマンドラインから
tftpboot 80800000 uImage.bin
そして、
bootm
とすると、Openwrtが起動しました!
嬉しいけど、やっぱりインストールしたい!
フラッシュメモリを載せ替えるか!?
http://continue-to-challenge.blogspot.jp/2015/01/fon2405e.html
その時は、Openwrtはサイズが2MB以上になってしまい、
結局 RalinkSDK的なものを使ったカスタムファームを導入することにした。
http://continue-to-challenge.blogspot.jp/2015/01/fon2405e_24.html
http://continue-to-challenge.blogspot.jp/2015/01/fon2405e_27.html
でも、最近になって、FONのGPIOでシリアル通信をやらせたいと考えるなかで、
SDKのバージョンも古いし、FONのフラッシュ2MBしか無いのが不満に思えてきた。
いまさらだけど、フラッシュメモリを載せ替えたら幸せになれるんじゃないかと思えてきた。すでにやっている方もいるみたいだし。
https://awaitingstock.wordpress.com/2013/01/11/fon2405efonara-simpl-flsah%E8%BC%89%E3%81%9B%E6%9B%BF%E3%81%88/
そのための準備として、最新のOpenwrtはFON2405E でも動くのか?というのを確認した。
手順1 Openwrtのカーネルソース入手
基本的には、以下の手順だけど、 別にtrunkじゃなくて、安定版が欲しい時は、
https://wiki.openwrt.org/jp/doc/howto/buildroot.exigence
https://dev.openwrt.org/wiki/GetSource
svn co svn://svn.openwrt.org/openwrt/trunk/
を
git clone -b chaos_calmer git://github.com/openwrt/openwrt.git
にしたら幸せになれた。
手順2 Make!「make menuconfig」後の話
Tartget System = Ralink RT288x/RT3xxx
Subtarget = RT3x5x/RT5350 based boards
ほかは必要に応じて変更
pppやusb関係が不要なら削除など。
手順3 FON2405Eにお試しインストール
先の手順で、bin/ramips/以下にバイナリイメージがたくさん作成される。
そのなかで、これを試してみる
2369793 bin/ramips/openwrt-ramips-rt305x-rt-g32-b1-initramfs-uImage.bin
なぜお試しかというと、イメージサイズが、2MB以上だからOrz
インストールできない!!
作成したイメージをTFTPサーバー上においておく、名前は適当に今回はuImage.bin。
このサーバーのIPは10.10.10.3とした(FONのU-Bootのデフォルトがそうだから) 。
FONはリセットボタンを押しながら電源ONして、U-Bootの起動オプションで3を選択!
その後、 コマンドラインから
tftpboot 80800000 uImage.bin
そして、
bootm
とすると、Openwrtが起動しました!
嬉しいけど、やっぱりインストールしたい!
フラッシュメモリを載せ替えるか!?
ラズベリー・パイのカーネルビルドとクロスコンパイル環境のメモ
時間がたつと忘れそうなので、メモ
カーネルビルドとクロスコンパイル環境の作成
→ https://www.raspberrypi.org/documentation/linux/kernel/building.md
Raspiのバージョンによって手順が異なるので注意。
以下はRaspi1の場合
git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel
make bcmrpi_defconfig
カーネルビルドとクロスコンパイル環境の作成
→ https://www.raspberrypi.org/documentation/linux/kernel/building.md
Raspiのバージョンによって手順が異なるので注意。
以下はRaspi1の場合
git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel
make bcmrpi_defconfig
2016年10月23日日曜日
ラズベリー・パイで自力シリアル通信(ドライバー編)
随分と時間がかかってしまったけど、ようやく動くものになってきた。
概要
カーネルモジュール(ドライバー?)を作成して、GPIOをパタパタさせる。
8月からやっているヤツのデバドラ版。
デバイスとして扱われるので、echoやcatで入出力ができたり、既存の通信プログラムでも使えると思う。
出力されるクロックはdelayを使っているので、安定していると思う。
データのポーリングはカーネルタイマーを使っているので、
ラズベリー・パイの場合は100Hzが(10ms)が限界。
性能評価はこれから。
cat /dev/zero > /dev/MySFR9km0
とやってみると、大体350 Char/Secくらい。意外と遅い。
PIC側の設計上は960Char/Secまで行けるのはずなのだが??
メモ
request_mem_regionが毎回失敗するのはなぜだろう
早速Amisでも移植してみるか?
概要
カーネルモジュール(ドライバー?)を作成して、GPIOをパタパタさせる。
8月からやっているヤツのデバドラ版。
デバイスとして扱われるので、echoやcatで入出力ができたり、既存の通信プログラムでも使えると思う。
出力されるクロックはdelayを使っているので、安定していると思う。
データのポーリングはカーネルタイマーを使っているので、
ラズベリー・パイの場合は100Hzが(10ms)が限界。
性能評価はこれから。
cat /dev/zero > /dev/MySFR9km0
とやってみると、大体350 Char/Secくらい。意外と遅い。
PIC側の設計上は960Char/Secまで行けるのはずなのだが??
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/module.h> | |
#include <linux/moduleparam.h> | |
#include <linux/kernel.h> | |
#include <linux/fs.h> | |
#include <linux/types.h> | |
#include <linux/kdev_t.h> | |
#include <linux/errno.h> | |
#include <linux/cdev.h> | |
#include <linux/sched.h> | |
#include <linux/stat.h> | |
#include <linux/io.h> | |
#include <linux/ioport.h> | |
#include <linux/init.h> | |
#include <linux/version.h> | |
#include <linux/device.h> | |
#include <linux/slab.h> | |
#include <linux/delay.h> | |
#include <asm/uaccess.h> | |
#include <linux/timer.h> | |
#include "rpi_gpio.h" | |
MODULE_AUTHOR("Adeno"); | |
MODULE_LICENSE("Dual BSD/GPL"); | |
#define MYSFR9_NUM_DEVS 1 /* このドライバが制御するデバイスの数 */ | |
#define MYSFR9_DEVNAME "MySFR9km" /* このデバイスドライバの名称 */ | |
#define MYSFR9_MAJOR 0 /* メジャー番号だが自動設定なので0 */ | |
#define MYSFR9_MINOR 0 /* マイナー番号のベース番号 */ | |
#define MySFR9_GPIO_MAPNAME "mysfr9_gpio_map" | |
#define MYSFR_GPIO_BASE 7 | |
#define UDELAY 50 //us | |
#define CHARDELAY 592 //us | |
#define RCVPOLL 10000 //us | |
#define RCV_QUEUE_SIZE 8 //SFR -> | |
#define SND_QUEUE_SIZE 8 // -> SFR | |
static int _mysfr9_major = MYSFR9_MAJOR; | |
static int _mysfr9_minor = MYSFR9_MINOR; | |
static struct cdev *mysfr9_cdev_array = NULL; | |
static struct class *mysfr9_class = NULL; | |
static void __iomem *gpio_map; | |
volatile uint32_t *gpio_base; | |
static struct timer_list poll_timer; | |
//RCV関係 SFR -> | |
static unsigned char ircv,rcv; | |
static unsigned char rcv_queue[RCV_QUEUE_SIZE]; | |
static int rq_head, rq_tail; | |
//SND関係 -> SFR | |
static unsigned char isnd,snd; | |
static unsigned char snd_queue[SND_QUEUE_SIZE]; | |
static int sq_head, sq_tail; | |
/*プロトタイプ宣言*/ | |
//GPIOレジスタのマップ関係 | |
static int mysfr9_gpio_map(void); | |
static int mysfr9_gpio_unmap(void); | |
static void mysfr9_gpio_setup(void); | |
static int rpi_gpio_function_set(int pin, uint32_t func); | |
static int rpi_gpio_pull_control(int pin, uint32_t pullmode); | |
static void rpi_gpio_set32( uint32_t mask, uint32_t val ); | |
//static uint32_t rpi_gpio_get32( uint32_t mask ); | |
static void rpi_gpio_clear32( uint32_t mask, uint32_t val ); | |
static uint32_t rpi_gpio_getpin( int pin ); | |
static void gpio_put_msb(unsigned char isend ,unsigned char send, unsigned char *ircv,unsigned char *rcv); | |
//カーネルへの登録関係 | |
static int mysfr9_register_dev(void); | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep); | |
static int mysfr9_release(struct inode *inode, struct file *filep); | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos); | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos); | |
//File Operations構造体 | |
struct file_operations mysfr9_fops = { | |
.open = mysfr9_open, | |
.release = mysfr9_release, | |
.write = mysfr9_write, | |
.read = mysfr9_read, | |
}; | |
//タイマー関係 | |
static void register_poll_timer(void); | |
static void poll_timer_handler(unsigned long data); | |
//QUEUE関係 | |
static int ArrayEnqueue(unsigned char *queue, int data, int *head, int *tail, size_t n); | |
static unsigned char ArrayDequeue(unsigned char *queue, int *head, int *tail, size_t n); | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがロードされた時の処理 | |
static int mysfr9_init(void) | |
{ | |
int retval; | |
/* 開始のメッセージ */ | |
printk(KERN_INFO "%s loading...\n", MYSFR9_DEVNAME ); | |
sq_head=0, sq_tail=0; | |
rq_head=0, rq_tail=0; | |
/* GPIOレジスタがマップ可能か調べる */ | |
retval = mysfr9_gpio_map(); | |
if( retval != 0 ) { | |
printk( KERN_ALERT "Can not use GPIO registers.\n"); | |
return -EBUSY; | |
} | |
/* GPIO初期化 */ | |
mysfr9_gpio_setup(); | |
isnd=1; snd='I'; | |
ircv=0; rcv=0; | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
/* デバイスドライバをカーネルに登録 */ | |
retval = mysfr9_register_dev(); | |
if( retval != 0 ) { | |
printk( KERN_ALERT "MySFR9 driver register failed.\n"); | |
return retval; | |
} | |
printk( KERN_INFO "MySFR9 driver register sccessed.\n"); | |
/* GPIOレジスタのアンマップ */ | |
mysfr9_gpio_unmap(); | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスドライバがアンロードされた時の処理 | |
static void mysfr9_exit(void) | |
{ | |
int i; | |
dev_t devno; | |
del_timer_sync(&poll_timer); | |
/* キャラクタデバイスの登録解除 */ | |
for( i = 0; i < MYSFR9_NUM_DEVS; i++ ) { | |
cdev_del(&(mysfr9_cdev_array[i])); | |
devno = MKDEV(_mysfr9_major, _mysfr9_minor+i); | |
device_destroy(mysfr9_class, devno); | |
} | |
/* メジャー番号/マイナー番号を取り除く */ | |
devno = MKDEV(_mysfr9_major,_mysfr9_minor); | |
unregister_chrdev_region(devno, MYSFR9_NUM_DEVS); | |
/* デバイスノードを取り除く */ | |
class_destroy( mysfr9_class ); | |
/* GPIOレジスタのアンマップ */ | |
mysfr9_gpio_unmap(); | |
kfree(mysfr9_cdev_array); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//デバイスに対する処理 | |
static int mysfr9_open(struct inode *inode, struct file *filep) | |
{ | |
int retval; | |
if( gpio_base != NULL ) { | |
/* すでにオープンされている */ | |
printk(KERN_ERR "MySFR9 is already open.\n" ); | |
return -EIO; | |
} | |
retval = mysfr9_gpio_map(); | |
if( retval != 0 ) { | |
printk(KERN_ERR "Can not open MySFR9.\n" ); | |
return retval; | |
} | |
printk( KERN_INFO "RPI HZ = %d\n", HZ ); | |
register_poll_timer(); | |
return 0; | |
} | |
static int mysfr9_release(struct inode *inode, struct file *filep) | |
{ | |
//まだSFRに送信できていないないものがあるので、待ってみる | |
while ( sq_tail - sq_head ) { | |
udelay(UDELAY); | |
} | |
del_timer_sync(&poll_timer); | |
mysfr9_gpio_unmap(); | |
return 0; | |
} | |
static ssize_t mysfr9_write(struct file *filep,const char __user *buf, size_t count, loff_t *f_pos) | |
{ | |
//char cvalue; | |
//int retval; | |
unsigned char c; | |
if(count > 0) { | |
if(copy_from_user( &c, buf, sizeof(char) )) { | |
return -EFAULT; | |
} | |
while(ArrayEnqueue(snd_queue, c, &sq_head, &sq_tail, SND_QUEUE_SIZE) == 0){ | |
//udelay(UDELAY); | |
msleep(1); | |
} | |
//isnd=1; | |
//ircv=0; rcv=0; | |
//gpio_put_msb(isnd,snd,&ircv,&rcv); | |
/*retval = ssegled_put(cvalue); | |
if( retval != 0 ) { | |
printk(KERN_ALERT "Can not display %d\n", cvalue ); | |
} | |
else { | |
ssegled_display_value = cvalue; | |
}*/ | |
return sizeof(char); | |
} | |
return 0; | |
} | |
static ssize_t mysfr9_read(struct file *filep,char __user *buf,size_t count, loff_t *f_pos){ | |
unsigned char c; | |
//printk( KERN_INFO "RCV READ cont=%d, RCVQ=%d\n",count,(rq_tail - rq_head)); | |
if(count > 0) { | |
while((rq_tail - rq_head) == 0){ | |
//udelay(UDELAY); | |
msleep(1); | |
} | |
c = ArrayDequeue(rcv_queue, &rq_head, &rq_tail, RCV_QUEUE_SIZE); | |
//printk( KERN_INFO "RCV READ char=%c\n",c); | |
if(copy_to_user( buf,&c, sizeof(char) )) { | |
return -EFAULT; | |
} | |
return sizeof(char); | |
} | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//カーネルへの登録 | |
static int mysfr9_register_dev(void) | |
{ | |
int retval; | |
dev_t dev; | |
size_t size; | |
int i; | |
/* 空いているメジャー番号を使ってメジャー& | |
マイナー番号をカーネルに登録する */ | |
retval = alloc_chrdev_region( | |
&dev, /* 結果を格納するdev_t構造体 */ | |
MYSFR9_MAJOR, /* ベースマイナー番号 */ | |
MYSFR9_NUM_DEVS, /* デバイスの数 */ | |
MYSFR9_DEVNAME /* デバイスドライバの名前 */ | |
); | |
if( retval < 0 ) { | |
printk(KERN_ERR "alloc_chrdev_region failed.\n" ); | |
return retval; | |
} | |
_mysfr9_major = MAJOR(dev); | |
/* デバイスクラスを作成する */ | |
mysfr9_class = class_create(THIS_MODULE,MYSFR9_DEVNAME); | |
if(IS_ERR(mysfr9_class)) | |
return PTR_ERR(mysfr9_class); | |
/* cdev構造体の用意 */ | |
size = sizeof(struct cdev) * MYSFR9_NUM_DEVS; | |
mysfr9_cdev_array = (struct cdev*)kmalloc(size, GFP_KERNEL); | |
/* デバイスの数だけキャラクタデバイスを登録する */ | |
/* ただし7セグLEDは1個しかない */ | |
for( i = 0; i < MYSFR9_NUM_DEVS; i++ ) { | |
dev_t devno = MKDEV(_mysfr9_major, _mysfr9_minor+i); | |
/* キャラクタデバイスとしてこのモジュールをカーネルに登録する */ | |
cdev_init(&(mysfr9_cdev_array[i]), &mysfr9_fops); | |
mysfr9_cdev_array[i].owner = THIS_MODULE; | |
if( cdev_add( &(mysfr9_cdev_array[i]), devno, 1) < 0 ) { | |
/* 登録に失敗した */ | |
printk(KERN_ERR "cdev_add failed minor = %d\n", _mysfr9_minor+i ); | |
} | |
else { | |
/* デバイスノードの作成 */ | |
device_create( | |
mysfr9_class, | |
NULL, | |
devno, | |
NULL, | |
MYSFR9_DEVNAME"%u",_mysfr9_minor+i | |
); | |
} | |
} | |
return 0; | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//GPIOレジスタのマップ関係 | |
static int mysfr9_gpio_map(void) | |
{ | |
if( !request_mem_region(RPI_GPIO_BASE, | |
RPI_BLOCK_SIZE, | |
MySFR9_GPIO_MAPNAME) ) { | |
printk( KERN_ALERT "request_mem_region failed.\n"); | |
//return -EBUSY; | |
} | |
gpio_map = ioremap_nocache(RPI_GPIO_BASE, BLOCK_SIZE); | |
gpio_base = (volatile uint32_t *)gpio_map; | |
return 0; | |
} | |
static int mysfr9_gpio_unmap(void) | |
{ | |
iounmap(gpio_map); | |
release_mem_region(RPI_GPIO_BASE, RPI_BLOCK_SIZE); | |
gpio_map = NULL; | |
gpio_base = NULL; | |
return 0; | |
} | |
static void mysfr9_gpio_setup(void) | |
{ | |
rpi_gpio_function_set(MYSFR_GPIO_BASE+0, RPI_GPF_OUTPUT);//CLK-OUT | |
rpi_gpio_function_set(MYSFR_GPIO_BASE+1, RPI_GPF_OUTPUT);//DATA-OUT | |
rpi_gpio_function_set(MYSFR_GPIO_BASE+2, RPI_GPF_INPUT);//DATA-INPUT | |
rpi_gpio_pull_control(MYSFR_GPIO_BASE+2,RPI_GPIO_PULLUP); | |
} | |
static int rpi_gpio_function_set(int pin, uint32_t func) | |
{ | |
int index = RPI_GPFSEL0_INDEX + pin / 10; | |
uint32_t mask = ~(0x7 << ((pin % 10) * 3)); | |
gpio_base[index] = (gpio_base[index] & mask) | ((func & 0x7) << ((pin % 10) * 3)); | |
return 1; | |
} | |
static int rpi_gpio_pull_control(int pin, uint32_t pullmode) | |
{ | |
gpio_base[RPI_GPPUD_INDEX] = pullmode & 0x03; | |
gpio_base[RPI_GPPUDCLK0_INDEX] = 0x01 << pin; | |
// wait > 150 cycles | |
udelay(100); | |
gpio_base[RPI_GPPUDCLK0_INDEX] = 0; | |
gpio_base[RPI_GPPUD_INDEX] = 0; | |
return 1; | |
} | |
static void rpi_gpio_set32(uint32_t mask, uint32_t val ) | |
{ | |
gpio_base[RPI_GPSET0_INDEX] = val & mask; | |
} | |
/*static uint32_t rpi_gpio_get32( uint32_t mask ) | |
{ | |
return gpio_base[RPI_GPLEV0_INDEX] & mask; | |
}*/ | |
static void rpi_gpio_clear32(uint32_t mask, uint32_t val ) | |
{ | |
gpio_base[RPI_GPCLR0_INDEX] = val & mask; | |
} | |
static uint32_t rpi_gpio_getpin(int pin ) | |
{ | |
return (gpio_base[RPI_GPLEV0_INDEX] & (1 << pin)) != 0; | |
} | |
static void gpio_put_msb(unsigned char isend ,unsigned char send, unsigned char *ircv,unsigned char *rcv) | |
{ | |
volatile int i=0; | |
volatile unsigned char _rcv = 0; | |
volatile unsigned char _send = send; | |
unsigned int _ircv = 0; | |
unsigned int rcvbit=0; | |
//D0 データ有無ビット | |
//--DATA | |
if(isend){ | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (2 & 0x0F) << MYSFR_GPIO_BASE); | |
}else{ | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (2 & 0x0F) << MYSFR_GPIO_BASE); | |
} | |
//--CLK=H | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (1 & 0x0F) << MYSFR_GPIO_BASE); | |
udelay(UDELAY); | |
//--データ有無ビット入力 | |
_ircv = rpi_gpio_getpin(MYSFR_GPIO_BASE+2); | |
//--CLK=L | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (1 & 0x0F) << MYSFR_GPIO_BASE); | |
udelay(UDELAY); | |
//printf("データ有無\t送信:%d(%c)\t受信:%d(%c)\n",isend,((isend>0) ? 'X':'-'),_ircv,((_ircv>0) ? 'X':'-')); | |
for(i=0;i<8;i++){ | |
//D1-9 データビット | |
//--データ出力 | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,((v & 0x80) == 0x80 ? 1 : 0)); | |
//printf("%d",((v & 0x80) == 0x80 ? 1 : 0)); | |
if((_send & 0x80) == 0x80){ | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (2 & 0x0F) << MYSFR_GPIO_BASE); | |
}else{ | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (2 & 0x0F) << MYSFR_GPIO_BASE); | |
} | |
//--CLK=H | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (1 & 0x0F) << MYSFR_GPIO_BASE); | |
udelay(UDELAY); | |
//--データ入力 | |
_rcv = _rcv << 1 ; | |
rcvbit = rpi_gpio_getpin(MYSFR_GPIO_BASE+2); | |
//printf("c=%d,gpin=%d\n",c,gpin); | |
if(rcvbit > 0){ | |
_rcv = _rcv | 0x01; | |
} | |
_send=_send<<1; | |
//--CLK=L | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (1 & 0x0F) << MYSFR_GPIO_BASE); | |
udelay(UDELAY); | |
} | |
*ircv = _ircv; | |
*rcv = _rcv; | |
//printf(" 内容\t送信:%c(%#x)\t受信:%c(%#x)\n",send,send,*rcv,*rcv); | |
//printf("----------------------------------------------------------------------------------------------------\n"); | |
//printf("### 送信:%c - %c(%#x) 受信:%c - %c(%#x)\n",((isend>0) ? 'O':'X'),send,send,((_ircv>0) ? 'O':'X'),_rcv,_rcv); | |
udelay(CHARDELAY); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//タイマー処理関係 | |
static void register_poll_timer(void) | |
{ | |
init_timer(&poll_timer); | |
//poll_timer.expires = jiffies + HZ; | |
poll_timer.expires = jiffies + (HZ * RCVPOLL) / 1000000; | |
/* 最短のTickより短い場合は最短のTickに */ | |
if( poll_timer.expires == 0 ) poll_timer.expires = jiffies + 1; | |
poll_timer.data = jiffies; | |
poll_timer.function = poll_timer_handler; | |
add_timer(&poll_timer); | |
} | |
static void poll_timer_handler(unsigned long data) | |
{ | |
//unsigned char ircv,rcv; | |
//unsigned char isnd,snd; | |
do{ | |
if(sq_tail - sq_head){ | |
isnd = 1; | |
snd = ArrayDequeue(snd_queue, &sq_head, &sq_tail, SND_QUEUE_SIZE); | |
}else{ | |
isnd = 0; | |
} | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
if(ircv > 0){ | |
//printk( KERN_INFO "RCV %c \n",rcv); | |
if(ArrayEnqueue(rcv_queue, rcv, &rq_head, &rq_tail, RCV_QUEUE_SIZE) > 0){ | |
}else{ | |
printk( KERN_ALERT "RCV Buffer Full.\n"); | |
} | |
} | |
}while ((sq_tail - sq_head) || (ircv > 0)); | |
/*while ((q_tail - q_head) || (ircv > 0)) { | |
if(q_tail - q_head){ | |
isnd = 1; | |
snd = ArrayDequeue(queue, &q_head, &q_tail, QUEUE_SIZE); | |
}else{ | |
isnd = 0; | |
} | |
gpio_put_msb(isnd,snd,&ircv,&rcv); | |
isnd = 0; | |
}*/ | |
//isnd=1; snd='P'; | |
//ircv=0; rcv=0; | |
//gpio_put_msb(isnd,snd,&ircv,&rcv); | |
//isnd=0; | |
register_poll_timer(); | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//Queue | |
static int ArrayEnqueue(unsigned char *queue, int data, int *head, int *tail, size_t n) { | |
if (*head % n != (*tail + 1) % n) { | |
queue[(*tail)++ % n] = data; | |
return *tail - *head; | |
} else { | |
return 0; | |
} | |
} | |
static unsigned char ArrayDequeue(unsigned char *queue, int *head, int *tail, size_t n) { | |
if (*head != *tail) { | |
return queue[(*head)++ % n]; | |
} else { | |
return (unsigned char)0; | |
} | |
} | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
//initの登録 | |
module_init(mysfr9_init); | |
//exitの登録 | |
module_exit(mysfr9_exit); |
メモ
request_mem_regionが毎回失敗するのはなぜだろう
早速Amisでも移植してみるか?
2016年9月21日水曜日
PHPからslackに投稿する(WebPI)
最近ますます流行ってきているSlackを導入してみて2日経過した。
PHPからPOSTで投稿してみた。
rsyslogと連携して、sshdのログイン/ログアウトを通知するようにしてみた。
#attachmentsの入れ方がわからなくて、ものすごく苦労したOrz
PHPからPOSTで投稿してみた。
rsyslogと連携して、sshdのログイン/ログアウトを通知するようにしてみた。
#attachmentsの入れ方がわからなくて、ものすごく苦労したOrz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
echo "sndmsg_slack.php run...".PHP_EOL; | |
$slackApiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; | |
$url = "https://slack.com/api/chat.postMessage"; | |
$argchk = false; | |
if(count($argv) == 4){ | |
if($argv[1]=="GET"){ | |
$argchk = true; | |
/// GET /////////////////////////////////////////////////////////// | |
$query = [ 'token' => $slackApiKey, | |
'channel' => '#'.$argv[2], | |
'text' => str_replace("\\n",PHP_EOL,$argv[3]), | |
'as_user' => 'true' | |
]; | |
echo "[GET]URL=".$url.http_build_query($query).PHP_EOL; | |
$result = file_get_contents($url."?".http_build_query($query)); | |
echo $result.PHP_EOL; | |
/////////////////////////////////////////////////////////////////// | |
} | |
} | |
if(count($argv) == 7){ | |
if($argv[1]=="POST"){ | |
$argchk = true; | |
/// PST /////////////////////////////////////////////////////////// | |
$attachment = ['pretext' => $argv[3], | |
'color' => $argv[4], | |
'title' => $argv[5], | |
'text' => $argv[6]]; | |
$query = [ 'token' => $slackApiKey, | |
'channel' => '#'.$argv[2], | |
'attachments' => json_encode(Array($attachment)), | |
'as_user' => 'true' | |
]; | |
$options = array( | |
'http' => array( | |
'header' => "Content-Type: application/x-www-form-urlencoded\r\n", | |
'method' => 'POST', | |
'content' => http_build_query($query) | |
) | |
); | |
$context = stream_context_create($options); | |
echo "[POST]QUERY=".json_encode($query).PHP_EOL; | |
$result = file_get_contents($url, false, $context); | |
echo $result.PHP_EOL; | |
} | |
// $result = json_decode($result); | |
// $obj = json_decode(json_encode($query)); | |
// var_dump($obj); | |
} | |
if(!$argchk){ | |
echo "[mode] [channel] [text]".PHP_EOL; | |
echo "\tmode\tGET or POST".PHP_EOL; | |
echo "GET [channel] [message]".PHP_EOL; | |
echo "POST [channel] [pretext] [color] [title] [text]".PHP_EOL; | |
} | |
?> |
2016年9月20日火曜日
Slackインストール
〇〇botとか作ってみたくて、でもLineは私用なので、分けてみたいと思っていたら、slackというものを発見した。
これなら今までメール通知でやっていたものを置き換えできそう!!
メール通知
http://webos-goodies.jp/archives/50645131.html
<参考>
http://toach.click/slack-botkit/
http://lab.aratana.jp/entry/2014/12/04/185053
http://tech.machiiro.jp/entry/2016/05/13/090000
https://elstreet.style/?p=1124
https://elstreet.style/?p=1099
これなら今までメール通知でやっていたものを置き換えできそう!!
メール通知
http://webos-goodies.jp/archives/50645131.html
<参考>
http://toach.click/slack-botkit/
http://lab.aratana.jp/entry/2014/12/04/185053
http://tech.machiiro.jp/entry/2016/05/13/090000
https://elstreet.style/?p=1124
https://elstreet.style/?p=1099
2016年9月3日土曜日
MPLABXをLINUXで使ったら文字化け
バージョンアップの度にはまるので、備忘録として
日本語が表示できるいい感じのフォントをfonts/fallbackにぶち込んでおく
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipag.ttf
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipamp.ttf
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipam.ttf
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipagp.ttf
これだけ。毎回忘れる。Orz
日本語が表示できるいい感じのフォントをfonts/fallbackにぶち込んでおく
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipag.ttf
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipamp.ttf
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipam.ttf
/opt/microchip/mplabx/v3.40/sys/java/jre1.8.0_91/lib/fonts/fallback/ipagp.ttf
これだけ。毎回忘れる。Orz
2016年8月31日水曜日
ラズペリーパイで自力シリアル通信
ひょんなことから、過去にFONのGPIOを使ったなんちゃってシリアル通信を実装したのを思い出した。過去の投稿
当時は、ラズベリーパイが注目されていて、いいな−と思いつつ、ちょっと高いなと感じており、中古で@500円程度で入手できるFONを何とか拡張できなかと思っていた。
結局受信エラーが抑えきれなくて、途中興味を失ってしまった。
最近になって、
1.2014年7月 トランジスタ技術
2.LINUXデバイスドライバ
3.RaspberryPiで学ぶARMデバイスドライバープログラミング
を読む機会があって、FONでやりたかったことを再度挑戦してみようと思った。
そのまえに、情報が豊富なラズベリーパイで準備運動をしてみた記録。
概要
ユーザーランドでGPIOをパタパタさせて、同期型シリアル通信を行い、
PICマイコンにて、UARTに変換する。
ラズピでuname -aを実行してPIC経由のURATで受信した結果。
ラズピ側
ユーザーランドでGPIOをパタパタさせるプログラム
ほとんど前述の 「3」のとおり
GPIO7 - CLK OUT
GPIO8 - DATA OUT
PIC側
RB0 - CLK IN (割り込み)
RB5 - DATA IN
RB2 - TX
なんとなく達成感があるね。
次はPICからラズピ側に送信する機能を作ってみよう。
当時は、ラズベリーパイが注目されていて、いいな−と思いつつ、ちょっと高いなと感じており、中古で@500円程度で入手できるFONを何とか拡張できなかと思っていた。
結局受信エラーが抑えきれなくて、途中興味を失ってしまった。
最近になって、
1.2014年7月 トランジスタ技術
2.LINUXデバイスドライバ
3.RaspberryPiで学ぶARMデバイスドライバープログラミング
を読む機会があって、FONでやりたかったことを再度挑戦してみようと思った。
そのまえに、情報が豊富なラズベリーパイで準備運動をしてみた記録。
概要
ユーザーランドでGPIOをパタパタさせて、同期型シリアル通信を行い、
PICマイコンにて、UARTに変換する。
ラズピでuname -aを実行してPIC経由のURATで受信した結果。
ラズピ側
ユーザーランドでGPIOをパタパタさせるプログラム
ほとんど前述の 「3」のとおり
GPIO7 - CLK OUT
GPIO8 - DATA OUT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <rpi_gpio.h> | |
#include <rpi_gpiolib.h> | |
#define LED_BASE 7 | |
void led_init(void) | |
{ | |
// GPIOファンクションセット | |
rpi_gpio_function_set( LED_BASE+0, RPI_GPF_OUTPUT );//CLK | |
rpi_gpio_function_set( LED_BASE+1, RPI_GPF_OUTPUT );//DATA | |
rpi_gpio_function_set( LED_BASE+2, RPI_GPF_OUTPUT ); | |
rpi_gpio_function_set( LED_BASE+3, RPI_GPF_OUTPUT ); | |
} | |
void gpio_put_lsb(unsigned char v ) | |
{ | |
// 4ビットクリア | |
//rpi_gpio_clear32( RPI_GPIO_P1MASK, (3 & 0x0F) << LED_BASE); | |
printf("0b"); | |
volatile int i=0; | |
for(i=0;i<8;i++){ | |
//CLK=L | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
//DATA | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,v%2); | |
printf("%d",v%2); | |
if(v % 2 == 1){ | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
}else{ | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
} | |
usleep(100); | |
//CLK=H | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
v=v>>1; | |
} | |
printf("\n"); | |
} | |
void gpio_put_msb(unsigned char v ) | |
{ | |
// 4ビットクリア | |
//rpi_gpio_clear32( RPI_GPIO_P1MASK, (3 & 0x0F) << LED_BASE); | |
printf("0b"); | |
volatile int i=0; | |
for(i=0;i<8;i++){ | |
//CLK=L | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
//DATA | |
//printf("i=%d,v=%#x,v2=%d\n",i,v,((v & 0x80) == 0x80 ? 1 : 0)); | |
printf("%d",((v & 0x80) == 0x80 ? 1 : 0)); | |
if((v & 0x80) == 0x80){ | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
}else{ | |
rpi_gpio_clear32( RPI_GPIO_P1MASK, (2 & 0x0F) << LED_BASE); | |
} | |
usleep(100); | |
//CLK=H | |
rpi_gpio_set32( RPI_GPIO_P1MASK, (1 & 0x0F) << LED_BASE); | |
usleep(100); | |
v=v<<1; | |
} | |
printf("\n"); | |
} | |
int main(int argc,char *argv[]) | |
{ | |
// GPIO初期化 | |
if( ! rpi_gpio_init() ) | |
return -1; | |
led_init(); | |
int c=0; | |
if(argc==2){ | |
while(argv[1][c]){ | |
//ASCII値として送信する | |
printf("Char = %c(%#x) ",argv[1] [c],argv[1] [c]); | |
gpio_put_msb(argv[1] [c]); | |
c++; | |
} | |
}else if(argc==3){ //s | |
char buf[512]; | |
fgets(buf, sizeof(buf), stdin); | |
while(buf[c]){ | |
//ASCII値として送信する | |
printf("Char = %c(%#x) ",buf[c],buf[c]); | |
gpio_put_msb(buf[c]); | |
c++; | |
} | |
}else{ | |
unsigned int value = 0; | |
for( value = 0; value < 10; value++ ) { | |
printf("LED = %d\n", value ); | |
gpio_put_lsb(value); | |
sleep(1); | |
} | |
} | |
// mmap開放 | |
rpi_gpio_deinit(); | |
return 1; | |
} |
RB0 - CLK IN (割り込み)
RB5 - DATA IN
RB2 - TX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* File: main.c | |
* Author: adeno | |
* | |
* Created on 2016/08/31, 9:58 | |
*/ | |
#include <xc.h> | |
// CONFIG | |
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) | |
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) | |
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) | |
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) | |
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) | |
#pragma config LVP = ON // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled) | |
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) | |
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) | |
#define _XTAL_FREQ 4000000 // delay_ms(x) のための定義 | |
unsigned char rbuf=0,rcnt=0; | |
void putsUSART(char *str){ | |
while(*str){ | |
while (!TXIF); | |
TXREG = *str++; | |
} | |
} | |
void putc(unsigned char c){ | |
while(!TXIF){ | |
} | |
TXREG = c; | |
} | |
static void interrupt intr(void) { | |
if(INTF){ //INT割り込み | |
INTE = 0; //INT割り込み禁止 | |
INTF = 0; | |
if(RB5 ==1){ | |
rbuf = (rbuf<<1) + 0x01; | |
}else{ | |
rbuf = (rbuf<<1) + 0x00; | |
} | |
rcnt++; | |
if(rcnt >= 8){ | |
rcnt=0; | |
putc(rbuf); | |
} | |
INTE = 1; //INT割り込み開始 | |
} | |
} | |
void main(void) { | |
OSCF = 1; //4MHz | |
PORTA = 0b00000000; //PORTAの中身をきれいにする | |
TRISA = 0b00000000; //PORTAは 1:入力 0:出力 | |
PORTB = 0b00000000; //PORTBの中身をきれいにする | |
TRISB = 0b00100111; //PORTBは 1:入力 0:出力 | |
PORTB = 0b00001000; | |
//USARTの初期化 | |
TXSTA = 0b00100100; | |
RCSTA = 0b10010000; | |
SPBRG = 25; //ボーレート9600dpb @4MHz | |
//割り込みの設定 | |
INTEDG = 1; //RB0 立ち上がり | |
INTF = 0; // RB0/INT外部割込みフラグをクリア | |
INTE = 1; // RB0/INT外部割込み許可 | |
GIE = 1; // すべての割り込み許可 | |
//SFR-RXの初期化 | |
rbuf = 0; | |
rcnt = 0; | |
unsigned char wtim=0; | |
__delay_ms(100); // 100ms | |
putsUSART("Hello OK>\r\n"); | |
while(1){ | |
PORTB = 0b00001000; | |
__delay_ms(100); // 100ms | |
//putsUSART("Hello OK>\r\n"); | |
PORTB = 0b00000000; | |
__delay_ms(100); // 100ms | |
if(rcnt>0){ | |
wtim++; | |
if(wtim==10){ | |
rcnt=0; | |
wtim=0; | |
putsUSART("Timeout\r\n"); | |
} | |
} | |
} | |
return; | |
} |
次はPICからラズピ側に送信する機能を作ってみよう。
2016年8月22日月曜日
2つ同時に初期不良品をつかんでしまった
こんなこともあるのかと・・・。
Amazonで購入した3TBの外付けHDDと近所のハードオフで購入した光BOX3が見事に初期不良品だった。
・HDD MAL33000EX3 3TB @9,890
安さに惹かれてついつい買ってしまい、レビューを見て愕然。
リフレッシュ品とか初期不良の文字が目立つ。
実際HDDとして認識しないし、フォーマットかけてもエラーになるし・・・。
・光BOX3 @1,500
HDMI出力されない。TVにつないでもパソコンモニターにつないでもだめ。
まぁついていないことは重なるものだね。。。
返品できるかなぁ。Orz
Amazonで購入した3TBの外付けHDDと近所のハードオフで購入した光BOX3が見事に初期不良品だった。
・HDD MAL33000EX3 3TB @9,890
安さに惹かれてついつい買ってしまい、レビューを見て愕然。
リフレッシュ品とか初期不良の文字が目立つ。
実際HDDとして認識しないし、フォーマットかけてもエラーになるし・・・。
・光BOX3 @1,500
HDMI出力されない。TVにつないでもパソコンモニターにつないでもだめ。
まぁついていないことは重なるものだね。。。
返品できるかなぁ。Orz
2016年7月12日火曜日
でんき家計簿のデータをMySQLに保存する(phantom.jsを使う)
先日、selenium+firefoxを使用したでんき家計簿のスクレイピング をやってみた。
次はphantom.jsを使ってcronで実行できるようにしたいと思った。
といっても、driverの部分を変えるだけ。
最初は、
と書いていたんだけど、cronで実行するとphantom.jsのパスが見つからないと怒られてしまった。
調べてみると、適切な書き方があった。
これを定期的に呼べばいい感じに電力使用量が入手できる。
次はphantom.jsを使ってcronで実行できるようにしたいと思った。
といっても、driverの部分を変えるだけ。
最初は、
var driver = new webdriver.Builder().forBrowser('phantomjs',phantomjs.path).build();
と書いていたんだけど、cronで実行するとphantom.jsのパスが見つからないと怒られてしまった。
調べてみると、適切な書き方があった。
var driver = new webdriver.Builder() .withCapabilities({"phantomjs.binary.path":phantomjs.path}) .forBrowser('phantomjs') .build();これでOK!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var argv = require("minimist")(process.argv.slice(2)); | |
if(!argv.u || !argv.p){ | |
console.log(process.argv[1] + ' -u [userid] -p [password]'); | |
console.log('\toption -d DB Write Mode'); | |
console.log('\toption -c Phantom Mode'); | |
return 0; | |
} | |
if(argv.d){ | |
if(!argv.dbhost || !argv.dbuser || !argv.dbpass || !argv.dbname || !argv.dbtblname){ | |
console.log(process.argv[1] | |
+ ' --dbhost=[hostname] --dbuser=[username] --dbpass=[password] --dbname=[dbname] --dbtblname=[dbtblname]'); | |
console.log(argv.dbhost); | |
console.log(argv.dbuser); | |
console.log(argv.dbpass); | |
console.log(argv.dbname); | |
console.log(argv.dbtblname); | |
return 0; | |
} | |
} | |
var webdriver = require('selenium-webdriver'), | |
By = webdriver.By, | |
until = webdriver.until; | |
if(!argv.c){ | |
var driver = new webdriver.Builder().forBrowser('firefox').build(); | |
}else{ | |
var phantomjs = require('phantomjs'); | |
console.log(phantomjs.path); | |
// var driver = new webdriver.Builder().forBrowser('phantomjs',phantomjs.path).build(); | |
var driver = new webdriver.Builder() | |
.withCapabilities({"phantomjs.binary.path":phantomjs.path}) | |
.forBrowser('phantomjs') | |
.build(); | |
} | |
driver.get('https://www.kakeibo.tepco.co.jp/dk/aut/login/'); | |
driver.findElement(By.name('id')).sendKeys(argv.u); | |
driver.findElement(By.name('password')).sendKeys(argv.p); | |
driver.findElement(By.id('idLogin')).click(); | |
/* 使用量と料金をグラフで見る */ | |
driver.findElement(By.id('idNotEmptyImg_contents01.jpg')).click(); | |
/* 時間別グラフはこちら */ | |
driver.findElement(By.id('bt_time_view.jpg')).click(); | |
/* データと日付を得る */ | |
driver.getPageSource().then(function(pageSource){ | |
var result = {}; | |
getElectricityUsage(pageSource,result); | |
// console.log(JSON.stringify(result)); | |
if(argv.d){ | |
var mysqlid = { host : argv.dbhost, | |
user : argv.dbuser, | |
password : argv.dbpass, | |
database: argv.dbname}; | |
writeDB(mysqlid,argv.dbtblname,result); | |
} | |
}); | |
driver.quit(); | |
function getElectricityUsage(pageSource,result) { | |
var findstr = 'var items = [["日次",'; | |
var datePattern = /20\d\d\/\d\d\/\d\d/i; | |
var lines = pageSource.split('\n'); | |
lines.forEach(function (line) { | |
var findindex = line.indexOf(findstr); | |
if (findindex != -1) { | |
var ElectricityUsage = line.substr(findindex+findstr.length).replace(/]];/g,""); | |
process.stdout.write(ElectricityUsage+"\n"); | |
var ElectricityUsageArray = ElectricityUsage.split(","); | |
process.stdout.write("要素数:"+ElectricityUsageArray.length+"\n"); | |
var ElectricityUsageValueArray = new Array(); | |
ElectricityUsageArray.forEach(function (item) { | |
ElectricityUsageValueArray.push(parseFloat(item)); | |
}); | |
result['value'] = ElectricityUsageValueArray; | |
} | |
if (line.indexOf('の電気使用量') != -1) { | |
item = line.match(datePattern); | |
process.stdout.write(item[0] + '\n'); | |
result['date'] = item[0].replace(/\//g,"-"); | |
} | |
}); | |
} | |
function writeDB(mysqlid,tblname,result){ | |
var mysql = require('mysql'); | |
var colname = "`0000-0030`,`0030-0100`,`0100-0130`,`0130-0200`,`0200-0230`,`0230-0300`,`0300-0330`,`0330-0400`," | |
+"`0400-0430`,`0430-0500`,`0500-0530`,`0530-0600`,`0600-0630`,`0630-0700`,`0700-0730`,`0730-0800`," | |
+"`0800-0830`,`0830-0900`,`0900-0930`,`0930-1000`,`1000-1030`,`1030-1100`,`1100-1130`,`1130-1200`," | |
+"`1200-1230`,`1230-1300`,`1300-1330`,`1330-1400`,`1400-1430`,`1430-1500`,`1500-1530`,`1530-1600`," | |
+"`1600-1630`,`1630-1700`,`1700-1730`,`1730-1800`,`1800-1830`,`1830-1900`,`1900-1930`,`1930-2000`," | |
+"`2000-2030`,`2030-2100`,`2100-2130`,`2130-2200`,`2200-2230`,`2230-2300`,`2300-2330`,`2330-2400`"; | |
var valline = ""; | |
for(var i=0;i<48;i++){ | |
if(i != 0) valline+=","; | |
valline+=result['value'][i]; | |
} | |
console.log('insert into '+tblname+'(date,'+colname+') values("'+result['date']+'",'+valline+')'); | |
var connection = mysql.createConnection(mysqlid); | |
connection.connect(); | |
connection.query('insert into '+tblname+'(date,'+colname+') values("'+result['date']+'",'+valline+')', | |
function(error,results,fields){ | |
if (error) { | |
console.error('error connecting: ' + error.stack); | |
return; | |
} | |
}); | |
connection.end(); | |
} |
2016年7月3日日曜日
でんき家計簿のデータをMySQLに保存する
でんき家計簿
というサービスがある。
スマートメーターが設置されていれば、30分間隔の電力使用量が表示できる。
https://www.kakeibo.tepco.co.jp/dk/syo/electricUsage30MinGraph/
これをなんとかMySQLに保存したいと思った。
wgetでもごもごできるかなと思ったけど、認証があるしメンドクセー。
と思って数日経過し、ネットサーフィンしていたら、
すでに実現している人がいた。スゲー。
http://sirrow.info/archives/578
いろいろな技術を使っているのね。
スクレイピングするツール?
https://www.npmjs.com/package/selenium-webdriver
http://www.seleniumhq.org/docs/03_webdriver.jsp#selenium-webdriver-api-commands-and-operations
PhantomJS
http://tips.hecomi.com/entry/20121229/1356785834
http://phantomjs.org/download.html
ふーん。キャプチャできた!
まずは
selenium-webdriver + firefoxででんき家計簿にアクセスしてみる
ほぼ前述の方と同じだ。 Orz
こんな感じ。
得られたデータはこんな感じ。
ひさしぶりにすごいなと思った。
というサービスがある。
スマートメーターが設置されていれば、30分間隔の電力使用量が表示できる。
https://www.kakeibo.tepco.co.jp/dk/syo/electricUsage30MinGraph/
これをなんとかMySQLに保存したいと思った。
wgetでもごもごできるかなと思ったけど、認証があるしメンドクセー。
と思って数日経過し、ネットサーフィンしていたら、
すでに実現している人がいた。スゲー。
http://sirrow.info/archives/578
いろいろな技術を使っているのね。
- minimist・・・コマンド引数パーサー
- selenium-webdriver・・・Web自動テストツールらしい
- phantomjs・・・ブラウザ画面のないQtWebKit ベースのブラウザらしい
スクレイピングするツール?
https://www.npmjs.com/package/selenium-webdriver
http://www.seleniumhq.org/docs/03_webdriver.jsp#selenium-webdriver-api-commands-and-operations
PhantomJS
http://tips.hecomi.com/entry/20121229/1356785834
http://phantomjs.org/download.html
ふーん。キャプチャできた!
まずは
selenium-webdriver + firefoxででんき家計簿にアクセスしてみる
ほぼ前述の方と同じだ。 Orz
こんな感じ。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var argv = require("minimist")(process.argv.slice(2)); | |
if(!argv.u || !argv.p){ | |
console.log(process.argv[1] + ' -u [userid] -p [password]'); | |
return 0; | |
} | |
if(argv.d){ | |
if(!argv.dbhost || !argv.dbuser || !argv.dbpass || !argv.dbname || !argv.dbtblname){ | |
console.log(process.argv[1] | |
+ ' --dbhost=[hostname] --dbuser=[username] --dbpass=[password] --dbname=[dbname] --dbtblname=[dbtblname]'); | |
console.log(argv.dbhost); | |
console.log(argv.dbuser); | |
console.log(argv.dbpass); | |
console.log(argv.dbname); | |
console.log(argv.dbtblname); | |
return 0; | |
} | |
} | |
var webdriver = require('selenium-webdriver'), | |
By = webdriver.By, | |
until = webdriver.until; | |
var driver = new webdriver.Builder() | |
.forBrowser('firefox') | |
.build(); | |
driver.get('https://www.kakeibo.tepco.co.jp/dk/aut/login/'); | |
driver.findElement(By.name('id')).sendKeys(argv.u); | |
driver.findElement(By.name('password')).sendKeys(argv.p); | |
driver.findElement(By.id('idLogin')).click(); | |
/* 使用量と料金をグラフで見る */ | |
driver.findElement(By.id('idNotEmptyImg_contents01.jpg')).click(); | |
/* 時間別グラフはこちら */ | |
driver.findElement(By.id('bt_time_view.jpg')).click(); | |
/* データと日付を得る */ | |
driver.getPageSource().then(function(pageSource){ | |
var result = {}; | |
getElectricityUsage(pageSource,result); | |
// console.log(JSON.stringify(result)); | |
if(argv.d){ | |
var mysqlid = { host : argv.dbhost, | |
user : argv.dbuser, | |
password : argv.dbpass, | |
database: argv.dbname}; | |
writeDB(mysqlid,argv.dbtblname,result); | |
} | |
}); | |
driver.quit(); | |
function getElectricityUsage(pageSource,result) { | |
var findstr = 'var items = [["日次",'; | |
var datePattern = /20\d\d\/\d\d\/\d\d/i; | |
var lines = pageSource.split('\n'); | |
lines.forEach(function (line) { | |
var findindex = line.indexOf(findstr); | |
if (findindex != -1) { | |
var ElectricityUsage = line.substr(findindex+findstr.length).replace(/]];/g,""); | |
process.stdout.write(ElectricityUsage+"\n"); | |
var ElectricityUsageArray = ElectricityUsage.split(","); | |
process.stdout.write("要素数:"+ElectricityUsageArray.length+"\n"); | |
var ElectricityUsageValueArray = new Array(); | |
ElectricityUsageArray.forEach(function (item) { | |
ElectricityUsageValueArray.push(parseFloat(item)); | |
}); | |
result['value'] = ElectricityUsageValueArray; | |
} | |
if (line.indexOf('の電気使用量') != -1) { | |
item = line.match(datePattern); | |
process.stdout.write(item[0] + '\n'); | |
result['date'] = item[0].replace(/\//g,"-"); | |
} | |
}); | |
} | |
function writeDB(mysqlid,tblname,result){ | |
var mysql = require('mysql'); | |
var colname = "`0000-0030`,`0030-0100`,`0100-0130`,`0130-0200`,`0200-0230`,`0230-0300`,`0300-0330`,`0330-0400`," | |
+"`0400-0430`,`0430-0500`,`0500-0530`,`0530-0600`,`0600-0630`,`0630-0700`,`0700-0730`,`0730-0800`," | |
+"`0800-0830`,`0830-0900`,`0900-0930`,`0930-1000`,`1000-1030`,`1030-1100`,`1100-1130`,`1130-1200`," | |
+"`1200-1230`,`1230-1300`,`1300-1330`,`1330-1400`,`1400-1430`,`1430-1500`,`1500-1530`,`1530-1600`," | |
+"`1600-1630`,`1630-1700`,`1700-1730`,`1730-1800`,`1800-1830`,`1830-1900`,`1900-1930`,`1930-2000`," | |
+"`2000-2030`,`2030-2100`,`2100-2130`,`2130-2200`,`2200-2230`,`2230-2300`,`2300-2330`,`2330-2400`"; | |
var valline = ""; | |
for(var i=0;i<48;i++){ | |
if(i != 0) valline+=","; | |
valline+=result['value'][i]; | |
} | |
console.log('insert into '+tblname+'(date,'+colname+') values("'+result['date']+'",'+valline+')'); | |
var connection = mysql.createConnection(mysqlid); | |
connection.connect(); | |
connection.query('insert into '+tblname+'(date,'+colname+') values("'+result['date']+'",'+valline+')', | |
function(error,results,fields){ | |
if (error) { | |
console.error('error connecting: ' + error.stack); | |
return; | |
} | |
}); | |
connection.end(); | |
} |
ひさしぶりにすごいなと思った。
2016年6月25日土曜日
iij mioひかりが遅いのかと思ったら違った
インターネットが遅い!
夜、スマホを家のwifiに接続していると、ネット接続が遅すぎてイライラする。
普通にLTE接続したほうが早いくらい。
スピードテストを行ってもタイムアウトが発生することもしばしば。
なんでかなーと思って、家のネット速度を図ってみることにした。
使用したのは、speedtest-cilってやつ
https://github.com/sivel/speedtest-cli.git
これをcron様で1時間おきに実行してみた。
期間:2016/6/21 8:51~2016/6/25 13:15
結果
平均値
Ping :28.4ms
ダウンロード:56.9Mbps
アップロード:74.9Mbps
あれ?
あんまり遅くない!?
グラフにするとこんな感じ
生データもおいておきます。
夜、スマホを家のwifiに接続していると、ネット接続が遅すぎてイライラする。
普通にLTE接続したほうが早いくらい。
スピードテストを行ってもタイムアウトが発生することもしばしば。
なんでかなーと思って、家のネット速度を図ってみることにした。
使用したのは、speedtest-cilってやつ
https://github.com/sivel/speedtest-cli.git
これをcron様で1時間おきに実行してみた。
期間:2016/6/21 8:51~2016/6/25 13:15
結果
平均値
Ping :28.4ms
ダウンロード:56.9Mbps
アップロード:74.9Mbps
あれ?
あんまり遅くない!?
グラフにするとこんな感じ
生データもおいておきます。
date | Ping | Download | Upload |
2016/6/21 8:51 | 17.662 | 62.01 | 69.94 |
2016/6/21 8:52 | 13.458 | 74.54 | 102.25 |
2016/6/21 12:05 | 14.979 | 74.38 | 95.86 |
2016/6/21 12:23 | 13.296 | 66.93 | 73.06 |
2016/6/21 13:15 | 15.49 | 59.18 | 91.25 |
2016/6/21 14:15 | 119.306 | 41.96 | 98.37 |
2016/6/21 15:15 | 14.424 | 68.73 | 101.59 |
2016/6/21 16:15 | 57.403 | 28.06 | 73.57 |
2016/6/21 17:15 | 91.326 | 33.83 | 87.29 |
2016/6/21 18:15 | 18.206 | 35.91 | 63.8 |
2016/6/21 19:15 | 14.564 | 67.08 | 73.96 |
2016/6/21 20:15 | 16.082 | 64.41 | 83.83 |
2016/6/21 21:15 | 19.249 | 42.51 | 81.1 |
2016/6/21 22:15 | 32.393 | 55.25 | 49.22 |
2016/6/21 23:15 | 13.366 | 40.37 | 41.44 |
2016/6/22 0:15 | 14.862 | 60.54 | 69.99 |
2016/6/22 1:15 | 102.954 | 40.24 | 57.04 |
2016/6/22 2:15 | 14.314 | 68.08 | 85.78 |
2016/6/22 3:15 | 13.443 | 67.54 | 77.57 |
2016/6/22 4:15 | 13.521 | 67.16 | 81.69 |
2016/6/22 5:15 | 13.341 | 72.3 | 91.09 |
2016/6/22 6:15 | 14.252 | 69.19 | 24.39 |
2016/6/22 7:15 | 14.673 | 61.21 | 76.46 |
2016/6/22 8:15 | 18.76 | 37.04 | 91.31 |
2016/6/22 9:15 | 15.605 | 65.62 | 86.9 |
2016/6/22 10:15 | 14.654 | 59.9 | 77.27 |
2016/6/22 11:15 | 13.789 | 62.59 | 97.88 |
2016/6/22 12:15 | 17.035 | 44.92 | 98.17 |
2016/6/22 13:15 | 14.65 | 66.59 | 92.65 |
2016/6/22 14:15 | 57.149 | 30.3 | 68.24 |
2016/6/22 15:15 | 92.062 | 51.79 | 78.39 |
2016/6/22 16:15 | 14.691 | 56 | 53.31 |
2016/6/22 17:15 | 14.642 | 59.72 | 79.08 |
2016/6/22 18:15 | 89.277 | 30.02 | 68.7 |
2016/6/22 19:15 | 16.216 | 58.69 | 73.02 |
2016/6/22 20:15 | 48.201 | 38.4 | 38.21 |
2016/6/22 21:15 | 13.836 | 57.57 | 53.37 |
2016/6/22 22:15 | 48.478 | 47.26 | 34.01 |
2016/6/22 23:15 | 35.806 | 67.19 | 91.51 |
2016/6/23 0:15 | 72.176 | 24.71 | 45.62 |
2016/6/23 1:15 | 14.773 | 64.93 | 90.78 |
2016/6/23 2:15 | 41.096 | 43.38 | 43.99 |
2016/6/23 3:15 | 13.806 | 75.47 | 96.75 |
2016/6/23 4:15 | 14.745 | 65.45 | 93.72 |
2016/6/23 5:15 | 13.512 | 67.49 | 96.9 |
2016/6/23 6:15 | 14.597 | 70.07 | 98.11 |
2016/6/23 7:15 | 14.6 | 68.68 | 88.51 |
2016/6/23 8:15 | 13.641 | 75.12 | 90.88 |
2016/6/23 9:15 | 14.722 | 37.77 | 66.79 |
2016/6/23 10:15 | 13.974 | 72.87 | 99.66 |
2016/6/23 11:15 | 13.943 | 69.71 | 92.54 |
2016/6/23 13:15 | 14.196 | 72.69 | 100.79 |
2016/6/23 14:15 | 26.158 | 62.51 | 63.66 |
2016/6/23 15:15 | 14.817 | 49.36 | 34.87 |
2016/6/23 16:15 | 27.039 | 37.48 | 78.16 |
2016/6/23 17:15 | 16.061 | 47.53 | 81.91 |
2016/6/23 18:15 | 48.259 | 70.33 | 94.46 |
2016/6/23 19:15 | 21.64 | 33.72 | 52.55 |
2016/6/23 20:15 | 16.272 | 69.22 | 56.84 |
2016/6/23 21:15 | 41.007 | 37.62 | 44 |
2016/6/23 22:15 | 15.332 | 42.81 | 49.14 |
2016/6/23 23:15 | 22.458 | 57.33 | 38.63 |
2016/6/24 0:15 | 24.918 | 68.38 | 92.45 |
2016/6/24 1:15 | 14.115 | 53.59 | 22.11 |
2016/6/24 2:15 | 52.254 | 71.84 | 88.83 |
2016/6/24 3:15 | 15.287 | 59.09 | 84.3 |
2016/6/24 4:15 | 15.106 | 67.96 | 85.41 |
2016/6/24 5:15 | 15.563 | 73.71 | 93.67 |
2016/6/24 6:15 | 13.599 | 67.76 | 90.71 |
2016/6/24 7:15 | 14.032 | 60 | 87.25 |
2016/6/24 8:15 | 13.662 | 66.54 | 84.29 |
2016/6/24 9:15 | 14.192 | 60.12 | 95.02 |
2016/6/24 10:15 | 134.58 | 31.99 | 62.5 |
2016/6/24 11:15 | 13.768 | 60.08 | 59.94 |
2016/6/24 12:15 | 13.934 | 65 | 85.13 |
2016/6/24 13:15 | 13.959 | 65.34 | 83.09 |
2016/6/24 15:15 | 14.748 | 56.74 | 58.4 |
2016/6/24 16:15 | 16.261 | 42.16 | 96.2 |
2016/6/24 17:15 | 13.818 | 60.69 | 95.49 |
2016/6/24 18:15 | 13.922 | 61.76 | 75.35 |
2016/6/24 19:15 | 16.095 | 51.09 | 72.14 |
2016/6/24 20:15 | 14.162 | 66.01 | 66.65 |
2016/6/24 21:15 | 15.049 | 54.15 | 69.63 |
2016/6/24 22:15 | 14.417 | 56.3 | 53.04 |
2016/6/24 23:15 | 13.8 | 38.39 | 39.68 |
2016/6/25 0:15 | 74.175 | 13.08 | 20.96 |
2016/6/25 1:15 | 14.759 | 55.81 | 58.15 |
2016/6/25 2:15 | 14.84 | 62.29 | 53.59 |
2016/6/25 3:15 | 14.871 | 50.66 | 83.97 |
2016/6/25 4:15 | 13.858 | 67.08 | 86.4 |
2016/6/25 5:15 | 14.373 | 65.79 | 87.27 |
2016/6/25 6:15 | 181.924 | 59.77 | 84.69 |
2016/6/25 7:15 | 14.276 | 62.22 | 82 |
2016/6/25 8:15 | 13.959 | 65.01 | 87.42 |
2016/6/25 9:15 | 18.152 | 51.83 | 84.71 |
2016/6/25 10:15 | 13.731 | 54.33 | 73.85 |
2016/6/25 11:15 | 16.152 | 66.96 | 91.25 |
2016/6/25 12:15 | 180.747 | 63.24 | 58.08 |
2016/6/25 13:15 | 13.96 | 64.15 | 86.51 |
登録:
投稿 (Atom)