Digital Angel Master

Spread the wing for new starting.

Archive for March, 2008

Bulk In

Posted by Digital Angel Master on March 31, 2008

출처 : http://muosys.egloos.com/112198

 

UniHigh 모듈을 가지고 bulk든 isochronous든 IN transfer를 연습해 보려면 무언가 데이터를 모듈로 전송해 줄 수 있는 게 필요하다.

UniHigh 모듈 두 개를 붙혀서 하나는 OUT transfer를 통해 받은 데이터를 I/O 포트를 통해 다른 모듈로 전해주면 다른 하나는 I/O포트를 통해 받은 데이터를 IN transfer를 통해 호스트로 전송하면 빵빵한 대역폭을 다 시험해 볼 수 있겠지만 그렇게 하다간 행자들 호주머니가 거덜나게 생겼는지라…

그래서 생각한 게 페러렐 포트를 통해 데이터를 전송하고, UniHigh모듈이 이 데이터를 I/O포트를 통해 받아 IN transaction을 실행하는 것이다.

나중에 GPIF를 사용한 transfer를 연습할 때도 지금 만들 것을 사용하면 될 것 같다.

그래서 본좌, 집에서 굴러다니던 멀쩡한 프린터 케이블 한쪽 대가리를 썩둑 썰어버렸다.
(본체에 끼우는 반대쪽 대가리를 자르시라. 반대를 자르면 대략 낭패.)

clip_image001

clip_image002

핀 번호를 헛갈리지 않기 위해 일일이 테스터로 찍어가며 라벨링을 한 다음 번호순으로 핀 헤더에 납땜했다.
18핀이 되더라.
핀 번호는 여기를 참고하시라.

Parallel 포트의 신호레벨이 5V이므로 3.3V를 쓰는 FX2랑은 안 맞지만, 버퍼 같은 거 구하기도 귀찮고 해서 어떻게 대충 저항만 가지고 때워보려고 이리저리 고민중이다.

위의 케이블과 함께 4.7KΩ 저항 10개 정도와 330Ω저항 4개정도도 미리 구해 놓으시라.

본좌 패러렐 포트 가지고 뭐 해 본적이 없어서, 학습 하려면 시간 좀 걸릴 것 같다.
빠르면 오늘 밤 안에 되겠고, 늦으면 이번 주말을 다 까먹으리라.

고로 (SPP,) ECP, EPP 모드 중 하나를 MS에서 제공하는 표준 드라이버를 통해 구현한 적이 있는 행자가 소스를 던져주면 낼롬 받아 먹겠다.
(즉, 어플리케이션 단에서 WriteFile로 데이터 전송한 예.)

당근 펌웨어 단에서 그 모드에 대응하기 위해 취해 줘야 하는 동작에 대한 소스나 설명도 있으면 감사하다.

*이미 다른 마이컴 모듈을 가지고 있어서 UniHigh 모듈로 데이터를 주는데 별 문제가 없는 행자들은 기냥 패쓰.

오늘 실험할 Bulk IN 트렌스퍼는 절차가 약간 복잡하다.
페러렐 포트를 통해 UniHigh 보드로 데이터를 전송해야 하기 때문에 그렇다.
아래의 절차를 빼먹지 말고 잘 따라가시라.

1. 페러렐 포트를 제어하기 위한 드라이버 설치

먼저 port95nt.exe를 다운받아 설치한 후, 컴퓨터를 재시작 한다.
http://electoy.cafe24.com/blog/?no=121&category=13의 아랫쪽 “Win98/2000에서 병렬포트 쉽게 사용하기” 에 다운받을 수 있는 다른 곳과 자세한 사용법이 나와 있다.
이 프로그램을 깔면 페러렐포트의 레지스터를 직접 제어할 수 있도록 해주는 드라이버가 깔린다.
이 드라이버는 DLPORTIO.lib라는 라이브러리를 통해 사용할 수 있는데, 본좌는 이 라이브러리를 이용해 Parallel.exe라는 어플리케이션을 만들었다.

2. Parallel.exe 어플리케이션 설치 및 데이터 전송 준비

Parallel이라는 어플리케이션은 본좌가 디자인한 프로토콜에 따라 페러렐포트를 통해 데이터를 전송하는 일을 한다.
전송할 데이터는 저번 강좌와 동일한 data.bin파일이다.
Parallel.exe를 실행시켜, “file” 버튼을 눌러 전송 할 데이터 파일(data.bin)을 선택한다.
그럼 “File Length”에 숫자가 나타날 것이다.
이 숫자를 잘 봐두자.

3. 회로 세팅

UniHigh보드를 아래 회로에 맞게 세팅한다.
(점선 부분은 그냥 데이터가 오가는 과정을 우리 눈으로 확인하려고 설치한 부분이므로 생략해도 상관 없다.)

clip_image003

* 우측 상단의 핀 설명은 Parallel Pin 1 (STROBE), 10 (ACK), 17 (SELECT)임.

4. 펌웨어 다운로드 및 데이터를 받을 준비

UniHigh1.6을 다운받아 C:CypressUSBExamplesFX2에 복사해 넣는다.
EZ-USB Control Panel을 실행시켜, 보드로 UniHigh1.6을 다운로드한다.

Get Pipe 버튼을 누른다.
“Pipe0 : Endpoint 6 IN” 파이프가 잡힐 것이다.
Length에 앞서 Parallel.exe의 “File Length” 에디트 박스에 나타난 숫자를 적어준다.
그리고, “Bulk/Int” 버튼을 누른다.
이제 EZ-USB Control Panel은 Endpoint 6 IN 파이프에서 데이터가 들어오기를 기다리는 상태가 되었다.

clip_image005

5. 페러렐 포트를 통해 데이터 전송

데이터를 보내는 것은 Parallel.exe의 “Transfer” 버튼을 누르면 된다.

clip_image006

6. 결과 확인

그럼 Paraller포트를 통해 데이터가 전송되고, 이에 따라 LED가 깜빡 거리면서
이 데이터가 다시 USB를 통해 호스트로 전송될 것이다.
전송된 결과는 EZ-USB Control Panel에 나타난다.

clip_image008

웹캠으로 찍었더니만 누락되는 프레임이 생겨서, LED의 깜빡임이 약간 부자연 스럽게 보인다.
원래는 “Bulk Endpoint로 데이터 날리기“에서 처럼 자연스럽게 깜빡인다.

여기까지의 절차를 주의 깊게 따라해라.
하나만 삐끗해도 뭔가 잘 안될 것이다.

본좌가 Q&A 게시판에 관련 파일들을 모두 올려 놓을 테니, 다운로드가 잘 안되는 행자들은 거기서 다운 받으시라.

Parallel.exe 소스 코드

펌웨어 소스코드에 대한 설명은 내일로 미룬다.

펌웨어 소스코드를 보려면 본좌가 만든 울트라 허접 프로토콜도 알아야 하기 땜시 부지런한 행자들을 위해 프로토콜을 설명하는 그림과 간락한 설명을 미리 포스팅한다.

clip_image009

데이터 전송절차 (번호는 윗 그림의 번호와 동일)
1. 호스트는 Select를 Low로 세팅하여, 데이터 전송이 시작될 것임을 디바이스에게 알린다.
디바이스는 Select가 Low가 되면 데이터를 받을 준비를 한다.
디바이스에게 준비할 시간을 주기 위해 100mS를 delay한 후 2.로 넘어간다.
2. 호스트는 Ack가 Low인지 체크한다.
3. Ack이 Low이면 디바이스가 데이터를 받아들일 준비가 되 있는 것이므로, 버스에 Data를 싣는다.
4. 호스트는 Strobe를 Low로 세팅한다.
5. Strobe가 Low가 되면 디바이스는 호스트가 데이터를 실었다는 것을 알아채고, Ack를 High로 세팅한다.
6. 디바이스는 버스의 데이터를 FIFO로 넣은 후, Ack를 Low로 세팅한다.
7. 호스트는 3번 이후, Ack가 High가 될 때까지 기다린 다음 Ack가 High가 되면 Strobe를 High로 세팅 한 후, 전송할 데이터가 남았다면 2번부터 반복한다.
8. 데이터를 모두 전송했으면 호스트는 Select를 High로 세팅한다.

디바이스 입장에서 본 데이터 전송절차
1. Select를 Low가 되면 데이터를 전송할 준비를 한다.
(우리의 예제에서는 아무일도 하지 않는다.)
2. Strobe가 Low가 되면 데이터가 도착한 것이므로
3. Ack를 High로 세팅한다.
4. Data를 FIFO에 넣는다.(미리 설정된 길이대로 패킷을 날린다.)
5. Ack를 Low로 세팅한다.
6. Select를 High가 되면, FIFO의 나머지 데이터를 날린다.

이제까지 부산시럽게 뚝딱 거렸지만서두.
결국 우리가 하고자 한 것은 Bulk모드에서 디바이스에서 호스트로 데이터를 보내려고 한 것이다.

UniHigh1.6은 UniHigh1.0에서 이번 예제에 필요하지 않은 코드를 지워서 뼈대만 남겨놓고 나서 Bulk IN transfer를 위한 코드를 추가한 것이다.
(그래봤자 Bulkloop.c의 DR_VendorCmnd()함수만 비운 것이다.)

자 본좌가 젤 먼저 추가한 부분이 뭘까?
빙고.
데이터를 전송할 통로를 확보하기 위해 Endpoint Descriptor를 추가했다.

;; Endpoint Descriptor      db   DSCR_ENDPNT_LEN	;; Descriptor length      db   DSCR_ENDPNT	;; Descriptor type      db   86H		;; Endpoint number, and direction      db   ET_BULK		;; Endpoint type      db   40H		;; Maximun packet size (LSB)      db   00H		;; Max packect size (MSB)      db   00H		;; Polling interval

나머지 항목은 따로 설명 안 해도 아실테고, 세 번째 바이트(Endpoint number, and direction)가 0×86이다.
파이프의 데이터 전송 방향을 나타내는 최상위 비트가 1이고 EP6을 사용할 것이므로 0×86이 된 것이다.
엔드포인트 티스크립터에 대한 설명은 여길 참조하시라.

이번에도 역시 High Speed와 Full Speed Descriptor를 동일하게 해 주었다.
Interface Descriptor의 Number of end points 필드도 1로 세팅해 주어야 한다는 걸 잊지 마시라.

두 번째로 한 일이 TD_Init()에 초기화 코드를 추가한 것이다.

EP6CFG = 0xE2;
0xE2는 EP6CFG 레지스터의 디폴트 값이므로 쓰나 안쓰나 마찬가지지만 심심해서 그냥 한번 써 봤다.
Bulkloop예제에서도 EP6를 IN Endpoint로 쓰고 있는데, Bulk IN transfer를 위해 꼭 EP6를 써야 할 이유는 없다.
레지스터 값만 적절히 세팅해 주면 EP2/4/6/8 어느 Endpoint든 사용 가능하다.
만약, 크고(1024) 깊은(quad buffering) 버퍼가 필요하다면 FX2의 하드웨어 구조상 EP2나 EP6가 유리하다.
세팅 가능한 버퍼의 형태는 T.R.M. 1-23을 참조하시라.

OEA = 0xA0; : 10100000
Port A의
7번 핀은 OUT : ACK 신호와 같이 LED를 키고 끄기 위한 용도로 사용
6번 핀은 IN : STROBE신호를 받기 위한 핀
5번 핀은 OUT : 호스트(컴퓨터)로 ACK 신호를 보내기 위한 핀
4번 핀은 IN : SELECT 신호를 받기 위한 핀

IOB = 0×00;
이걸 먼저 적고 나중에 OEB = 0xFF;를 써 주었는데,
순서를 바꿔 써야 맞는 것 같다.
행자들은 바꿔주시라.
I/O핀의 디폴트 세팅이 input으로 되어 있는데,
이 디폴트 세팅 상태에서 IOB레지스터에 데이터를 써 봤자 아무 의미 없는 짓거리다.
본좌도 왜 이렇게 했는지 모르겠다. -.-; 본좌가 잠시 광마로 변했었나 보다.

LED = OFF;
ACK = LOW;
Port A의 7번 5번핀의 상태를 LOW로 세팅한다.

AUTOPTRH2 = MSB( &EP6FIFOBUF );
AUTOPTRL2 = LSB( &EP6FIFOBUF );
이미 설명한바 있는 autopointer를 사용하기 위해 두번째 autopointer 값을 초기화 해주고 있다.
우리는 받은 데이터를 EP6를 통해 호스트로 전송할 것이므로, EP6의 버퍼주소 시작번지로 초기화 해주고 있다.

이제까지는 기냥 준비과정이었고 지금 설명할 TD_Poll()에서 실질적인 동작을 하고 있다.

( 본좌의 울트라 허접 프로토콜에 따르면 )
컴퓨터에서 페러렐 포트를 통해 데이터가 연달아 전송할 때 어느 시점에서 데이터를 끊어 읽어야 하는지를 디바이스에게 알리기 위해 호스트는 STROBE 신호를 High->Low로 세팅한다.
그러면 디바이스가 STROBE 신호를 감지했음을 호스트에 알리고, 디바이스가 이 데이터를 다 처리하기 전에 호스트가 다음 데이터를 보내지 않도록 ACK를 High로 세팅한다.
우리가 데이터를 받아 할 일은 이것을 FIFO에 넣는 것뿐이다.
데이터를 EP6의 FIFO에 넣고 나면 다음 데이터를 받을 준비가 된 것이므로, ACK를 다시 Low로 세팅한다.

여기까지가 아래 코드에 대한 설명이다.

if( STROVE == LOW ) <-앗 오타닷! {	ACK = HIGH;	LED = ON;

	IOB = IOD;	EXTAUTODAT2 = IOD;	wCount++;	EZUSB_Delay(20);

	ACK = LOW;	LED = OFF;

	EZUSB_Delay(20);}

Delay는 Port B에 달아놓은 LED가 너무 빨리 깜빡거리는 것을 방지하기 위해 삽입한 것이다. 빠른 데이터 전송을 위해서는 불필요하다.

IOB=IOD는 전송된 데이터에 따라 Port B의 LED를 키기 위한 것이고,

EXTAUTODAT2 = IOD;가 EP6 FIFO로 받은 데이터를 넣는 코드이다.

앞서 AUTOPTRH2를 EP6 버퍼의 시작번지로 세팅해 놓았으므로, EXTAUTODAT2에 데이터를 쓸 때마다 자동으로 autopointer가 증가하여 EP6 버퍼의 다음 번지를 가리키게 된다.
따라서 우리는 이것저것 신경 쓸 필요 없이 그냥 EXTAUTODAT2 = IOD;만 해주면 된다.

wCount를 증가시켜 주는 것은 우리가 엔드포인트 디스크립터에서 설정한 Packet Size가 64 Byte이므로 이 패킷 사이즈만큼 버퍼가 차면 패킷을 날리기 위해서이다.

if( PACKET_SIZE == wCount ){	// wait until IN buffer empty	while(EP2468STAT & bmEP6FULL);

	// Initilize Autopointer	AUTOPTRH2 = MSB( &EP6FIFOBUF );	AUTOPTRL2 = LSB( &EP6FIFOBUF );

	// Commit Packet	EP6BCH = MSB(wCount);  	SYNCDELAY;  	EP6BCL = LSB(wCount);        // arm EP6IN

	wCount=0;}

버퍼에 64바이트가 차면 Autopointer를 초기화 하고 패킷을 날리는 루틴이다.

While문은 USB의 대역폭이 감당하지 못할 만큼 데이터가 너무 빨리 들어오는 경우, 버퍼가 꽉 차 버리면 다음 데이터를 받지 않기 위해 삽입한 문장이다.

마지막으로 패러렐 포트의 SELECT신호가 High가 되면 디바이스는 호스트가 전송할 데이터를 다 전송했구나 하는 것을 알게 된다.
들어온 데이터가 우리가 정한 패킷사이즈(64byte)에 딱 나눠 떨어지는 크기라면 별 문제가 없겠지만 그렇지 않을 경우에는 버퍼에 전송되지 못하고 남은 데이터가 남아있게 된다.
이럴 때, SELECT신호를 감지해서 버퍼에 남은 자투리 데이터를 전송하기 위한 코드가 아래의 코드이다.

if( LOW == SELECT ){	…}else{	if( wCount )	{		// Commit Remnant Data		EP6BCH = MSB(wCount);  		SYNCDELAY;  		EP6BCL = LSB(wCount);        // arm EP6IN

		wCount=0;	}}

Bulk IN을 수행하기 위한 핵심 코드는
EXTAUTODAT2 = IOD; -> 데이터를 버퍼에 넣고

EP6BCH = MSB(wCount);
SYNCDELAY;
EP6BCL = LSB(wCount); -> 패킷을 날린다.

뭣도 없는 것을 졸라 길게 설명하자니 본좌 힘들었다. -.-;;;

SYNCDELAY는 앞서 어딘가에서 설명했으므로 기억 안 나는 행자들은 잘 찾아 보시라.

Posted in USB Lecture | Leave a Comment »

Bulk Endpoint로 데이터 날리기

Posted by Digital Angel Master on March 31, 2008

출처 : http://muosys.egloos.com/109906

 

오늘은 BULK OUT 트렌스퍼를 연습해 보자.

UniHigh1.5.zip

IN/OUT의 주체가 호스트란 것은 이미 설명 했으니, 이번 연습이 호스트가 데이터를 디바이스로 보내는 것이라는 것은 설명 안 해도 다들 잘 알고 계시리라.
라고 하면서 설명해 버렸다. -.-;

무엇부터 해야 될까?

빙고.
엔드포인트 디스크립터부터 추가해 주어야 하겠다.
그래서 본좌가 추가해 주었다.
Full/High Speed 똑같이 말이다.
이전 강의에서 Full Speed에서 Bulk Transfer의 Max Packet Size는 8, 16, 32, 64 byte중에 하나여야 하고, High Speedd에서는 최대 512byte여야 한다고 언급한 적이 있다.
근데 본좌가 High Speed Endpoint Descriptor의 Max Packet Size도 64로 세팅해버린 데는 남다른 사연이 있다.
바로 본좌의 귀차니즘 때문이다. -.-;
디바이스가 High Speed로 동작할 때와 Full Speed로 동작할 때를 따로 코딩해야 한다고 생각하니 너무 너무 귀찮은 생각이 들어서, 기냥 High Speed건 Full Speed건 상관없이 본좌가 코드 짜기 편하게끔 두 디스크립터를 똑같이 해버렸다.

행자들은 부디 본좌보다 부지런하길 바라며, Fx2.h에 선언된 EZUSB_HIGHSPEED() 매크로를 이용하면 내 장치가 구닥다리 컴퓨터에 붙여져서 Full Speed로 동작하는지, 아니면 최신형 신삥에 붙어서 High Speed로 동작하는 지 알 수 있다.

EZUSB_HIGHSPEED()를 사용하는 예는 Bulkloop.c의 ISR_Highspeed() 함수를 참조하시라.

추후에는 본좌가 암말 않터라도 위의 매크로를 이용해 Full/High Speed로 동작할 때, 달리 코딩해 주어야 하는 부분은 if 문으로 구분해서 코딩해 주시라.

사설이 길어졌는데….
어쨌든 Bulk Endpoint Descriptor를 추가 했으니 Desc.a51에 가서 휙~ 둘러보고 오시라.
디스크립터에 관한 설명은 이전에도 했고 해서 따로 안한다.

TD_Init()에 PortB를 output으로 설정하는 초기화 코드를 추가 했고,

SYNCDELAY;EP2BCL = 0x80;                // arm EP2OUT by writing byte count w/skip.SYNCDELAY;EP2BCL = 0x80;

도 추가했다.

EP2CFG = 0xA2;
요 초기화 코드는 위 코드의 앞에서 생략된 것으로 보심 되는데, 디폴트 값이기 때문이다.
T.R.M. 가서 휘딱 디비고 오시라.

EP2BCL에 아무 값이나 써 넣는 것은 OUT Endpoint Buffer를 쓰기 전에 꼭 우리가 해주어야 할 짓거리다.
http://muosys.egloos.com/81469를 참조하시라.

TD_Poll()의 마지막에 추가한 if문은 이전에 Bulkloop를 분석할 때 본 거를 쬐끔 변형한 것이므로 생각이 안 나면 http://muosys.egloos.com/75316를 다시 함 보시든지, 병원 가서 치매 치료를 받아보시라.

소스 설명은 끝이고…
아래의 회로를 꾸미시라.
Host에서 날라오는 데이터 대로 LED가 점등되도록 함 해보자.

clip_image001

어떻게 테스트를 하냐 하면 펌웨어를 다운로드 한 후에, Get Pipe 하고, Pipe 1을 선택한 후에, File Transfer버튼을 눌러 본좌가 제공한 파일을 지정해 주면 LED가 파일의 데이터 대로 깜빡거린다.
data.bin

clip_image002

이전에는 Hex … 리스트박스에 우리가 직접 데이터를 적어 넣어 주었지만, 길이가 긴 데이터는 매번 그렇게 하기가 번거로우므로 File Transfer 기능을 사용한 것이다.
이거나 그거나 데이터를 디바이스로 날린다는 거는 매한가지다.

clip_image003

본좌가 만든 bin파일은 Visual Studio같은 바이너리 파일이 편집 가능한 툴로 편집할 수 있다.

그렇게 데이터를 날리면 아래와 같이 호스트가 날린 테이터에 따라 LED가 깜빡인다.
LED가 너무 빨리 깜빡이면 우리 눈에는 안 보이므로 본좌가 TD_Poll()의 마지막 if문에서 delay를 준 것이다.

Posted in USB Lecture | Leave a Comment »

버튼입력을 받아보자

Posted by Digital Angel Master on March 31, 2008

인터럽트 모드 트렌스퍼에서 인터럽트의 의미가 “끼여들기”라기 보다는 “가끔”이라는 것은 이미 언급했었다.
인터럽트 엔드포인트 디스크립터를 보면 Polling Time이라는 항목이 있는데 여기에 세팅된 시간 간격으로 호스트가 디바이스에게 전송할 데이터가 있는지 정기적으로 물어 보게 된다.

USB의 구조가 호스트-슬레이브의 구조이므로, 디바이스가 호스트에게 전송할 무언가가 있다고 해서 디바이스 맘대로 호스트를 호출 할 수 없다.
노예(Slave)는 항상 주인님(Host)이 물어볼 때만 대답할 수 있다.
따라서 디바이스가 호스트에게 데이터를 보내야 할 필요가 있다면 호스트가 정기적으로 디바이스에게 보낼 데이터가 있는지를 물어보도록 만들어야 한다.
이런 때 쓰이는 Transfer Mode가 Interrupt Transfer Mode이다.

디바이스의 버튼이 눌린 것을 어플리케이션에 알리고자 한다면, 인터럽트 엔드포인트를 사용하는 것이 적절 할 것이다.

소스코드 : UniHigh1.4.zip

먼저 Endpoint Descriptor를 추가하자.

;; Endpoint Descriptor      db   DSCR_ENDPNT_LEN		;; Descriptor length      db   DSCR_ENDPNT		;; Descriptor type      db   81H			;; Endpoint number(1), and direction(IN)      db   ET_INT			;; Endpoint type      db   40H			;; Maximun packet size (LSB)      db   00H			;; Max packect size (MSB)      db   64H			;; Polling interval(100ms)

Maximum Packet Size는 64byte로 설정 하고 있는데, High Speed에서는 1024byte, Full Speed에서는 64byte, Low Speed에서는 8byte까지 설정 할 수 있다.
그러나 우리가 인터럽트 엔드포인트로 쓸 EP1의 버퍼사이즈가 64byte이므로 위와 같이 설정해 주었다.
(T.R.M. Page 1-23의 그림 참조)
물론 High Speed의 1024byte의 인터럽트 트렌스퍼를 사용하고 싶다면 EP2나 EP6를 이용하면 된다.

Polling Interval은 1~255까지 설정 할 수 있고, 단위는 mSec이다.

위의 디스크립터를 High Speed Config Descriptor와 Full Speed Config Descriptor에 추가해 주고, 각각의 Interface Descriptor의 Number of end points 필드도 1로 세팅해 주어라.

본좌가 메시지를 EP1을 통해 호스트로 날리기 위한 함수를 하나 추가 했다.

void SendMessage( BYTE cMessage, WORD wParam ){	while((EP1INCS & bmEPBUSY));	//wait until EP1IN Endpoint available

	EP1INBUF[0] = cMessage;	EP1INBUF[1] = LSB(wParam);	EP1INBUF[2] = MSB(wParam);

	EP1INBC = 3;}

EP0에서 데이터를 날리기 위해 EP0BCH/L을 썻던 것과 마찬가지로 EP1에서는 EP1INBC를 쓰면 된다.

이 루틴은 비단 버튼이 눌릴 때만이 아니라, 디버깅 용도로도 유용하다.
EZ-USB Control Panel을 이용하는 지금이야 디버깅 용도로 사용하기가 좀 번거롭지만, 앞으로 우리가 어플리케이션을 코딩하게 되면 이 루틴을 사용해 디바이스의 상태를 계속 USB포트를 통해 우리에게 보여 줄 수 있다.
그래서 본좌가 “WORD wParam”인자를 추가로 확보해 둔 것이다.
버튼 눌린 상태만 알고자 한다면 “BYTE cMessage”로도 충분한 데 말이다.

그 외에 Timer2를 사용하기 위해 TD_Init에 초기화 코드를 추가하고, Fw.c에 timer2_isr() Interrupt Service Routine을 추가 한 다음 TD_Poll()에 버튼입력을 체크하는 루틴을 추가 했다.

타이머는 버튼이 한 번 눌리면 일정시간 동안은 버튼 입력을 무시하도록 하는데 사용했다.
버튼이 눌릴 때 노이즈를 걸러내기 위해 세 번쯤 포트의 레벨 상태를 검사하는 루틴은 이 코드에서는 추가하지 않았다.
행자들이 추가 해 보시든가 하시라.

회로도는 아래와 같다.
아래 사진에서는 본좌는 점선으로 표시된 저항은 안 달았다.
사실 버튼입력 받을 때 이렇게 회로를 꾸며야 맞는지도 잘 모르겠다.
(본좌 하드웨어하는 넘이 아니므로 행자들이 이해 하시라.)
하지만 잘 작동하니까 대~충 맞다고 치자.
본좌처럼 점선 안의 저항을 생략하면 스위치가 눌릴 때 VCC와 GND가 쇼트되므로 별로 좋을 것 같지는 않다.

clip_image001

clip_image002

EZ-USB Control Panel로 버튼 입력을 받으려면, 펌웨어를 다운로드 한 다음에 “Get Pipe”버튼을 눌러주어 Pipe0(Endpoint 0)이 나타나는 지를 확인하고, “Bulk/Int”버튼을 누르면 된다.
잠시 어플리케이션이 응답이 없는 것처럼 보일 것이다.
디바이스로부터 응답을 기다리는데, 아직 버튼이 안 눌렸으므로 디바이스에서 응답을 안 하여서 마냥 기다리는 것이다.

clip_image004

나중에 우리의 어플리케이션을 짤 때, 이러한 상황을 피하기 위해서는 버튼을 체크하는 루틴은 다른 쓰레드에서 돌려주어야 한다.
안 그럼 이 경우처럼 프로그램의 메인 쓰레드가 디바이스로부터 응답이 있을 때까지 얼어 있게 된다.

자 이제 버튼을 눌러보자.
버튼 눌림이 표시 될 것이다.

그럼 버튼 먼저 누르고, “Bulk/Int”버튼을 눌러보자.
바로 응답이 올 것이다.
버튼이 눌렸다는 데이터가 FX2 버퍼에서 대기하고 있다가, 호스트가 요청하자마자 바로 보내기 때문에 즉각적인 응답이 나타난 것이다.

Posted in USB Lecture | Leave a Comment »

집중력을 높이는 방법

Posted by Digital Angel Master on March 31, 2008

1) 주위환경을 정돈하는 것입니다.
환경은 인간의 행동에 미치는 영향이 매우 큽니다. 그러므로 집중이 안되면 우선 환경부터 정돈해야 합니다. 그리고 잡음, 통풍, 온도, 조명 등을 잘 다스려서 좋은 분위기에서 공부해야 합니다.

2) 생리적인 상태를 잘 유지하는 것입니다.
너무 배고프거나 배부르거나 피곤하고, 몸이 아파도 정신집중이 안 됩니다. 그러기에 식사한 후 30분 동안은 학습을 하지 않도록 해야합니다.

3) 심리적인 안정을 유지하는 것입니다.
늘 안정된 심정을 갖도록 해야하며 과거에 대한 후회, 쓸데없는 공상, 미래에 대한 염려 등으로 정신이 산만하게 되는 것을 예방해야 합니다.

4) 일에 대한 기대감·호기심·흥미를 키우는 것입니다.
자기가 좋아하는 일을 하게 되면 집중해서 일할 수 있습니다. 에디슨은 일 하는 것이 오락이라고 생각하면서 그는 하루에 18시간씩 일해도 결코 피곤해하지 않았다고 합니다. 공부도 오락처럼 즐겁게 할 수 있다면 학습 능률은 점점 증가되기 마련입니다.

5) 한번에 한가지만 해낸다는 원칙을 세우는 것입니다.
두 마리의 토끼를 좇는 자는 한 마리도 못 잡습니다. 즉, 잡다한 행동을 멈추고 힘을 한가지에 집중시켜야 합니다.

6) 매사에 구체적 목표와 마감 시각을 정해 놓아야합니다.
어떠한 일에 긴장감이 없이 일을 하면 집중력이 더욱 떨어지게 되기에 목표와 계획된 시각이 정해 놓을 필요가 있습니다.

7) 집중이 잘되는 시간에 집중해서 일하는 것입니다.
집중이 잘 되는 시간은 개인마다 다르지만 밤보다는 오전, 오전보다는 새벽시간에 잘 됩니다.

Posted in Life News | Leave a Comment »

잠을 쫒는 방법

Posted by Digital Angel Master on March 31, 2008

1. 커피 마시기 – 체질에 따라 안되는 사람도 많습니다.

2. 졸릴 때는 바람 쐬기 – 마당이나 거실을 걷는 것입니다만, 밖에는 나가지 마세요. 밤 늦게 밖을 서성거리는 것은 대단히 위험한 일입니다. 집안(담안)에서 해결하도록 하세요.

3. 찬 물로 세수하기 , 찬 물로 머리감기 – 찬 물에 머리를 담그고 한참 있으면 아주 좋음

4. 화장실에서 음악 틀어 놓고 춤추기 – 식구들에게 밀 알리며 너무 크게 틀지 않는다.

5. 송곳이나 바늘, 연필 끝으로 발바닥, 손바닥, 손끝, 발끝 찌르기 – 아프게 찌를 것, 손끝이나 발끝은 피가 나도 좋음. 체하면 일부러 따기도 하잖아요..

6. 자신의 뺨 때리기 -자신의 뺨을 사정없이 마구 때릴 것, 단 고막이 터지지 않도록 귀 주위를 때리지 않도록 조심할 것.

7. 다리나 팔 아주 세게 꼬집기 – 눈물이 찡 날 정도로 꼬집어야 합니다.

8. 찬 물 떠놓고 발 담그기 – 책상 밑에 찬물을 한 대야 떠놓고 발을 담그세요.한가지 주의할 것은 발로 차서 쏟으면 골 때립니다.

9. 무서운 생각하기 – 머리 풀고 칼을 입에 물고 있는 산발한 귀신이 뒤에 서 있다고 생각할 것

10. 콘푸레이크를 우유에 타서 먹기 – 단 살이 안 찔 정도로 알맞게 먹을 것

11. 몸을 뒤로 한껏 제껴 기지개하기 – 30회 반복하기.. 그 자체가 대단한 운동이어서 잠이 달아남

12. 박수 500번 치기 – 큰 소리로 횟수를 쉬어가며 박수칠 것. 중간에 뺨도 한 대씩 때리면 더욱 효과적임.

13. 껌 씹으며 공부하기 -껌을 씹으면 턱 운동이 되므로 잠이 달아남. 운전자 졸음 방지용 껌이면 더욱 효과적임. 단 껌 2-3개 정도를 한꺼번에 씹으면 더욱 효과적임

14. 얼음 주머니로 얼굴 문지르기 – 냉장고의 얼음을 손수건에 싸서 졸릴 때마다 얼굴에 문지른다.

15. 의자에서 일어났다 앉았다 100회 반복하기 – 이 자체가 너무 고통이다. 반드시 횟수를 소리 내어 셀 것이며 팔을 앞으로 쭉 평치고 하거나 위로 올리고 하면 더욱 끝내줌

16. 엎드려 뻗혀하기 – 단, 이 경우는 그대로 엎어져 자는 수가 있으므로 바닥이 더러운 장소에서 하는 것이 좋음

17. 귀 끝을 꼬집기 – 귀 끝을 아주 세게 정말 잔인할 정도로 꼬집으며 눈물이 핑 돈다.

18. 알통 누르기 – 팔 알통부분을 엄지로 아주 강하고 세게 누르면 느낌이 얼얼한 것이 죽인다.

19. 머리카락 잡아 당기기 – 머리카락 몇 올을 을 꼭 잡고 순간적으로 확 잡아당길 것. 머리카락이 빠지지 않을 정도로 당길 것, 머리숱이 적은 사람은 하지말 것

20. 노래부르기 – 무릎을 때리며 반주를 넣으면서 좋아하는 노래를 부른다. 집이면 크게 부를 것, 단 식구들의 양해를 구할 것

21. 손가락으로 턱 튕기기 – 이마에 손가락 튕겨 때리면 아프잖아요. 똑같은 식으로 턱에 손가락을 튕겨 때려보세요. 잠이 확….

22. 의자에 앉은 채 머리 돌리기 운동하기 – 적당한 속도로 돌릴 것 마구 돌리면 어지러워 오히려 역효과임

23. 소리 지르기 – 아주 발악적인 소리를 지른다. 단 가족들에게 미리 말해둘 것. 옆집에서 놀라지 않을 정도의 크기여야 할 것 스트레스 해소와 잠 쫓기에는 소리 지르기가 짱

24. 발끝으로 걷기 – 의자에서 일어나 발끝으로 온 집안을 걸어보라. 발끝이 지압이 되므로 몸에도 좋고 잠도 깬다.

Posted in Life News | Leave a Comment »