-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrc6.c
205 lines (180 loc) · 5.2 KB
/
rc6.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#include <misc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_tim.h>
#include "rc6.h"
//Fonksiyon içinde kullanılan değişkenler
volatile int bit_counter;
volatile int tt;
volatile int bit_switch;
//Kesme fonksiyonu
void TIM4_IRQHandler(void) {
int t = 0;
int j = 0;
int temp_bit = 0;
if (TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) != RESET)
TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
//Kararlı bir okuma için bit değişim anından kaçınarak
//bitin baslangıcından değil 1/3 den analiz edeceğiz,
//bunun için yaklasık 150 mikrosaniyelik
//zaman gecikmesi oluşturuyoruz.
for (j = 0; j < 833; j++) {
;
}
//B portunun 0. pini okunuyor.
//IR alıcının baglı oldugu pin
t = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0);
//RC6 IR verici sinyali farklı bileşenlerden oluşuyor. Bunlar sıra ile soyle:
//Baslık,adres,komut,veri
//Bit genisligi 444 mikrosaniye
//baslangıç 6 bit genişliğinde bir palsten oluşuyor aralarında boşluk bulunmuyor
//Sinyalin başını belirlemek için kullanılıyor.
//Daha sonra 2 boşluk ile bunu takip eden manchester kodlama ile
//kodlanmış bir bit ile başlık kısmı tamamlanıyor.
switch (receiver_stage) {
case START_POINT:
if (t) {
bit_counter++;
} else {
bit_counter = 0;
return;
}
//Baslık kısmı aranıyor aralıksız 6 tane 1
if (bit_counter > 5) {
receiver_stage = READ_FIRST_BIT;
bit_counter = 0;
led ^= 1;
}
break;
case READ_FIRST_BIT:
if (t == 0) {
//Senkronizasyonu sağlamak için ilk bosluk kullanılıyor
//j sayacı zaman aşımı oluşturmak için kullanılıyor.
j=0;
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0 && j < 10000) {
//Yeniden kesme çağrısı oluşumunu engellemek ve senkronizasyon sağlamak
//için timer sıfırlanıyor.
TIM4->CNT = 0;
j++;
}
//İşlem zaman aşımına uğramadan biter ise bir sonraki aşamaya geçiliyor.
if (j < 10000) {
receiver_stage = SNC_RECEIVE_DATA;
bit_counter=0;
} else {
//İşlem zaman aşımına uğradı program resetleniyor.
receiver_stage = START_POINT;
err++;
}
return;
}
break;
case SNC_RECEIVE_DATA:
//Başlik ile adres verisi arasinda 12 bitlik bosluk var bunu atliyoruz
if (bit_counter > 11) {
receiver_stage = READY_TO_READ;
command = 0;
address = 0;
remote_data = 0;
bit_switch = 0;
bit_counter=0;
tt=0;
return;
}
bit_counter++;
break;
case READY_TO_READ:
//Manchester decoder
//8bit adres 8bit komut okunuyor manchester kodlama olduğu icin
//1 bit iki aşamadan oluşuyor toplamda 16*2 32 bit.
//0 dan 1 e geçiş 0, 1 den 0 a geçiş 1 olarak değerlendiriliyor.
//1 den 1 e ya da 0 dan 0 a geçiş var ise hatalı giriş olduğu için
//hata sayacı bir arttırılıyor ve döngüden çıkılıyor.
if (bit_counter < 32) {
if (bit_switch) {
if (t == 0) {
if (tt == 1) {
temp_bit = 1;
} else {
//error
err++;
receiver_stage = START_POINT;
return;
}
} else if (t == 1) {
if (tt == 0) {
temp_bit = 0;
} else {
//error
err++;
receiver_stage = START_POINT;
return;
}
}
if (bit_counter < 16) {
address = (address << 1)| temp_bit;
} else{
command = (command << 1)| temp_bit;
}
bit_switch = 0;
}
else {
tt = t;
bit_switch = 1;
}
bit_counter++;
return;
}
//Standart RC6 protokole göre bu verinin command kısmında yer alması gerekir
//Asıl ihtiyacımız olan veri bu alanda bulunuyor 52-60 aralığı 8bit
if (bit_counter < 60) {
if (bit_counter >51) {
remote_data = remote_data << 1;
remote_data = remote_data | t;
}
bit_counter++;
} else {
receiver_stage = START_POINT;
err = 0;
}
break;
}
}
void rc6Init(void){
TIM_TimeBaseInitTypeDef TIM_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//IR alıcının bağlı olduğu B portunun 0. pinini giriş olarak yapılandırıyoruz.
//Eğer IR alıcı başka bir porta bağlı ise buradaki port numarasını
//ve kesme fonksiyonu içinde okuma yapılan portu değiştirin.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//Timer 444 mikrosaniyede bir kesme üretecek şekilde yapılandırılıyoruz.
//Ayrıca senkronizasyon sağlamak amacı ile kesme fonksiyonu içerisinde timer sıfırlanıyor.
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_InitStructure.TIM_Prescaler = 72;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_InitStructure.TIM_Period = 444;
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM4, &TIM_InitStructure);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
//Kesme fonksiyonu ayarlanıyor
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM4, ENABLE);
//Değişkenlere başlangıç değerleri veriliyor.
led = 1;
receiver_stage = START_POINT;
tt = 0;
bit_switch = 0;
err = 0;
command = 0;
address = 0;
remote_data = 0;
bit_counter = 0;
}