2015年4月25日土曜日

FON2405EのGPIOでキャラクタ液晶を制御する(受信機能追加)

目的

前回、チェックサムと送達確認(PICマイコンからFONに対して応答)を行うようにした。
 今回は、送達確認を拡張して受信機能(PICマイコンからFONに対してコマンドを出せる)ようにした。

概要

チェックサムOKの場合に、FONに対してACKを送信する。
 シリアル通信のクロックはFON側で生成しているので、
 イメージとしてはSPI通信に近いと思う。

結果

前回同様に1秒毎に顔文字「Adeno(^o^)mm-ss」※mm-ssは分-秒を送信し続けると、
 400回のコマンド送信に対して、送信NGは15回
  80回のときは、2回 2〜3%くらい?
 結果は地味だけど、PIC→FON方向の通信ができるようになったのは大きい


何をやったか

・フォーマット
1.データを送信するとき
  種類   方向
  クロック FON→PIC 385us
  送信データ      [STX][チェックサム][DATA][ETX]
  受信データPIC→FON  1byte前に対する受信結果

2.送信結果を確認するとき
  種類   方向
  クロック FON→PIC 385us
  送信データ      [ENQ]
  受信データPIC→FON  1byte前に対する受信結果

黄色・・・クロック
水色・・・受信データ(PIC→FON)この場合はACK(0x06)

------------------------------------------------
gpio_write_sr Start:CLK=12 DATA_OUT=11 DATA_IN=14
Send:[STX][CHKSUM = 14][DATA][ETX]<-4ms->[ENQ]
Input      = 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
RcvChk     = OK
Total Time = 307ms
------------------------------------------------

・FON側
int gpio_io_byte(int port_clk,int port_in,int port_out,unsigned char *cin,unsigned char cout){
int shift_clk = port_clk-8;
int shift_out = port_out-8;
unsigned char mask = 1 << 7;
int idx=1,fd,req_w,req_r,i,j,value,tmp;
int in_val=0;
*cin = 0;
fd = open(GPIO_DEV, O_RDONLY);
if (fd < 0) {
perror(GPIO_DEV);
return -1;
}
if (0L <= port_in && port_in < RALINK_GPIO_DATA_LEN
&& shift_clk >= 0 && shift_out >= 0){
req_w = RALINK_GPIO_WRITE_BYTE | (idx << RALINK_GPIO_DATA_LEN);
req_r = RALINK_GPIO_READ_BIT | (port_in << RALINK_GPIO_DATA_LEN);
} else {
close(fd);
printf("gpio_io_byte: out of range\n");
}
for(i=0;i<8;i++){
value = 0;
tmp = 0;
if((cout & mask)>0){ value = 1;}
//clk reset(L) 1 with data set
for(j=0;j<385;j++){ //1.4us x 275 = 385us
tmp = (1<<shift_clk);
tmp |= (value<<shift_out);
tmp &= 0xff;
if (ioctl(fd, req_w, tmp) < 0) { perror("ioctl"); close(fd); return -1; }
}
//clk set(H) 0 with data set
for(j=0;j<385;j++){
tmp = (value<<shift_out);
tmp &= 0xff;
if (ioctl(fd, req_w, tmp) < 0) { perror("ioctl"); close(fd); return -1; }
}
//data read
if(ioctl(fd,req_r,&in_val,0) < 0){ perror("ioctl"); close(fd); return -1; }
if(in_val == 0)
*cin = (*cin << 1);
else
*cin = (*cin << 1)+1;
//next mask
mask = mask >>1;
}
//clk set(H) 0 with data set aftertime
for(j=0;j<4000;j++){
tmp = (value<<shift_out);
tmp &= 0xff;
if (ioctl(fd, req_w, tmp) < 0) { perror("ioctl"); close(fd); return -1; }
}
close(fd);
return 0;
}
view raw gpio_io_byte.c hosted with ❤ by GitHub
・PIC側
受信処理の後、に送信したいものを出力するだけ
↓受信処理
sr_buf = ((sr_buf<<1) & 0xFE) | (0x01 & DATA_PORT);
↓送信処理
 //DATA 出力
 if((sr_out & sr_out_mask) == 0){
   DATA_OUT_PORT = 0;
}else{
         DATA_OUT_PORT = 1;
 }
 sr_out_mask = sr_out_mask >> 1;

・エラー発生回数測定用スクリプト
#!/bin/sh
myvar=1
errvar=0
sndvar=0
retval=0
while [ $myvar -ne $1 ]
do
echo ==================================================== SeqNo.$myvar
./mygpio5a.exe s 12 11 14 1000 "C2"
if [ $? -eq 2 ]; then
errvar=`expr $errvar + 1`
fi
sndvar=`expr $sndvar + 1`
usleep 100000
./mygpio5a.exe s 12 11 14 1000 "NAdeno(-_-)"`date +%M-%S`
if [ $? -eq 2 ]; then
errvar=`expr $errvar + 1`
fi
sndvar=`expr $sndvar + 1`
usleep 400000
./mygpio5a.exe s 12 11 14 1000 "C2"
if [ $? -eq 2 ]; then
errvar=`expr $errvar + 1`
fi
sndvar=`expr $sndvar + 1`
usleep 100000
./mygpio5a.exe s 12 11 14 1000 "NAdeno(^o^)"`date +%M-%S`
if [ $? -eq 2 ]; then
errvar=`expr $errvar + 1`
fi
sndvar=`expr $sndvar + 1`
usleep 400000
myvar=`expr $myvar + 1`
done
echo TotalSend=$sndvar
echo ErrSend=$errvar
view raw lcdloop2.sh hosted with ❤ by GitHub
今日はここまで、次回は、PICからなにかデータを送信させてみるか

2015年4月19日日曜日

FON2405EのGPIOでキャラクタ液晶を制御する(チェックサム追加)

目的

前回、なんとかFON2045E(RT3050)のGPIOを使って、キャラクタ液晶の制御を行ったが、受信が失敗してしまう場合があった。
そこで、チェックサムと到達確認(PICマイコンからFONに対して応答)を行うようにした。

結果

チェックサムの導入によって、受信失敗したものは、破棄できるようになった。
1秒毎に顔文字「Adeno(^o^)mm-ss」※mm-ssは分-秒
を送信し続けると、おおよそ1分に2回程度チャックサムエラーが発生している模様。

何をやったか

1.チェックサムの導入

   送信するデータを以下のように変更
   [STX][チェックサム][DATA][ETX]

   STX     : 02h
   チェックサム:DATA部の合計値を0〜15(下位4ビット分)
   DATA   :今まで送っていたデータ
   ETX    :03h
#include <stdio.h>
#include "rcv_lib.h"
#include "lcd_lib.h"
volatile unsigned char rcv_state = 0;
volatile unsigned char rcv_poi = 0;
volatile unsigned char rcv_cmd = ' ';
volatile unsigned char rcv_buf[RCV_SIZE];
volatile unsigned char rcv_timeoutflg = 0;
volatile unsigned char rcv_timeout = 0;
volatile unsigned char rcv_full = 0;
volatile unsigned char rcv_chksum = 0;
volatile unsigned char rcv_chksum_base = 0;
volatile unsigned char rcv_drv_state = 0;
void rcv_init(){
//受信バッファの準備
for(rcv_poi = 0; rcv_poi < RCV_SIZE; rcv_poi++){
rcv_buf[rcv_poi] = ' ';
}
//drv
rcv_drv_state = RCV_DRV_STATE_S0_STXWAIT;
rcv_chksum = 0;
rcv_chksum_base = 0;
//app
rcv_full = 0;
rcv_state = RCV_STATE_S1_CMDWAIT;
rcv_cmd = ' ';
}
char read_byte(int i){ return rcv_buf[i]; }
void clearRCVflg(){ rcv_full = 0; }
char getRCVflg(){ return rcv_full; }
unsigned char getRCVcmd(){ return rcv_cmd; }
void rcv_byte(unsigned char c){
if(rcv_full == 1){
printf("BufFull>%c\r\n",c);
}else if(rcv_drv_state == RCV_DRV_STATE_S0_STXWAIT){
if(c == rSTX){
rcv_cmd = ' ';
rcv_state = RCV_STATE_S1_CMDWAIT;
rcv_drv_state = RCV_DRV_STATE_S1_CHKSUMWAIT;
}
}else if(rcv_drv_state == RCV_DRV_STATE_S1_CHKSUMWAIT){
rcv_chksum = 0;
rcv_chksum_base = c & 0x0f;
rcv_drv_state = RCV_DRV_STATE_S2_ETXWAIT;
}else if(rcv_drv_state == RCV_DRV_STATE_S2_ETXWAIT){
if(c == rETX){
rcv_chksum = rcv_chksum & 0xf;
if(rcv_chksum_base == rcv_chksum){
rcv_buf[rcv_poi] = '\n';
printf("ChkSumOK:%d\r\n",rcv_chksum);
rcv_full = 1;
}else{
rcv_state = RCV_STATE_S1_CMDWAIT;
printf("ChkSumNG:%d:%d\r\n",rcv_chksum_base,rcv_chksum);
rcv_full = 2;
}
rcv_drv_state = RCV_DRV_STATE_S0_STXWAIT;
}else{
rcv_chksum+= c;
if(rcv_state == RCV_STATE_S1_CMDWAIT){
if(c == 'C'){
rcv_state = RCV_STATE_S2_CMDWAIT2;
}else if(c == 'N'){
rcv_poi = 0;
rcv_state = RCV_STATE_S3_DATAWAIT;
}
}else if(rcv_state == RCV_STATE_S2_CMDWAIT2){
//コマンドを一時保存
rcv_cmd = c;
rcv_state = RCV_STATE_S1_CMDWAIT;
}else if(rcv_state == RCV_STATE_S3_DATAWAIT){
if(c == '\r'){
}else{
rcv_buf[rcv_poi] = c;
rcv_poi++;
//終了条件2:バッファがいっぱい
if(rcv_poi >= RCV_SIZE){
rcv_poi = 0;
rcv_state = RCV_STATE_S1_CMDWAIT;
printf("End2\r\n");
}
}
}
}
}
}
view raw rcv_lib.c hosted with ❤ by GitHub
 
2.受信の追加
   
   送信後に、readしているだけ
void gpio_test_write_sr(int gpio_clk, int gpio_out,int gpio_in,int delaytime, unsigned char *c){
long gpiomask = 0x00FF1FFF; //0x00FFFFFF;
printf("set_dir=%ld\n",gpiomask);
gpio_set_dir(gpiomask);
int i,d,chksum;
printf("gpio_write_sr Start:CLK=%d DATA_OUT=%d DATA_IN=%d\n",gpio_clk,gpio_out,gpio_in);
struct timeval s,f;
gettimeofday(&s,NULL);
chksum = 0;
unsigned char RSTX = 0x02;
unsigned char RETX = 0x03;
gpio_write_byte3(gpio_clk,gpio_out,RSTX);
for(i=0;i<17;i++){
if(*(c+i) == '\0'){ /*chksum += '\n';*/ break;
}else{ chksum += *(c+i); }
}
unsigned char RCHKSUM = (unsigned char)(chksum & 0xf);
gpio_write_byte3(gpio_clk,gpio_out,RCHKSUM);
for(i=0;i<17;i++){
if(*(c+i) == '\0'){
/*gpio_write_byte3(gpio_clk,gpio_out,'\n');*/
break;
}else{
gpio_write_byte3(gpio_clk,gpio_out,*(c+i));
}
}
gpio_write_byte3(gpio_clk,gpio_out,RETX);
printf("ChkSum=%d\n",RCHKSUM);
gpio_set_dir(RALINK_GPIO_DIR_ALLIN);
gpio_read_bit(gpio_in, &d);
printf("Input--------------------->%d\n", d);
gettimeofday(&f,NULL);
printf("Total Time=%dms\n",(f.tv_sec-s.tv_sec)*1000+(f.tv_usec-s.tv_usec)/1000);
}
view raw mygpio5a.c hosted with ❤ by GitHub


PICからの戻りは画面に表示しているだけだけど、
今後は、再送とか実装していきたい。

2015年4月13日月曜日

WAPM-HP-AM54G54を入手

はじまり

近所のリサイクルショップで見慣れない形状の無線LANAPを発見。
業務用らしい。アンテナがなくて、500円。
別に無線を出したいわけでは無いので、これでもOKです。

どんなものか

 外観はこんな感じ。ぼろぼろ(笑)

 http://buffalo.jp/products/catalog/item/w/wapm-hp-am54g54/


赤丸のところにUARTがあるようだ。
miniPCI×2とか富豪だね。他のカードに変えたら面白いかな。
PoE対応なので、それで遊ぶのも面白いかも。

今後の目標

もちろんOpenWrt化

2015年4月5日日曜日

FON2405EのGPIOでキャラクタ液晶を制御する(高速化)

目的

先週、FON2045E(RT3050)のGPIOを使って、キャラクタ液晶の制御を行ったが、
1行(16文字)表示するのに、1.6秒かかってしまっていた。
今回これの高速化を目指す。

受信側(PIC)の高速化によって改善できないかを実験。

結果


 1.6秒→0.5秒にまで短縮することができた。

何をやったか


FON側・・・クロック生成をusleep(4ms)からビジータイマー1460μsに変更
PIC側・・・1ms周期の割り込みによるデータサンプリングを480usに変更
      デバック出力としてのUART出力をエラー時のみに変更

● クロック生成の変更
GPIOの制御に1.4μs要するので、これを1000回繰り返しただけ。
それで1460μs消費させる。

for(i=0;i<8;i++){
//==========================================
//for pic
value = 0;
tmp = 0;
if((c & mask)>0){ value = 1;}
//clk reset(L) 1 with data set
for(j=0;j<1000;j++){ //1.4us x 1000 = 1460us
tmp = (1<<shift_clk);
tmp |= (value<<shift_data);
tmp &= 0xff;
if (ioctl(fd, req, tmp) < 0) { perror("ioctl"); close(fd); return -1; }
}
//clk set(H) 0 with data set
for(j=0;j<1000;j++){
tmp = (value<<shift_data);
tmp &= 0xff;
if (ioctl(fd, req, tmp) < 0) { perror("ioctl"); close(fd); return -1; }
}
mask = mask >>1;
}
view raw mygpio5a.c hosted with ❤ by GitHub
●割り込み間隔の変更
480μs もう少し攻めても大丈夫な気がするけど、余裕をみて。
PICは4MHzで動作しているので、1サイクルあたり1μs。
割り込み間隔100μsくらいでも 行けそうな気がする。