Skip to content

Commit 5733082

Browse files
committed
MCP3008 ADC 지원 추가 & 소스 정리
Signed-off-by: Ju, Gyeong-min <jcmh74@gmail.com>
1 parent 5e848dc commit 5733082

25 files changed

Lines changed: 6696 additions & 576 deletions

README.md

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ sudo apt install -y --force-yes raspberrypi-kernel-headers
102102
#### wget 사용시
103103

104104
```shell
105-
wget https://github.com/amos42/am_joyin/releases/download/v0.1.0-beta01/am_joyin-0.1.0.deb
106-
sudo dpkg -i am_joyin-0.1.0.deb
105+
wget https://github.com/amos42/am_joyin/releases/download/v0.2.0-beta01/am_joyin-0.2.0.deb
106+
sudo dpkg -i am_joyin-0.2.0.deb
107107
```
108108

109109
#### git 사용시
@@ -118,8 +118,8 @@ git clone https://github.com/amos42/am_joyin.git
118118

119119
```shell
120120
cd am_joyin
121-
./utils/makepackage.sh 0.1.0
122-
sudo dpkg -i build/am_joyin-0.1.0.deb
121+
./utils/makepackage.sh 0.2.0
122+
sudo dpkg -i build/am_joyin-0.2.0.deb
123123
```
124124
125125
이 과정까지 거치면 드라이버 설치가 1차적으로 완료된다.
@@ -333,6 +333,8 @@ endpoints="default,default,default;ext_joystick,1,11;ext_joystick_2,,6"
333333

334334
이 설정은 다음과 같은 의미를 갖는다.
335335

336+
![endpoint 파라미터 해석](images/param_ep_sep.png)
337+
336338
> * 첫번째 엔드포인트
337339
> + 이름 : default (최종적으로 "AmosJoystick_1" 이름이 부여된다.)
338340
> + 사용 버튼셋 인덱스 : 0
@@ -432,7 +434,7 @@ sudo modprobe am_joyin device1="gpio;;0,custom,0,{4,0x1,-100},{17,0x1,100},{27,0
432434

433435
![74HC165](images/74hc165.jpg)
434436

435-
![74HC165](images/74hc165_pinouts.png)
437+
![74HC165 Pinouts](images/74hc165_pinouts.png)
436438

437439
74HC165는 8-bit 레지스터이기 때문에, 실제로 사용할 땐 복수개를 사용해야 하는 경우가 많다.
438440
갯수를 특정하기 힘들어서인지, 이를 모듈화 해 놓은 상품은 그다지 흔히 판매되지 않은 듯 하다.
@@ -582,6 +584,70 @@ sudo modprobe am_joyin endpoints="default;default" \
582584
```
583585

584586

587+
### MCP3008 ADC 입력
588+
589+
아날로그 조이스틱 입력을 위해선 ADC 칩이 필요하다.
590+
591+
MCP3008은 8 channel의 10-bit ADC 칩이다.
592+
593+
섬세한 입력이 필요 없다면 조이스틱의 감도 수준은 10-bit의 해상도로도 충분하며, 8 channel을 지원하기에 1p에 2축 스틱 1개씩을 사용한다면 MCP3008 칩 1개로 총 4p까지 지원이 가능하다.
594+
595+
MCP3008은 모듈 형태로 판매되는 경우가 별로 없어서 칩 패키지를 그대로 이용하게 된다.
596+
597+
![MCP3008](images/mcp3008.jpg)
598+
599+
MCP3008의 Pinout은 다음과 같다.
600+
601+
![MCP3008 Pinouts](images/mcp3008_pinouts.png)
602+
603+
VDD와 VREF은 라즈베리파이의 3.3v에 연결하면 된다.
604+
CS 핀은 사용하고자 하는 SPI 채널에 맞춰 라즈베리파이의 SPI_CE0 혹은 SPI_CE1 중 하나에 연결하면 된다.
605+
606+
* 디바이스 파라미터
607+
> 1. spi_channel - SPI 채널. 기본값 0
608+
> 2. value_weight_percent - LPF 가중치. 단위 %, 기본값 100
609+
> 3. sampling_count - LPF 샘플링 횟수. 기본값 10
610+
611+
* 엔드포인트 파라미터
612+
> 1. config type - 버튼 설정 타입
613+
> - default : pin_count, button_start_index
614+
> - custom : code_mode (0: keycode, 1:index), {button1, value1}, {button2, value2}, ...
615+
616+
실제 사용 예
617+
618+
ADC의 경우엔 단독으로 사용되기보다는 보통은 다른 버튼 입력 장치에 추가적으로 아날로그 스틱을 더해서 설정하는 것이 일반적이다.
619+
620+
다음은 기존의 74HC165 입력에 추가적으로 MCP3008으로 아날로그 스틱을 더해 준 설정이다.
621+
622+
1p 설정의 예 (기본 방향키를 아날로그로 변경)
623+
624+
```shell
625+
sudo modprobe am_joyin device1="74hc165;16,20,21,16,1;0,default,13,4" \
626+
device2="mcp3008;;0,custom,keycode,{0,0x03,-100,100},{1,0x04,-100,100}"
627+
```
628+
629+
1p 설정의 예 (아날로그 축 Rx,Ry 추가)
630+
631+
```shell
632+
sudo modprobe am_joyin buttonset1="default,0,12;{0x03,-100,100},{0x04,-100,100}" \
633+
endpoints="default,buttonset1" \
634+
device1="74hc165;16,20,21,16,1;0,default" \
635+
device2="mcp3008;;0,custom,keycode,{0,0x03,-100,100},{1,0x04,-100,100}"
636+
```
637+
638+
2p 설정의 예 (아날로그 축 Rx,Ry 추가)
639+
640+
```shell
641+
sudo modprobe am_joyin buttonset1="default,0,11;{0x03,-100,100},{0x04,-100,100}" \
642+
endpoints="default,buttonset1;default,buttonset1" \
643+
device1="74hc165;16,20,21,32,1;0,default;1,default" \
644+
device2="mcp3008;;0,custom,,{0,0x03,-100,100},{1,0x04,-100,100};1,custom,,{0,0x03,-100,100},{1,0x04,-100,100}"
645+
```
646+
647+
jstest로 테스트 해 보면 새로운 2개 축이 추가되었고, 조이스틱의 기울어짐에 따라 입력 값이 순차적으로 변하는 것을 확인할 수 있다.
648+
649+
![jstest for ADC](images/jstest_adc.png)
650+
585651
---
586652

587653
> ***NOTE:***

am_joyin.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ MODULE_LICENSE("GPL");
5656
#include "device_74hc165.c"
5757
#include "device_mcp23017.c"
5858
#include "device_mux.c"
59+
#include "device_adc_mcp3008.c"
5960

6061

6162
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0)
@@ -362,6 +363,7 @@ static int am_joyin_init(void)
362363
register_input_device_for_74hc165(&a_input->device_type_desc_list[a_input->input_device_type_desc_count++]);
363364
register_input_device_for_mcp23017(&a_input->device_type_desc_list[a_input->input_device_type_desc_count++]);
364365
register_input_device_for_mux(&a_input->device_type_desc_list[a_input->input_device_type_desc_count++]);
366+
register_input_device_for_mcp3008(&a_input->device_type_desc_list[a_input->input_device_type_desc_count++]);
365367

366368
// 커맨드 라인 파라미터들을 분석한다.
367369
parsing_device_config_params(a_input);

am_joyin_cfg.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,15 @@ void /*__init*/ prepocess_params(void)
8989
static input_buttonset_data_t* __find_buttonset(am_joyin_data_t* a_input, char* buttonset_name, int exclude_count)
9090
{
9191
int i;
92+
int target_buttonset_count, buttonset_idx;
9293
char* endptr;
9394

94-
int target_buttonset_count = a_input->input_buttonset_count - exclude_count;
95-
int buttonset_idx = simple_strtol(buttonset_name, &endptr, 10);
95+
if (buttonset_name == NULL || strcmp(buttonset_name, "default") == 0 || strcmp(buttonset_name, "") == 0) {
96+
return &a_input->buttonset_list[0];
97+
}
98+
99+
target_buttonset_count = a_input->input_buttonset_count - exclude_count;
100+
buttonset_idx = simple_strtol(buttonset_name, &endptr, 10);
96101

97102
if (endptr != buttonset_name && buttonset_idx < target_buttonset_count) {
98103
return &a_input->buttonset_list[buttonset_idx];
@@ -112,6 +117,8 @@ static int __append_button(input_buttonset_data_t* target_buttonset, int key_cod
112117
int i;
113118
int idx = -1;
114119

120+
if (key_code < 0) return -1;
121+
115122
for (i = 0; i < target_buttonset->button_count; i++) {
116123
if (key_code == target_buttonset->button_data[i].button_code) {
117124
idx = i;
@@ -187,20 +194,16 @@ void parsing_device_config_params(am_joyin_data_t* a_input)
187194
char *section = strsep(&pText, ";");
188195
if(section[0] == '{') {
189196
while (section != NULL) {
190-
char *block_p, *keycode_p, *minvalue_p, *maxvalue_p;
197+
char *block_p;
191198
int key_code, min_value, max_value;
192199

193200
strsep(&section, "{");
194201
block_p = strsep(&section, "}");
195-
keycode_p = strsep(&block_p, ",");
196-
minvalue_p = strsep(&block_p, ",");
197-
maxvalue_p = strsep(&block_p, ",");
202+
key_code = parse_number(&block_p, ",", 0, -1);
203+
min_value = parse_number(&block_p, ",", 10, 0);
204+
max_value = parse_number(&block_p, ",", 10, 0);
198205
strsep(&section, ",");
199206

200-
key_code = simple_strtol(keycode_p, NULL, 0);
201-
min_value = simple_strtol(minvalue_p, NULL, 0);
202-
max_value = simple_strtol(maxvalue_p, NULL, 0);
203-
204207
// 키 설정 추가
205208
if (__append_button(target_buttonset, key_code, min_value, max_value) < 0) {
206209
break;

0 commit comments

Comments
 (0)