Created
January 2, 2020 07:23
-
-
Save ak1211/fb030dd374d876bc667397fb8a26c09c to your computer and use it in GitHub Desktop.
irrec プログラム(C言語とpigpioライブラリ)
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
/* | |
irremocon <https://github.com/ak1211/irremocon> | |
Copyright 2019 Akihiro Yamamoto | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
*/ | |
// | |
// use pigpio libraries. without pigpiod | |
// install libraries | |
// sudo apt-get install pigpio | |
// | |
// build | |
// | |
// $ gcc -Wall -pthread -o irrec1 irrec1.c -lpigpio -lrt | |
#include <assert.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <sys/timerfd.h> | |
#include <unistd.h> | |
#include <pigpio.h> | |
// 赤外線受信モジュール電源ピン(GPIO 24 / Physical 18) | |
const uint8_t GPIO_IRM_POWER_PIN = 24; | |
// 赤外線受信モジュール入力ピン(GPIO 25 / Physical 22) | |
const uint8_t GPIO_IRM_INPUT_PIN = 25; | |
// 赤外線受信モジュールは負論理信号 | |
const int ASSERT_IR = 0; | |
const int NEGATE_IR = 1; | |
// キャリア周波数[kHz} | |
// 38kHz | |
const uint16_t CARRIER_FREQ_KHZ = 38; | |
// キャリア周期[us] | |
// 1/38,000 * 1,000,000 = 26us | |
const uint16_t CARRIER_PERIOD_MICROS = 1000 / CARRIER_FREQ_KHZ; | |
// | |
// ラズパイゼロではキャリア周期に同期できず | |
// タイミング違反が起きるので分周する | |
// | |
// プリスケーラの倍率 | |
// 2分周 | |
const uint16_t N_OF_PRESCALER = 2; | |
// 分周後でのクロックカウンタ増加量 | |
const uint16_t COUNT_PACE = N_OF_PRESCALER; | |
// タイマー周期[us] | |
// キャリア周期 * プリスケーラの倍率 | |
const uint16_t TIMER_INTERVAL_MICROS = CARRIER_PERIOD_MICROS * N_OF_PRESCALER; | |
// この時間信号が変化しないと, 赤外線リモコン信号を読み取るのを終了する | |
// 34ms | |
const uint16_t TIMEOUT_COUNTS = 34 * 1000 / TIMER_INTERVAL_MICROS; | |
// | |
// | |
// | |
ssize_t receive_ir_codes( uint16_t* buffer, size_t buffer_size ) | |
{ | |
assert( TIMEOUT_COUNTS <= buffer_size ); | |
ssize_t ret_val = -1; | |
int tfd = timerfd_create( CLOCK_REALTIME, 0 ); | |
struct itimerspec interval = { | |
.it_interval = { .tv_sec = 0, .tv_nsec = TIMER_INTERVAL_MICROS * 1000 }, | |
.it_value = { .tv_sec = 0, .tv_nsec = 1000 } | |
}; | |
timerfd_settime( tfd, 0, &interval, NULL ); | |
// リモコン信号入力待ち | |
while (gpioRead(GPIO_IRM_INPUT_PIN) == NEGATE_IR) { | |
// タイマー待ち | |
uint64_t v; | |
if (read( tfd, &v, sizeof(uint64_t) ) < 0) { | |
goto exit; | |
} | |
} | |
// リモコン信号を検出したのでカウント開始 | |
bool previous = false; | |
size_t buffer_counter = 0; | |
uint16_t count = 0; | |
while (count < TIMEOUT_COUNTS) { | |
if (previous == gpioRead(GPIO_IRM_INPUT_PIN)) { | |
// 信号が変化しないならカウンタを増やす | |
count += COUNT_PACE; | |
} else { | |
// 信号が変化したら | |
// カウント値をバッファに入れて | |
// カウンタを初期化 | |
buffer[buffer_counter++] = count; | |
previous = !previous; | |
count = 0; | |
} | |
// タイマー待ち | |
uint64_t v; | |
if (read( tfd, &v, sizeof(uint64_t) ) < 0) { | |
goto exit; | |
} | |
} | |
// 最後のカウント値をバッファに入れる | |
buffer[buffer_counter++] = count; | |
ret_val = buffer_counter; | |
exit: | |
close(tfd); | |
return ret_val; | |
} | |
// | |
// | |
// | |
int main() | |
{ | |
if (gpioInitialise() < 0) { | |
perror(""); | |
return 0; | |
} | |
if (gpioSetMode(GPIO_IRM_POWER_PIN, PI_OUTPUT) != 0) { | |
perror(""); | |
goto exit; | |
} | |
// 赤外線受信モジュールに電源を供給する。 | |
if (gpioWrite(GPIO_IRM_POWER_PIN, 1) != 0) { | |
perror(""); | |
goto exit; | |
} | |
fprintf( stderr, "irrec\n" ); | |
fprintf( stderr, "This program is display infrared codes.\n" ); | |
enum { IRCODES_SIZE = 1024 }; | |
uint16_t ircodes[IRCODES_SIZE] = {0}; | |
ssize_t count; | |
if ((count = receive_ir_codes(ircodes, IRCODES_SIZE)) < 0) { | |
perror(""); | |
goto exit; | |
} | |
// | |
for( ssize_t c=0 ; c<count ; c++ ) { | |
int lo =ircodes[c] & 0x00ff; | |
int hi =ircodes[c] >> 8 & 0x00ff; | |
printf( "%02X%02X", lo, hi ); | |
} | |
printf( "\n" ); | |
// 赤外線受信モジュールの電源を切る | |
if (gpioWrite(GPIO_IRM_POWER_PIN, 0) != 0) { | |
perror(""); | |
goto exit; | |
} | |
fprintf( stderr, "bye.\n"); | |
exit: | |
gpioTerminate(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hello!