/***********************************************(abc889_18426.c)***
* NEC/SONY赤外線リモコンの送受信
******************************************************************/
#include "mcc_generated_files/mcc.h"
#include "string.h"
#include "i2cLCD_ST7032i.h"
#define MAXDATA 90 // 赤外線データ配列数
#define MAXADDR 10 // SONYアドレス配列数
/*
#define BFSIZE 20 // eusart.hで定義
*/
// ----- NEC pulse time parameter ----
#define MARK() __delay_us(562)
#define SPACE_1() __delay_us(1686)
#define SPACE_0() __delay_us(562)
#define LEADER_1() __delay_us(8992)
#define LEADER_0() __delay_us(4496)
#define GYAP_0() __delay_ms(43)
// ---- SONY puls time parameter -----
#define S_LEADER() __delay_us(2400)
#define S_SPACE() __delay_us(600)
#define S_MARK_0() __delay_us(600)
#define S_MARK_1() __delay_us(1200)
#define S_GYAP_20() __delay_ms(19)
#define S_GYAP_15() __delay_ms(25)
#define S_GYAP_12() __delay_ms(29)
// ----- DSM & STM controle ----
#define DSM_1() (MD1CON0bits.MD1BIT = 1)
#define DSM_0() (MD1CON0bits.MD1BIT = 0)
#define SMT_START() (SMT1CON1bits.SMT1GO = 1)
#define SMT_STOP() (SMT1CON1bits.SMT1GO = 0)
// ---- IOdata Customer Code ----
#define IO_CUSTOM 0xE880
/* ----- Variables ----- */
uint16_t PW[MAXDATA]; // Mark配列
int16_t PR[MAXDATA]; // Space配列
uint8_t p_PW; // Mark配列ポインタ
uint8_t p_PR; // Space配列ポインタ
char sBf[BFSIZE]; // 文字列作業エリア
char rBuf[BFSIZE]; // シリアル受信バッファ
uint8_t sFlg; // シリアル受信フラグ
uint8_t Sony; // Sonyフォーマット?
uint16_t Sa[MAXADDR]; // SONYアドレス配列
uint16_t IO2[] = {0x1084,0x2084,0x3084}; // IOdata赤外線コード例
/*----- Send NEC Code -----*/
void Ir_Leader(){
DSM_1(); // send Leader
LEADER_1();
DSM_0();
LEADER_0();
}
void Ir_Stop(){
DSM_1();
MARK(); // send stop
DSM_0();
}
void Ir_Send(uint8_t *dt, uint8_t x){ // send Byte
uint8_t sft;
for (int j = 0; j < x;j++){
sft = 0x01;
for(int i = 0; i < 8;i++){
DSM_1();
MARK();
DSM_0();
if(dt[j] & sft) SPACE_1();
else SPACE_0();
sft <<= 1;
}
}
}
void Ir_Send2(uint16_t wd){ // send Word
uint16_t wsft = 0x0001;
for(int i = 0; i < 16;i++){
DSM_1();
MARK();
DSM_0();
if(wd & wsft) SPACE_1();
else SPACE_0();
wsft <<= 1;
}
}
void send_NEC(uint16_t cst, uint16_t d){
uint16_t dat;
IO_RC2_SetLow();
SMT_STOP(); // 赤外線測定中断
dat = (d & 0x00FF) | ((~d << 8) & 0xFF00); // Calc data code
Ir_Leader(); // Leader Start
Ir_Send2(cst); // Send Custmer
Ir_Send2(dat); // Send Data
Ir_Stop(); // stop
LCD_clr();
sprintf(sBf,">NEC %04X-%04X",cst,dat);
LCD_str(sBf);
printf("\n\r>NEC %04X-%04X",cst,dat);
SMT_START(); // 測定再開
}
/*----- Send IOdata code ------*/
void send_IOdata(uint8_t c){ // from IOarray(word)
uint16_t w = IO2[c];
uint16_t wLo;
uint16_t wHi;
IO_RC2_SetLow();
SMT_STOP(); // 赤外線測定中断
wLo = (w & 0x00FF) | ((~w << 8) & 0xFF00); // Calc Low word
wHi = ((w >> 8) & 0x00FF) | (~w & 0xFF00); // Calc High word
Ir_Leader(); // Leader Start
Ir_Send2(IO_CUSTOM); // Send Custom
Ir_Send2(wLo); // Send Data1
Ir_Stop(); // stop
GYAP_0(); // Gyap time
Ir_Leader(); // Leader Start
Ir_Send2(IO_CUSTOM); // Send Custom
Ir_Send2(wHi); // Send Data2
Ir_Stop(); // stop
LCD_clr();
sprintf(sBf,">IOdata %08X",w);
LCD_str(sBf);
printf("\n\r>IOdata %08X",w);
SMT_START(); // 測定再開
}
/*----- Send SONY Code ----*/
void send_SONY(uint16_t wd, uint16_t ad){
uint8_t btc; // bit counter
uint32_t icd; // IRcode data
uint8_t adx; // address number
uint32_t sft; // shift data
LCD_clr();
sprintf(sBf,">Sony:%04X-%04X",wd,ad);
LCD_str(sBf);
printf("\r\n%s\n\r",sBf);
icd = (uint32_t)(wd & 0x007F);
if(wd & 0x0080){ // 15bit mode?
btc = 15;
icd += (uint32_t)((wd >> 1) & 0x7F80);
}else{
if(wd & 0x8000){ // 20bit mode?
btc = 20;
adx = (wd >> 8) & 0x003F;
if(adx >= MAXADDR){
btc = 0;
}else{
if(wd & 0x4000){ // write?
icd += (uint32_t)ad << 7;
Sa[adx] = ad;
}else{ // read
icd += (uint32_t)Sa[adx] << 7;
}
}
}else{ // 12bit mode
btc = 12;
icd += (uint32_t)((wd >> 1) & 0x0F80);
}
}
if(btc){ // 送信データが有効なら
IO_RC2_SetHigh();
SMT_STOP(); // 赤外線測定中断
sft = 0x00000001;
DSM_1(); // send Leader
S_LEADER();
for(int i = 0; i < btc; i++){
DSM_0(); // send Space
S_SPACE();
DSM_1(); // send Mark
if(icd & sft) S_MARK_1();
else S_MARK_0();
sft <<= 1;
}
DSM_0(); // send Stop
if(btc==20){
S_GYAP_20();
}else if(btc==15){
S_GYAP_15();
}else{
S_GYAP_12();
}
sprintf(sBf,"- IR %05X",icd);
LCD_cursor(0,1);
LCD_str(sBf);
printf("\r%s",sBf);
SMT_START(); // 測定再開
}
}
void prt_Hex(uint8_t w, uint8_t n){ // 16進数表示
if(n){
sprintf(sBf,"%02X ",w);
printf(" >> %02XH\n\r",w);
}else{
sprintf(sBf,"%02X",w);
printf(" >> %02XH",w);
}
LCD_str(sBf); // LCD表示
}
/*-------------------------------------------
* Main application
*-------------------------------------------*/
void main(void){
uint8_t ird; // 赤外線データ
uint8_t sbt; // ビットセット用バイト
uint8_t bct; // 有効ビットカウンタ
uint8_t sgf; // データ有効フラグ
uint16_t sDat; // SONY送信データ
uint16_t sAdr; // SONY送信アドレス
char *end; // 文字列切り出し処理用
SYSTEM_Initialize(); // デバイス初期化
LCD_init(); // LCD初期化
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
LCD_str("== ready ==");
// --- テスト用データセット
Sa[0] = 0x04B9; // SONYデフォルトアドレス
sDat = 0xC000;
sAdr = 0x1C5A;
while (1) // 赤外線信号受信繰返し
{
p_PW = 0; // データポインタ初期化
p_PR = 0;
SMT1PWAIF = 0; // フラグクリア
SMT1PRAIF = 0;
SMT1IF = 0;
SMT_START(); // 赤外線測定開始
printf("\r\n-ready\r\n"); // 準備完了メッセージ送信
// ====== 赤外線信号の受信・送出ループ =====
while((p_PR < MAXDATA)){ // バッファ満杯まで繰返
if(sFlg){ // 受信データがあれば?
if(strchr(rBuf,'X') || strchr(rBuf,'x')){
sDat = (uint16_t)strtol(rBuf, &end, 16);
sAdr = (uint16_t)strtol(end, NULL, 16);
send_SONY(sDat,sAdr); // SONYコード送信
send_SONY(sDat,sAdr); // SONYコード送信(2回目)
}else{ // IODATA(NEC)コード
uint8_t n = atoi(rBuf);
if((n > 0) & (n < 4)){ // 配列データ数内か?
send_IOdata(n-1); // IOdataコード送信
}
}
sFlg = 0; // シリアルフラグをクリア
printf("\n\r");
}
if(PORTCbits.RC4 == 0){ // テストボタンが押された?
// ---- 赤外線コード送信(テスト用、以下のどれかを有効に)
send_SONY(sDat,sAdr); // 前回データを送信
// send_IOdata(0); // 赤外線送信(IOdata)
// send_NEC(0x847C,0x10EF); // 赤外線送信(NEC)
// send_SONY(0x0200,0); // 赤外線送信(SONY12)
// send_SONY(0xB4D0,0); // 赤外線送信(SONY15)
// send_SONY(0xC000,0x1C5A); // 赤外線送信(SONY20)
// send_SONY(0x8000,0); // 赤外線送信(SONY20)
}
/* // ---- LCD画面シフト操作 (現在無効)
if(PORTAbits.RA0 == 0){ // ボタン0が押されていたら
LCD_sift(RIGHT); // LCD表示右シフト
__delay_ms(100); // チャタリング対策
}
if(PORTAbits.RA1 == 0){ // ボタン1が押されていたら
LCD_sift(LEFT); // LCD表示左シフト
__delay_ms(100); // チャタリング対策
}
*/
// ----- 赤外線信号受信 ----
if(SMT1PWAIF){ // mark終了なら
SMT1PWAIF = 0; // フラグクリア
PW[p_PW++]=SMT1CPW; // High時間を保存
}
if(SMT1PRAIF){ // space終了なら
SMT1PRAIF = 0; // フラグクリア
if(SMT1CPR < 10000){ // 10ms未満なら
PR[p_PR++] = SMT1CPR; // Low時間を保存
}else{ // 10ms以上なら
PR[p_PR++] = -(SMT1CPR / 1000); // msに変換し負数で保存
}
}
if(SMT1IF){ // 無信号が100ms続いたら
SMT1IF = 0; // フラグクリア
PR[p_PR++]=0; // 無信号記号「0」を保存
break;
}
}
SMT_STOP(); // 測定終了
// ===== 受信結果を解析・送信する =====
ird = 0;
sbt = 1;
bct = 0;
sgf = 0;
LCD_clr();
if(PW[0]<3000){
Sony = 7; // -> SONY Mode
IO_RC2_SetHigh();
sprintf(sBf,"$SONY, %d",p_PW);
LCD_str(sBf);
puts(sBf);
}else{
Sony = 0; // -> NEC Mode
IO_RC2_SetLow();
sprintf(sBf,"$NEC, %d",p_PW);
LCD_str(sBf);
puts(sBf);
}
printf(" - mark space (us)\r\n"); // タイトル送信
LCD_cursor(0,1);
for(char i = 0; i < p_PW; i++){ // 保存した時間を送信
printf("%2d %5d",i,(uint16_t)PW[i]); // mark時間
if(PR[i]==0) { // 無信号なら
printf(" ---"); // 「---」を送信
if(Sony){
if(PW[i] < 1600){ // markが1600us未満なら
bct++;
if(PW[i] > 900){ // markが900us超なら
ird |= sbt; // シフトバイトを加える
printf(" 1");
}else{
printf(" 0");
}
prt_Hex(ird, 0); // 16進数で表示
}
}
}else if(PR[i] > 0){ // 10ms未満なら
printf(" %5d",PR[i]); // us単位で送信(無改行)
if (Sony){ // *** SONY Code (Mark)
if(PW[i] < 1600){ // markが1500us未満なら
sgf = 1; // 有効データ
if(PW[i] > 900){ // markが900us超なら
ird |= sbt; // シフトバイトを加える
printf(" 1");
}else{
printf(" 0");
}
}
}else{ // *** NEC Code (Space)
if(PW[i] < 1500){ // markが1500未満なら
if(PR[i]<2000){ // spaceが2000未満なら
sgf = 1; // 有効データ
if(PR[i]>900){ // 更にspaceが900以上なら
ird |= sbt; // シフトバイトを加える
printf(" 1");
}else{
printf(" 0");
}
}
}
}
if(sgf){ // 有効データなら
sbt <<= 1; // シフトバイトを左シフト
bct++; // 有効データ数を1増やす
if(Sony){ // コードがSONYなら
if(bct == Sony){
prt_Hex(ird, 0); // 16進数で表示
ird = 0; // 赤外データをクリア
sbt = 1; // シフトバイトも初期化
Sony = bct + 8;
}
}else{ // コードがSONY以外
if((bct % 8) == 0){ // データ数が8の倍数?
prt_Hex(ird, 0); // 16進数で表示
ird = 0; // 赤外データをクリア
sbt = 1; // シフトバイトも初期化
}
}
sgf = 0;
}
}else{ // 10ms超なら
printf("%7d (ms)",-PR[i]); // ms単位で送信
if(Sony){
if(PW[i] < 1600){ // markが1500us未満なら
bct++;
if(PW[i] > 900){ // markが900us超なら
ird |= sbt; // シフトバイトを加える
printf(" 1");
}else{
printf(" 0");
}
prt_Hex(ird, 1); // 16進数で表示
ird = 0; // 赤外データをクリア
sbt = 1; // シフトバイトも初期化
Sony = bct + 7;
}
}
}
printf("\r\n");
}
if(p_PW >= MAXDATA){ // バッファ満杯なら
printf("-- Buffer Full --\r\n"); // Buffer Full 送信
}
}
}
/***** End of File *****/
|