/*
http://gadget.renesas.com/ja/product/cotton_sp9.html
リモコンのボタンに応じてLEDを光らせる。
このサンプルは、以下のリモコンのA, B, Cボタンを押したときにLEDを光らせます。
このリモコンはNECフォーマットに準拠しています。サンプルではNECフォーマットに合わせた信号の分析をしてLEDを光らせる他、シリアルモニターに信号の内容を表示しています。
リモコンのボタンに応じて車を制御する。
(リモコン受信部は上記をほとんど借用した)
*************************************************************************
Pin3,4:5,6に出力{モーター2個(M1,M2)、ドライブIC=TA7291P/S}で制御及びLED点滅
<< I/Oマップ >>GR-COTTO
< Pin4(出力)/NC(接続なし)
< Pin2(入力)/リモコンデータ
< Pin3(出力)/IN2(モータードライブIC1)
< Pin4(出力)/IN1(モータードライブIC1)
< Pin5(出力)/IN2(モータードライブIC2)
< Pin6(出力)/IN1(モータードライブIC2)
< Pin22(出力)/LED(red)
< Pin23(出力)/LED(green)
< Pin24(出力)/LED(blue)

TA7291
ピン番号は型番文字の書いてある側と向き合って、
左から 1、2、3・・・・ となります。
ピン TA7291P/S 接続
P S
VCC 7 2 ドライバICの電源
VS 8 6 モーター用電源
VREF 4 8 モーターの電源コントロール用
GND 1 5
IN1 5 9 マイコンにつなぐ信号1
IN2 6 1 マイコンにつなぐ信号2
OUT1 2 7 モーターにつなぐ
OUT2 10 3 モーターにつなぐ
ピン番号は型番文字の書いてある側と向き合って、
左から 1、2、3・・・・ となります。
*************************************************************************
ファンクション
入 力 出力 モード
IN1 IN2 OUT1 OUT2
0 0 ∞ ∞ ストップ
1 0 H L CW / CCW
0 1 L H CCW / CW
1 1 L L ブレーキ

∞: ハイインピーダンス
注: 入力は“H”アクティブ
*/
#include

#define IR_PIN 2
#define IR_INTERRUPT 0

uint8_t g_ir_data = 0;
bool g_ir_available = false;

void ir_receive_interrupt();
void ir_receive_start();
uint8_t ir_getData();
uint8_t ir_data=0,last_code = 0;
uint8_t dur = 100;
bool ir_available();
byte pin_sig[2][2] = { //CW/CCW signal IN1,IN2
{3,4}, //motor0:pin3,4
{5,6}, //motor1:pin5,6
};

void setup() {
setPowerManagementMode(PM_STOP_MODE);
//Serial.begin(9600);
pinMode(IR_PIN, INPUT_PULLUP);
ir_receive_start();

pinMode(22, OUTPUT);
pinMode(23, OUTPUT);
pinMode(24, OUTPUT);
digitalWrite(22, HIGH);
digitalWrite(23, HIGH);
digitalWrite(24, HIGH);

pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
digitalWrite(3, HIGH);//brake
//digitalWrite(3, LOW);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
//digitalWrite(5, LOW);
digitalWrite(6, HIGH);
}

void loop() {
ir_receive_start();
delay(0xFFFFFFFF); // hold STOP mode until receiving IR signal.

if(ir_available()){
//Serial.println(ir_getData(), HEX);
//Serial.flush();
ir_data=ir_getData();
switch (ir_data) {
case 0xD8: // POWER BUTTON
last_code = ir_data;
digitalWrite(22, LOW);
motor_brake(0,200);
motor_brake(1,200);
digitalWrite(22, HIGH);//前進
motor_cw(0,0);//右車正転
motor_cw(1,0);//左車正転
//digitalWrite(22, LOW);//前進
//digitalWrite(3, LOW);//右車ブレーキ
//digitalWrite(4, LOW);
//digitalWrite(5, LOW);//左車ブレーキ
//digitalWrite(6, LOW);
//delay(10);
//digitalWrite(22, HIGH);
//digitalWrite(3, LOW);//右車正転
//digitalWrite(4, HIGH);
//digitalWrite(5, LOW);//左車正転
//digitalWrite(6, HIGH);
delay(400);
break;
case 0xF8: // A BUTTON
last_code = ir_data;
digitalWrite(23, LOW);//led green off
motor_brake(0,10);
motor_brake(1,10);
digitalWrite(23, HIGH);//led green on //左折
motor_cw(0,1);//左車逆転
motor_cw(1,0);//右車正転
delay(400);
break;
case 0x78: // B BUTTON
last_code = ir_data;
digitalWrite(24, LOW);//led blue off
motor_brake(0,200);
motor_brake(1,200);
digitalWrite(24, HIGH);//led blue on//後退
motor_cw(0,1);//左車逆転
motor_cw(1,1);//右車逆転
delay(400);
break;
case 0x58: // C BUTTON
last_code = ir_data;
motor_brake(0,10);
motor_brake(1,10);
digitalWrite(24, LOW);//led blue off
digitalWrite(24, HIGH);//led blue on
motor_cw(0,0);//左車正転
motor_cw(1,1);//右車逆転
delay(400);
break;
case 0x20: // 空白 BUTTON
last_code = ir_data;
digitalWrite(22, LOW);//led red off
digitalWrite(24, LOW);//led blue off
digitalWrite(22, HIGH);//led led on//左右車ストップ
digitalWrite(24, HIGH);//led blue on
motor_stop(0,200);//左車ストップ
motor_stop(1,200);//右車ストップ
//delay(200);
break;
default:
break;
}
}
else{
ir_data = last_code;
g_ir_available = false;
}
}
//void motor(byte num, byte pw){
//pw = map(pw, 0, 100, 0, 255);
//analogWrite(pin_pwm[num], pw);
//}

void motor_cw(byte num, boolean cw){
digitalWrite(pin_sig[num][0],LOW);
digitalWrite(pin_sig[num][1],LOW);
delay(10);
if(cw == true){//逆転
digitalWrite(22, LOW);//led red off
digitalWrite(pin_sig[num][0],HIGH);
digitalWrite(pin_sig[num][1],LOW);
digitalWrite(22, HIGH);//led red on
}
else{//正転
//digitalWrite(22, LOW);
digitalWrite(23, LOW);//led green off
digitalWrite(pin_sig[num][0],LOW);
digitalWrite(pin_sig[num][1],HIGH);
//digitalWrite(22, HIGH);//右折
digitalWrite(23, HIGH);//led green on
}
}

void motor_stop(byte num,int uint8_t){
digitalWrite(pin_sig[num][0],LOW);
digitalWrite(pin_sig[num][1],LOW);
if(dur >0){
delay(dur);
}
}

void motor_brake(byte num,uint8_t dur){
digitalWrite(pin_sig[num][0],LOW);
digitalWrite(pin_sig[num][1],LOW);
delay(10);
digitalWrite(pin_sig[num][0],HIGH);
digitalWrite(pin_sig[num][1],HIGH);
if(dur >0){
delay(dur);
}
}
/************ IR utility function ***************/
void ir_receive_interrupt(){

unsigned long last_time;

detachInterrupt(IR_INTERRUPT);
last_time = micros();

// confirm if reader code is correct
uint8_t err = 0;
while(!digitalRead(IR_PIN)){ // until change from low to high
if((micros() - last_time) > 10000){ // interval low should be 9ms or less
err = true;
break;
}
}
while(digitalRead(IR_PIN)){ // until change from high to low
if((micros() - last_time) > 15000){ // interval of reader code should be 13.5ms or less
err = true;
break;
}
}
if(((micros() - last_time) < 13000) || (err == true)){ // Unknown code
attachInterrupt(0, ir_receive_interrupt, FALLING);
g_ir_available = false;
return; // not available remote controller
}

// get data
uint8_t receive_count = 0;
uint8_t temp_ir_data[4] = {0};
g_ir_data = 0;
last_time = micros();
while((32 > receive_count) && ((micros() - last_time) < 80000)){
// interval of a frame data should be 76.5ms or less
last_time = micros();
while(!digitalRead(IR_PIN) && ((micros() - last_time) < 1000)){
// interval of low state is about 0.56ms.
}
while(digitalRead(IR_PIN) && ((micros() - last_time) < 2500)){
// interval of a bit is between 1.125ms and 2.25ms
}
if((micros() - last_time) > 1500){
bitSet(temp_ir_data[receive_count / 8], receive_count % 8);
}
receive_count++;
}

if(temp_ir_data[2] == (uint8_t)~temp_ir_data[3]){
g_ir_data = temp_ir_data[2]; // set actual data
g_ir_available = true;
}

}

void ir_receive_start(){
attachInterrupt(IR_INTERRUPT, ir_receive_interrupt, FALLING);
}

uint8_t ir_getData(){
g_ir_available = false;
return g_ir_data;
}

bool ir_available(){
return g_ir_available;
}