2011년 7월 29일 금요일

5각형으로 만든 돔 (Geodesic dome)

조명 장치와 카메라를 여러대 달려고 구상중 아크릴판을 통짜로 가공하는 방식은 너무나도 번거롭고 모양의 변형이 많다.

그래서 구조적으로 견고하고 일정한 반경의 돔을 간단한 기초 작업으로 쉽게 만드는 방법을 찾던 중 pentagon(5각형)으로 암실 돔을 구성하면 어떨까? 하고 찾아 보았다. 외국에서는 과학 캠프나 실습차원에서 많이 하는 것 같다. 나도 예전에 서울 대공원에서 본 것 같은 기억이 있다. 가본지 너무 오래 되어서 아마도 거기 입장료가 좀 쎘었던거 같다.

아무튼 http://hilaroad.com/camp/projects/dome/domemath.html 에 가보면 원하는 직경의 Geodesic 돔을 구성할 수 있는 계산을 할 수 있게 해준다. 다음에는 이것을 번역해 보아야 겠다. 위와 같은 것을 레고 처럼 구성할 수 있다면 조명과 카메라를 자유 자재로 안정적인 위치에 고정 시킬 수 있을 거 같다.

Hila Science Camp

Dome Math

Geodesic Domes



돔을 만드는 사람들은 이러한 방식의 돔을 2V Icosa Alternate 라고 부른다.  icosahedron의 각 삼각형 표면안에 딱 맞는 4개의 삼각형에 의해서 만들어 진다. icosahedron란 뭔가? icosahedron는 고대 그리스인들에 의해서 만들어진 5개의 구조물(solids) 중의 하나이다. 이것이 그들 5개이다:



어떻게 이름 지어졌을까? 우측 맨 끝이 icosahedron이다. 이것은 20의 삼각형 면을 가지고 있다.
여러분이 정말로 정말로 알고 싶다면, 다음의 링크를 따라가서 어떻게 삼각형이 icosahedron의 각각의 삼각형에 맞아 떨어지는지 알아 볼 수 있다. - Icosahedron Domes Explained!

맨 위에서 보여주는 것과 같은 돔을 만들기 위해서, 여러분은 40개의 삼각형, 30개의 isosceles 삼각형, 그리고 10 equilateral 삼각형을 만들어야 한다.

돔을 디자인해 봅시다!

1단계:

여러분이 만들고자하는 돔의 직경을 결정하자. 우선 작은 30cm정도의 직경을 갖는 작은 모델을 만들어 보자.

2단계:

필요한 삼각형의 크기를 결정하자. 우리가 만들어야할 삼각형은 각면에 접착용 탭이 필요하다. 다음과 같이 생겼다:


10개의equilateral 삼각형은 각 면이 "A" 길이로 같다. "A"를 결정하기 위해서 "Chord Factor" 라고 불리는 숫자를 사용한다.
"A"를 위한 chord factor는 0.61803. "A"의 길이를 결정하기 위해서 여러분이 디자인한 돔의 반경에 이 chord factor를 곱하자. 반경은 직격의 1/2에 해당한다는 것을 잊지 말자. 지금 디자인하는 돔은 직경이 30cm이고 반경은 15cm이다.


A = 돔의 반경 x 0.61803
A = 15 cm x 0.61803
A = 9.27045 cm
A=9.27 cm

30 isosceles 삼각형은 한 면이 "A"이고, 두 면은 "B"이다. "A"값은 9.27cm으로 알려져 있고, "B"를 계산하기 위해서 우리는 다른 chord factor를 사용한다. "B"를 위한 chord factor는 0.54653이다.



B = 돔의 반경 x 0.54653
B = 15 cm x 0.54653
B = 8.19795 cm
B = 8.20 cm


3단계:

이 돔을 구성하기 위해서 "A"와 "B"값으로 구성된 삼각형 요소들을 만들어야 한다. 단단한 cardboard위에 30cm 직경의 원을 그리고 다음 링크의 내용을 따라하도록 하자. instructions for constructing the  50 cm dome.어떤 크기의 돔이라도 만들 수 있다. 그저 반경에 chord factor만 곱하면 된다. 그리고 나서 조립하는 순서만 따라하면 된다. 

이 페이지는  Hila Science Camp: http://hilaroad.com 에 의해서 만들어 졌습니다.



돔 조립하기


Geodesic dome들은 우아하고 정교한 구조물이다. 가벼운 무게와 강인함으로 인해서 재료를 아주 효율적으로 사용하도록 만든다. 북극과 같은 먼 지역에서 사용하기에 이상적인 구조다. 언젠가 달이나 covering(?) 도시에서 돔 구조물을 볼지도 모른다.


이 사이트는 종이로 geodesic dome을 만드는 과정을 차례차례로 제공한다. 그 내용은 다른 크기의 dome을 디자인할 수 있는 것도 포함한다.

이 프로젝트는 많은 지방과 주에서의 과학과 기술 교과 과정의 구조와 매커니즘 부분을 지원한다. 교과 과정의 목표는 geodesic dome이나 shell 구조물을 구축하는 것을 종종 포함한다. geodesic dome은 독특한 구조에서 생기는 응측력과 팽창력을 보여준다. 여러분은 다양한 재질로된 geodesic dome을 구축할 수 있다. 지금의 dome은 종이로 구축될 것이다. 다른 크기의 dome을 구축하기 위해선 여기서 제시된 디자인 개념을 사용하고 Bristol 보드나 골판지, plywood 심지어는 얼음과 같은 재료로도 도전해 보자!

6, 7 학년의 학생에 대해서 어떤 교사들은 활기차고 화려한 조작으로 변화 시켜서 이 같은 활동을 미술 시간과 결합하기도 한다.

이 프로젝트의 수학적인 부분은 8학년과 9학년의 응용 수학에 아주 적당하다. 응용 수학과 "구조와 매커니즘"에 대한 여러분의 주와 지방의 교과 과정 문서를 확인해보자.


Geodesic Dome 구축하기

Geodesic dome은 Buckminister Fuller에 의해서 대중화 되고 삼각형들의 구조적 접목이 dome이나 shell 구조물의 고유의 강도에 더해 졌다.


다음은 50cm의 직경을 갖는 geodesic dome의 구축하는데 필요한 지시사항들이다. 여러분이 다른 크기의 dome을 만들고자 한다면 다음 링크를 따라하자.  - DOME MATH

먼저 아래에 보여진 삼각형들의 정확한 그림을 생성해서 시작해보자. 여러분은 30개의 B-A-B 삼각형과 10개의 A-A-A 삼각형이 필요하다. 이 삼각형으로 만들어진 유닛들은 기본 구성 요소가 된다. 여러분은 이 삼각형들을 정확하기 만들어야 하기 때문에 제시된 수치들은 매우 중요하다. 콤파스와 자를 사용하자. A, B의 수치는 삼각형의 각 면의 길이가 되고 접착면을 위한 tab은 여분이 됨을 주의하자.




A-A-A 삼각혀은 equilateral 이라고 하고, B-A-B 삼각형은 isosceles라고 한다.



이것은 기하학에서 훌룡한 예제가 된다. 각 삼각형의 요소요소의 정확한 도면을 만들기 위해서 콤파스와 자, 연필로 작업하자.

각 삼각형의 도면을 그린 후 photo copy만으로 dome을 만드는데 충분하다. 어떤 종류의 종이도 적당하다.
두 가지 색상의 종이를 사용하자. 하나는 A-A-A 삼각형에, 다른 하나는 B-A-B 삼각형에 사용하자. 색상을 다르게 하는 것은 구축을 쉽게하고 여러분의 dome을 좀 더 극적이게 보이도록 만든다.

나는 이 삼각형들의 도면을 그리고 싶지 않다. 그져 dome을 만들고 싶다!
좋다. 이미 그려진 요소들을 위한 프린트 가능한 페이지에 대한 링크를 따라가라.


Link to template for A-A-A triangle: (PDF File)

Link to template for B-A-B triangle: (PDF File)




주의 사항: 프린트 한후 "A"와 "B"면이 정확한 길이로 프린트 되었는지 확인하라. 모든 프린트가 동일한 해상도 이지는 않다.

삼각형을 잘라내고 tab 라인을 조심스럽게 접자. 깔끔하게 접는 것이 무엇보다도 중요하다.
다섯개의 A-B-B삼각형을 조합해서 pentagon을 만들자. "B"면을 접착면을 활용해서 접착시키자. 접착용 풀은 이 프로젝트에 아주 적당하다.





pentagon의 외부 면이 삼각형의 "A" 면이 되도록하는 것을 명심하자.




완성된 pentagon은 위의 이미지와 같게 보여야 한다. 가운데가 쏫아 올라와야 한다. 다섯개의 pentagon을 더 만들자.

판지로 75cm 직경의 원은 만들어서 dome을 위한 바닥을 만들자. 
그리고 그 바닥의 중앙에 50cm 직경의 원은 그리자.

바닥의 중앙의 25cm의 원을 잘라내자. 이것은 dome의 안쪽을 접근할 수 있도록 해줄것이다.




중요: 원 주위에 chords의 나열을 조심스럽게 그리자. 각 chord의 길이는 "A"이다.

50cm dome을 위해서 A값은 15.45 cm 이다. 원 주위에 10개의 chord가 완벽하게 들어 맞도록 위치시키자.

이 라인들은 각 삼각형이 어디에 위치해야하는 지를 알려준다.


두개의 pentagon 사이에 하나의 A-A-A 삼각형을 붙여서 두개의 pentagon을 붙이자.
또 다른 삼각형은 다음과 같이 추가하자.

이 완성된 부분의 바닥 부분에 접착제를 붙이고, chords의 한 부분에 각 삼각형의 한 면을 위치시키자. 



계속해서 pentagon과 삼각형을 추가하고, 접착제로 이들은 고정시키자.



equilateral ( A - A - A ) 삼각형은 맨 꼭대기의 pentagon 사이사이에 붙이자.
  
매 꼭대기에 마지막 pentagon을 붙이자.




여러분의 dome은 완성되었다. dome에 관한 것을 더 배우고 싶다면 다음의 링크를 따라가자.  Dome Math. 

이 페이지는  Hila Science Camp: http://hilaroad.com 에 의해서 만들어 졌습니다.


그리고 좀 더 복잡하고 실제적인 내용은 다음 링크를 따라가 보자. 다른 내용도 유용한 것들이 많다. - http://www.byexample.com/articles/topics/geodesic_domes

Matrox Solios eV-CL + MIL-Lite 9.0 + 2 * VCC-F22V39ACL

At first, it is necessary to change the configuration from Solios Camera Link Medium to Solios Camera Link Dual Base in Solios under Boards of left tree on Milconfig during unplugged the two camera. and then, reboot system.



In login time, the system detects Solios eV-CL as a new hardware named by Solios eV-CL Dual 0. And we can select the digitizer in Intellicam.


And the system totally detects three different new hardware like this:


In development part, for each camera a digitizer is able to allocated;

MdigAlloc(MilBoard[0].MilSystem, M_DEV0, DCF_NAME, M_DEFAULT, &MilDigitizer0);
MdigAlloc(MilBoard[0].MilSystem, M_DEV1, DCF_NAME, M_DEFAULT, &MilDigitizer1);

To control Matrox Solios Camera Link Com Port 0(COM3) and Port 1 (COM4) configuring  via MsysControl is better than via Windows API.

MsysControl(MilBoard[0].MilSystem, M_UART_DATA_LENGTH+M_UART_NB(M_DEV0), 8);
MsysControl(MilBoard[0].MilSystem, M_UART_PARITY+M_UART_NB(M_DEV0), M_DISABLE);
MsysControl(MilBoard[0].MilSystem, M_UART_STOP_BITS+M_UART_NB(M_DEV0), 1);
MsysControl(MilBoard[0].MilSystem, M_UART_SPEED+M_UART_NB(M_DEV0), 9600);
MsysControl(MilBoard[0].MilSystem, M_UART_TIMEOUT+M_UART_NB(M_DEV0), M_INFINITE); // ms

MsysControl(MilBoard[0].MilSystem, M_UART_DATA_LENGTH+M_UART_NB(M_DEV1), 8);
MsysControl(MilBoard[0].MilSystem, M_UART_PARITY+M_UART_NB(M_DEV1), M_DISABLE);
MsysControl(MilBoard[0].MilSystem, M_UART_STOP_BITS+M_UART_NB(M_DEV1), 1);
MsysControl(MilBoard[0].MilSystem, M_UART_SPEED+M_UART_NB(M_DEV1), 9600);
MsysControl(MilBoard[0].MilSystem, M_UART_TIMEOUT+M_UART_NB(M_DEV1), M_INFINITE); // ms

In serial-communication of VCC-F22V39ACL, the format of serial frame is:

* Total 14bytes


* Function settings





2011년 7월 28일 목요일

Trilinear coordination 이란 ?

삼각형 ABC에 대한 주어진 어떤 점 P의 trilinear coordinates라고 표현한다. trilinear coordinate를 표현하기 위해선 하나의 삼각형과 하나의 점이 주어져야한다.

 그럼 trilinear coordinate는 주어진 점 P에서 삼각형의 세 변의 수직거리에 해당하는 α, β, γ의 비로 나타나게 된다. 여기서, α 는 점 P와 변 BC의 수직거리이고,  β는 점 P와 변 CA의 수직거리, 그리고  γ는 점 P와 변 AB의 수직거리이다.

이와 같이 α : β : γ는 homogeneous coordinates 나 "trilinears"라고 부른다. 그리고 trilinear coordinate는 1835년에 Plücker에 의해서 소개되었다. 간단히 표현해보면 삼각형 ABC의 세 꼭지점에 해당하는 A, B, C는 1:0:0, 0:1:0 그리고 0:0:1의 trilinear coordinate로 표현된다.

참조 : http://mathworld.wolfram.com/TrilinearCoordinates.html

2011년 7월 27일 수요일

리눅스에서 파일 정보 캐시 만들고 빠르게 검색하기

# updatedb

# locate $(your_file_name)

삼각형의 면적 구하기 (Heron's formula)

Heron's formula에 의하면 삼각형 ABC의 넓이는 다음과 같다. 단, s는 (a+b+c)/2로 정의한다.


위와 같은 식은 다음과 같이 유도할 수 있다.

삼각형 ABC를 수직으로 분할하는 두 개의 삼각형에 대한 피타고라스의 정리는 다음과 같은 관계식을 제공한다.


그리고 두 수식으로부터 다음과 같은 관계식을 유도할 수 있다.


그럼 삼각형 ABC의 넓이는 c*h/2이고 이 넓이의 제곱값은 다음과 같이 전개할 수 있다.



그리고 s=(a+b+c)/2로 정의하면 Heron's의 방정식은 증명된다.


/* By Heron's formula, the area of the triangle
   sqrt(s*(s-a)*(s-b)*(s-c)), s: (a+b+c)/2 */
real_t triangle_area(triangle_t *tri)
{
  real_t s, a, b, c;

  assert(tri);

  a = distance_between_points(tri->b, tri->c);
  b = distance_between_points(tri->c, tri->a);
  c = distance_between_points(tri->a, tri->b);
  s = (a + b + c) / 2;

  return sqrt(s * (s - a) * (s - b) * (s - c))
}

랩탑 시스템에서 하드디스크 끍는 소리 제거하기

알려져 있다시피 랩탑용 하드 디스크는 저전력을 위해서 디스크 암이 아무런 작업이 없을때 수시로 초기위치로 되돌아 갔다 트랙으로 갔다를 반복하게 "틱틱틱"하는 소음이 발생한다.

 윈도우즈의 경우는 하드디스크 튜닝 프로그램을 항시 상주시켜서 APM(Advanced Power Management)모드를 한단계 아래인 "254"로 설정 시키면 소음이 제거된다고 보고 되고 있다.

리눅스의 경우는 hdparm이라는 명령어를 적절히 사용하면 동일한 효과를 볼 수 있다.

# hdparm -B 254 /dev/hda1

부팅하게 되면 하드 디스크의 APM은 128로 설정되어 있던 것이 위의 명령어 이후에는 254로 설정된다. 이것을 부팅시 254로 영구적으로 설정되도록 하기 위해서 /etc/hdparm.conf파일에 다음과 같은 내용을 추가하자.

/dev/your-hard-drive {
   apm = 254
}

그리고 설정을 바로 적용하기 위해서 다음과 같은 명령어를 실행 시키도록 하자.

# update-rc.d hdparm defaults

한가지 더 손바주어야 할 부분은 랩탑의 경우 절전모드나 최대절전모드에서 되돌아 올 경우 하드디스크의 원래의 설정으로 되돌아 가버리기 때문에 /etc/pm/sleep.d/50_hdparm-pm 파일을 만들고 다음과 같은 내용을 추가하자.


#!/bin/sh
if [ -n "$1" ] && ([ "$1" = "resume" ] || [ "$1" = "thaw" ]); then
        hdparm -B 254 /dev/your-hard-drive > /dev/null
fi

그리고 실행가능하도록 다음과 같은 명령어를 실행하자.

# chmod +x /etc/pm/sleep.d/50_hdparm-pm

별 효과가 없다면 다음과 같은 내용을 갖는 "99-hdd-spin-fix.sh" 스크립트를 생성하자.


#!/bin/sh
# Use a less aggressive hard disk power management to get rid of
# clicking noise when the drive is parking its heads
hdparm -B 254 /dev/sda

이 스크립트를  /etc/acpi/suspend.d/, /etc/acpi/resume.d/, /etc/acpi/start.d/ 밑에다가 복사하고 실행가능하도록 해주자.

# chmod +x /etc/acpi/?????.d/99-hdd-spin-fix.sh

참조 : http://www.thinkwiki.org/wiki/Problem_with_hard_drive_clicking#Possible_solutions_.28Linux.29

2011년 7월 26일 화요일

삼각형의 외접원 구하기

삼각형의 세 꼭지점 A, B, C에 대한 외접원의 반지름 r과 중심점 O는 다음과 같이 구할 수 있다. 


위의 수식에서는 삼각형의 꼭지점 A, B, C의 벡터와 외접원의 중심점 O의 벡터로 표현되었다.


/* tri : given triangle
 * org : the center of circumscribed-circle
 * return value : the radius of circumscribed-circle */
real_t triangle_circumcircle(point_t *org, triangle_t *tri)
{
  real_t area, a, b, c;
  real_t alpha, beta, gamma;
  point_t *A, *B, *C;
  point_t *d1, *d2, *d3;

  assert(org);
  assert(tri);

  A = tri->a, B = tri->b, C = tri->c;
  area = parallelogram_area_of_3points(A, B, C);
  a = distance_between_points(B, C);
  b = distance_between_points(C, A);
  c = distance_between_points(A, B);

  d1 = point_new();
  d2 = point_new();

  point_subtract(d1, A, B);
  point_subtract(d2, A, C);
  alpha = a * point_dotproduct(d1, d2) / (2 * sqr(area));

  point_subtract(d1, B, A);
  point_subtract(d2, B, C);
  beta = b * point_dotproduct(d1, d2) / (2 * sqr(area));

  point_subtract(d1, C, A);
  point_subtract(d2, C, B);
  gamma = c * point_dotproduct(d1, d2) / (2 * sqr(area));

  point_destroy(d2);
  point_destroy(d1);

  org->x = alpha * A->x + beta * B->x + gamma * C->x;
  org->y = alpha * A->y + beta * B->y + gamma * C->y;
  org->z = alpha * A->z + beta * B->z + gamma * C->z;

  return a*b*c/(2*area);
}

2011년 7월 24일 일요일

리눅스 CAS(Computer Algebra System)설치 (Maple같은 수식 전개방식의 수학 프로그램)

삼각형의 외접원의 중심점과 반지름을 구하기 위해서 wiki를 검색해 보았다. circumscribed circle, 혹은 circumcenter등으로 너무나도 친절하게도 잘되어 있다. 그런데 하는 김에 3차원으로 되어 있는 것으로 프로그램을 작성해 보고 싶어 직접 수식을 구성해서 해보기로 했다.


이와 같이 간혹 수식을 종이에 전개해야할 일들이 종종 있다. 머리와 종이도 아낄겸 예전에 windows에서 사용하던 Maple을 리눅스에서 사용하기 위해서 찾아 보았다.

두개의 CAS(Computer Algebra System)이 검색되었다. MuPAD와 MAXIMA라는 프로그램이다. 우선은 MuPAD를 설치하기위해서 데비안 리눅스 패키지를 찾아 보았으나 없었다. 보아하니 상용으로 전환하는 수순이가 보다 Mathworks에 넘어가 MATLAB에서 툴박스로 사용할 수 있게 되어 있다. 예전부터 MATLAB에서 수식 전개와 같은 범용 계산이 가능했으면 했는데 이미 사들였던 것이다. 

그래서 MAXIMA로 눈을 돌렸다. 텍스트 버전도 있고 GUI버전에다가 emacs에서 사용할 수도 있게 제공하는것같다. 무엇보다도 데비안 리눅스 배포본을 착실하게 제공하는 것같다. 우선은 설치해봤다.

  • Maxima Algebra System
  • Maxima backend for Cantor
  • A computer algebra system -- documentation
  • A computer algebra system -- emacs interface
  • A computer algebra system -- source code
  • A computer algebra system -- test suite
  • A computer algebra system -- base system
  • A computer algebra system -- extra code

여러 개가 다수 존재한다. 우선 Maxima Algebra System만 선택해서 설치하도록 하고 도움 문서와 base system 정도만 선택해서 설치해 보기로 했다. 그랬더니 documentation, source code, test suite, base system, extra code가 같이 설치 되어 버렸다. 우선은 써봐야 겠다.

프로그램의 교육에 설치가 되어있다. 우선은 삼각형의 외접원의 원점을 구하는 방정식으로 시험해 보기로 했다.


결과는 보았으나 가져다 쓰기가 영 좋지가 못하다. 이것도 감지덕지이긴 하지만.

2011년 7월 19일 화요일

Double linked list in c language

* data type double linkage

struct dlink {
  void *object;
  struct dlink *prev;
  struct dlink *next;
};

typedef struct dlink dlink_t;

- object : reference pointer indicating the address for any-type user-data using casting to void type pointer.
- prev : previous pointer for double-linked component
- next : next pointer for double-linked component

* data type double linked list

typedef struct {
  int count;
  dlink_t *head;
  dlink_t *tail;
} dlist_t;

- count : the number of components contained by the list.
- head, tail : the start and end linkage for data- inport and outport.

----------------------------------- dlink.h -------------------------------------------

/* Double linked list

 Copyright 2011 Hoyoung Yi.

 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with this program; if not, please visit www.gnu.org.
*/

#ifndef __DLINK_H__
#define __DLINK_H__

struct dlink {
  void *object;
  void *private;
  struct dlink *prev;
  struct dlink *next;
};

typedef struct dlink dlink_t;

dlink_t *dlink_new(void);
void dlink_prepend(dlink_t *obj, dlink_t *at);
void dlink_append(dlink_t *obj, dlink_t *at);
void dlink_cutoff(dlink_t *obj);
void dlink_substitute(dlink_t *dummy, dlink_t *at);
void dlink_exchange(dlink_t *a, dlink_t *b);
void dlink_destroy(dlink_t *dlink);

typedef struct {
  int reference;
  int count;
  void *private;
  dlink_t *head;
  dlink_t *tail;
} dlist_t;

dlist_t *dlist_new(void);
void dlist_push(dlink_t *link, dlist_t *list);
dlink_t *dlist_pop(dlist_t *list);
void dlist_insert(dlink_t *link, dlist_t *list);
dlink_t *dlist_extract(dlist_t *list);
dlink_t *dlist_glimpse(int index, dlist_t *list);
dlink_t *dlist_pick(int index, dlist_t *list);
void dlist_put(dlink_t *link, int i, dlist_t *list);
void dlist_exchange(int i, int j, dlist_t *list);
void dlist_destroy(dlist_t *list);

#endif /* __DLINK_H__ */
----------------------------------- dlink.c -------------------------------------------

/* Double linked list

 Copyright 2011 Hoyoung Yi.

 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with this program; if not, please visit www.gnu.org.
*/

#include
#include
#include
#include "dlink.h"

dlink_t *dlink_new(void)
{
  dlink_t *dlink;

  dlink = malloc(sizeof(dlink_t));
  assert(dlink);
  memset(dlink, 0, sizeof(dlink_t));

  return dlink;
}

void dlink_prepend(dlink_t *obj, dlink_t *at)
{
  assert(obj);
  assert(at);

  obj->prev = at->prev;
  obj->next = at;

  at->prev->next = obj;
  at->prev = obj;
}

void dlink_append(dlink_t *obj, dlink_t *at)
{
  assert(obj);
  assert(at);

  obj->prev = at;
  obj->next = at->next;

  at->next->prev = obj;
  at->next = obj;
}

void dlink_cutoff(dlink_t *obj)
{
  assert(obj);

  obj->prev->next = obj->next;
  obj->next->prev = obj->prev;
}

void dlink_substitute(dlink_t *dummy, dlink_t *at)
{
  assert(dummy);
  assert(at);

  at->prev->next = dummy;
  at->next->prev = dummy;
  dummy->prev = at->prev;
  dummy->next = at->next;
}

void dlink_exchange(dlink_t *a, dlink_t *b)
{
  dlink_t *dummy;

  assert(a);
  assert(b);

  dummy = dlink_new();

  dlink_substitute(dummy, a);
  dlink_substitute(a, b);
  dlink_substitute(b, dummy);

  dlink_destroy(dummy);
}

void dlink_destroy(dlink_t *dlink)
{
  assert(dlink);
  free(dlink);
}

dlist_t *dlist_new(void)
{
  dlist_t *dlist;

  dlist = malloc(sizeof(dlist_t)+2*sizeof(dlink_t));
  assert(dlist);

  memset(dlist, 0, sizeof(dlist_t)+2*sizeof(dlink_t));

  dlist->head = (dlink_t *)(dlist+1);
  dlist->tail = dlist->head+1;

  dlist->head->next = NULL;
  dlist->head->prev = dlist->tail;

  dlist->tail->next = dlist->head;
  dlist->tail->prev = NULL;

  return dlist;
}

void dlist_push(dlink_t *link, dlist_t *list)
{
  assert(list);
  assert(link);

  dlink_append(link, list->tail);
  //dlink_prepend(link, list->head);
  list->count++;
}

dlink_t *dlist_pop(dlist_t *list)
{
  dlink_t *link;
  assert(list);

  //link = list->head->prev;
  link = list->tail->next;
  dlink_cutoff(link);
  list->count--;

  return link;
}

void dlist_insert(dlink_t *link, dlist_t *list)
{
  assert(list);
  assert(link);

  dlink_prepend(link, list->head);
  list->count++;
}

dlink_t *dlist_extract(dlist_t *list)
{
  dlink_t *link;

  assert(list);

  if (list->count == 0) return NULL;

  //link = list->tail->next;
  link = list->head->prev;
  dlink_cutoff(link);
  list->count--;

  return link;
}

dlink_t *dlist_glimpse(int index, dlist_t *list)
{
  dlink_t *link;

  assert(list);
  assert(index >= 0 && index < list->count);

  link = list->tail->next;
  while (index--) link = link->next;

  return link;
}

dlink_t *dlist_pick(int index, dlist_t *list)
{
  dlink_t *link;

  assert(list);
  assert(index >= 0 && index < list->count);

  link = list->tail->next;
  while (index--) link = link->next;
  dlink_cutoff(link);
  list->count--;

  return link;
}

void dlist_put(dlink_t *link, int i, dlist_t *list)
{
  dlink_t *ilink;

  assert(link);
  assert(i >= 0 && i < list->count);

  ilink = list->tail->next;
  while (i--) ilink = ilink->next;
  dlink_prepend(link, ilink);
}

void dlist_exchange(int i, int j, dlist_t *list)
{
  dlink_t *ilink, *jlink;

  assert(list);
  assert(i >= 0 && i < list->count);
  assert(j >= 0 && j < list->count);

  ilink = list->tail->next;
  while (i--) ilink = ilink->next;

  jlink = list->tail->next;
  while (j--) jlink = jlink->next;

  dlink_exchange(ilink, jlink);
}

void dlist_destroy(dlist_t *list)
{
  dlink_t *link;

  assert(list);

  if (list->reference == 0) {
    while (list->count > 0) {
      link = dlist_extract(list);
      dlink_destroy(link);
    }
    free(list);
  } else list->reference--;
}

2011년 7월 17일 일요일

Use GdkPixbuf in GTK+

At first it needs to create GtkImage on GtkViewport. Then, we can use GdkPixbuf-embedded GtkImage.

static void gdk_pixbuf_clear(GdkPixbuf *pixbuf)
{
   int x, y;
   int width, height, rowstride, n_channels;
   guchar *pixels, *p;

   n_channels = gdk_pixbuf_get_n_channels(pixbuf);
   g_assert(gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB);
   g_assert(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
   g_assert(gdk_pixbuf_get_has_alpha(pixbuf));
   g_assert(n_channels == 4);

   width = gdk_pixbuf_get_width(pixbuf);
   height = gdk_pixbuf_get_height(pixbuf);
   rowstride = gdk_pixbuf_get_rowstride(pixbuf);
   pixels = gdk_pixbuf_get_pixels(pixbuf);

   for (y = 0; y < height; y++) {
      for (x = 0; x < width; x++) {
         p = pixels + y*rowstride + x*n_channels;
         *(p+0) = 255; // red channel
         *(p+1) = 0; // green channel
         *(p+2) = 0; // blue channel
         *(p+3) = 255; // alpha channel
      }
   }
}


....

image = gtk_image_new();

....

pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 640, 480);
g_assert(pixbuf);

gdk_pixbuf_clear(pixbuf);

gtk_image_set_from_pixbuf(image, pixbuf);

...

2011년 7월 15일 금요일

FabFi - 무료, 공개된 오픈 소스 장거리 wireless ethernet 전송 시스템(Reflector + Router)

[출처] http://fabfi.fablab.af

FabLab의 공용으로 성장중인 시스템이다. 제목에서 보듯이 장거리 wireless ethernet 신호를 전송해 줄 목적으로 된 소스가 공개된 시스템이다. 서울에서는 필요없을 수도 있겠지만 wireless 네트워크가 미약한 지방의 경우 활용 용도가 분명히 있을 것이다. 그래도 reflector는 충분히 wireless 전파가 미약한 곳에서 RF 전파를 포집하는데 많은 도움이 될 수 있는 안테나 증폭기로 사용될 수 있을 듯 싶다. 찾아 보면 reflector의 도면 파일이 있다. 현재 케냐와 아프가니스탄 같은 기반시설이잘 갖추어 지지 않은 곳에서 구현되고 있다.

현제 wiki에서 제공하는 내용은 맨 처음으로 구성된 아프가니 스탄의 Jalalabad의 FabFi를 기반으로 설명하고 있다. 이 시스템은 uplink와 Open courseware 미러링을 제공하고 링크할 수 있는 거리는 3,880m이다.

FabFi의 안테나는 reflector와 router로 구성된다. reflector는 직접 개개인이 만들어야 하고, router는 수정된 기존 상품이다. reflector 디자인은 4인치에서 18인치까지로 범위가 다양한다. (plywood, signboard, 아크릴로 만든다.) radio frequency(RF)에 대한 반사 재료로 chicken wire(?),  스텐레스 짠 그물망, 그리고 강철로 된 윈도우 스크린를 사용한다. 특히 똑똑한 아프가니스탄 사람들은 오래된 USAID 쿠킹 오일 캔을 reflector로 사용하기 시작했다.

router는 쉽게 판매되는 가정용 wireless AP에 수정된 router-radio-antenna를 사용한다. 버전 3.0에서는 FabFi는 공식적으로 Linksys WRT54GL과 ASUS WL-520GU를 지원한다. 비록 다른 많은 router들도 그에 걸맞는 image를 생성하면 쉽게 사용할 수 도 있다. FabFi는 OpenWRTOpenWRT 8.09.2 (Kamikaze) firmware가 구동되는 상황에서 구동된다.


FabFi 기술 요약

개요
 
FabFi은 확장가능한 장거리 P2P 시스템이고 mesh hybrid-wireless broadband transmission 기반시설이다. 개념은 간단하다. 간단하고 지능적이고 서로 연결가능한 network가 불안정한 상황에서도 믿을 수 있는 network 환경을 만들어 낼 수 있다는 개념이다. FabFi는 low-cost 장치를 아주 먼거리에 대해서 직접적으로 통신할 수 있도록 하는 간단한 물리 개념과 아주 다양한 상황들에 적용할 수 있는 탄력적인 구성을 활용한다.

극한의 상황에 대해서 RF(Radio Frequency) 에너지를 방향 전환시킬 수 있는 wire mesh surface를 갖는 제작된 RF reflector위에 상용 wireless routers를 장착하여 사용한다. Reflector의 증폭율은 reflector의 크기와 사용된 재료에 의존한다. 그러나 현재의 디자인에서는 15dBi정도로 높게 측정되어진다.

A Single FabFi Link

FabFi 시스템에서 단일 wireless link는 wireless router가 장착된 두 대의 reflector로 구성된다. 이와 유사하게, 두 대의 router도 wired 연결로 link될 수 있다. 단일 router는  동시에 wireless 연결과 wired연결 둘 다로 link될 수도 있다. 이 시스템은 수많은 방법으로 구성된 개개의 link에 대한 구성도 가능하다. (매우 먼 거리나 작은 지역에 많은 사용자를 수용할수 있는 링크 같은 것들 말이다. 이 링크의 중요한 요소는 "meshing"이라는 것이다. mesh network는 구조화 되지 않는 ad-hoc같은 방식으로 하나 이상의 다른 근방의 디바이스에 접속할 수 있도록 허용하는 시스템이다. Mesh network는 소프트웨어가 network의 topology(구조)를 감지해서 실시간으로 자동적으로 데이터의 흐름을 결정하기 때문에 강인하고 단순하다. 전통적인 mesh network들은 단일 라디오와 wireless 만으로된 연결과 모든 방향을 커버할 수 있는 안테나에 의존하기 때문에 구조적으로 제한되어져 있다. 가능한 상황에 따라서 직접적인 wireless link나 유선 전송을 이용해서 Fabfi 시스템은 매우 큰 규모의 한곳에 고정되서 사용하는 mesh network를 구성할 수 있도록 최적화 되어 있다. 높은 데역폭의 좁은 영역의 uplink에 의존하지 않고 지역내에서 강인한 디지털 통신이 가능한 규모에서는 가격이 비싸고 많은 지역에서 사용 불가능하다. 좀 더 자세한 설명을 해주는 에니매이션을 확인해보자. (2MB의 용량으로 다소 시간이 걸릴수 있다.)
Meshing 101...
Reflector의 작동 방식


A FabFi Parabolic Reflector
FabFi의 reflector는 포물선의 준선에 수직한 전파가 포물선의 표면에 접촉할 때 이 전파들을 포물선의 초점에 모이게 하는 포물선 모양(Y=cX^2)의 구조를 사용한다.(이것에 대한 좀더 자세한 것은 Mathworld 를 보라...) RF 전파를 반사 시킬 수 있는 window screen, chicken wire같은 것을 3차원 의 포물선 모양을 이루는 frame에 붙이고 정확하게 계산된 추점에 wireless router를 붙인다. 그럼 전송 지점의 router에서 오는 RF 에너지가 수신부의 router에서 RF 에너지가 효율적으로 모아진다.

Reflector 만들기 


Cutting a Reflector From Acrylic
FabFi 시스템의 본질적인 부분은 지역특색에 따라 사용가능한 어떤 재료로도 구현할 수 있는 유연성이 있다는 것이다. 필요한 모든 것들은 2D 디자인 파일을 프린트하고 여러분이 찾을 수 있는 재료를 조각으로 만들 수 있는 능력이면 된다. 여러분이 Fab Lab을 가지고 있다면. 나무나 금속, 아크릴로 직접 reflector를 만들기 위해서 CNC 나무 제단기나 레이져 커터를 사용할 수 있다. 그러나 진흙으로 빚거나 돌을 깍거나 얼음 블럭을 끌로 파거나 해서 만들지 못할 이유는 없다. 2009년 1월에 초기 배치시 Jalalabad에서는 세 가지의 다른 reflector 디자인이 구현되었다: 큰 4인치의 나무로 된것과 2인치의 나무 버전 그리고 18인치의 아크릴 버전이 구현되었다. 반사면의 재질은 chicken wire와 스테인레스 강철로 짜여진 그물망과 window screen이 될 수 있다.
Three reflector Versions
다음으로 실제 현장에서 필요한 것들은 봉합된 방수가 가능한 뺏다 낄 수 있는 조립품의 수정된 reflector 디자인을 개발하는 것이다. 이 새로운 디자인 2010년 여름에 개시 되었다.
Reflector with integrated weatherproofing
그러나 멀리 볼 것도 없이 network 사용자들은 이미 지역적으로 구할 수 있는 고철 더미로 만든 reflector를 디자인하고 만들고 있다. 아직 중요한 부분에 정교한 장업이 필요하지만, 이 reflector들은 기술적인 면에서 지역 인력이 자체적으로 개발되는 기술이 전파되고 있다는 분명한 신호이다. 이것들은 모두 $3달러 이하의 가격이다.!
Reflector with integrated weatherproofing
Router와 FabFi 펌웨어는 OpenWRT라 불리는 open source 3rd party 펌웨어를 사용한다. OpenWRT는  리눅스 기반의 유연성을 장점으로 가지고 있어 FabFi 장치들은 다양한 범위의 모니터링과 자가 진단 도구들을 운용할 수 있다. 현재의 시스템은 실시간 network 모니터링과 local web을 저장해 집중된 접근을 제어하는 기능과 사용자 관리, 요금 부과를 위한 사용량 추적을 지원한다. 이 모든 것들은 $50에서 $100 달러의 장치에서 구현된다. 자동 구성 기능은 FabFi 1.0이 발표된 이후로 지속적으로 개선되어 왔다. 지금은 다중 fabfi상에서 다중 router를 지원하고 있다. 그리고 802.11n의 속도로 network를 구성할 수 있는 능력이 있다. 개발 부서에서 사용하는 전원인 안정적인 전원은 계속적인 도전거리다. 편리하게도 지금 지원하는 모든 장치들은 12VDC에서 동작하고 자동차나 작은 엔진 베터리에서 직접 전원으로 사용 될 수 있다. 자동차 배터리와 두 대의 비싸지 않은 충전기는 Jalalbad network에서 두 개의 큰 distribution  허브에서 작동하는 믿을 만한 UPS 장치로 작동한다. 도시의 전원없이 거의 이틀동안 router 를 동작시킬수 있는 전원이다. 케냐에서 주 전원과 태양열 전원을 모두 지원하는 network에 어느 node에나 부착할 수 있고 방수 기능이 있는 UPS를 지원하는 "node in a box"를 고안했다. 다음 개발 버전은 router에 연결된 일반 UPS나 제작된 UPS에 장착하는 100-240VAC switching power를 이용해서 설치할 수 있도록 하는 bare-bone 타입의 12V-12V UPS가 될 것이다. 바람이나 다른 그 지역에서 생산되는 전력으로 동작하는 충전회로들은 동시에 진행되는 FabLab의 프로젝트이다.


Fab Future는 미적인 부분도 고려되었을 뿐만 아니라, Fabfi는 일상적으로 모래 폭퐁이 부는 여름의 Jalalabad에서 130F의기온인 혹독한 아프가니스탄 기후에서도 놀랄정도로 안정적인 것이 증명되어 왔다. 2010년도 초여름에 fabfi 시스템을 client 장치에 직접 wireless 접속하도록 제공하고 통신망 규모의 wifi ISP업체를 운영해 왔다. 2년 이상의 운영하는 동안 한편으로는 여전히 하드웨어적인 실폐가 발견되기도 한다. 앞으로의 가장 큰 과제는 uplink 대역폭 문제이다. 많은 나라들은 범용적인 접속 문제의 해결방안으로써 "mobile broadband"를 밀고 있지만, 대부분의 지역에서의 실제적인 현실은 mobile 장치들만으로는 어떤 보조없이 감당할만한 충분한 가격이나 충분한 효율을 제공하지 못한다. 케냐에서 fabfi는 mobile 연결이 사용자당 데이타 허용량이 감소해서 단지 접속의 도구로 전락한 상황에서 통신하는데 가치있는 서비스를 제공한다.

이것에 관한것이다 기타 다른 프로젝트의 진행 과정은 여기 FabFi Blog에서 살펴 볼 수 있다.

reflectror 만들기

http://fabfi.fablab.af/distribution.html에 가서 알맞은 크기의 디자인을 다운로드 받아서 나무를 자르고 조립한다. 원하면 페인트를 칠하거나 실링을 할 수 도 있다. 그리고 조립된 프레임에 철로된 그물망이나 스크린을 고정시킨다. 고정면이 구부러지거나 주름이 생기지 않도록 단단하게 해야한다.

 
라우터 구성하기


안테나 설치하기


reflector에 router를 고정시킨다. 비가 올 경우를 대비해서 router주변을 비닐 봉다리로 둘러 싸거나 방수가 되는 플라스틱 박스를 사용한다. router에 전원을 인가하고 LAN포트에 인터넷이 연결될 수 있는 ethernet 케이블을 연결시킨다. 다른 FabFi의 방향으로 안테나를 조절한다. 컴퓨터의 LAN포트에 연결해서 연결상태를 점검한다. 안테나를 끈을 이용해서 단단히 고정한다.

2011년 7월 8일 금요일

Experimental USB Camera

 To test single CMOS Image sensor module, I combined CPLD, SRAM, and USB FIFO module. In the below pictures, these blocks are connected by jumping wire. To operate circuit, it is required three pieces of software; for CPLD, verilog HDL code to interfacing with SRAM, USB FIFO, and CMOS sensor. And for USB FIFO, 8051 based firmware code to operate as Slave FIFO. At final, PC based application and USB device driver.






CMOS Image Sensor Module

It is composed of Omnivision's OV9121, powering components and PCB. OV9121 is setting as Master mode; provided MCLK, it distributes PCLK, VSYNC, HREF and digital data signals to CPLD module. The provided MCLK is 10Mhz for stable operation despite of regular MCLK 24Mhz.

SRAM

It has asynchronous operation, 16bit data bus width and 10ns maximum operation time for both reading and writing. The purpose of SRAM is buffering between CMOS Module and USB FIFO.

CPLD Module

It is Dr.Kim CPLD Module(MCA128-10) from http://www.devicemart.co.kr/mart7/mall.php?cat=004010000&query=view&no=18796.
Because of poor performance CPLD, CMOS Sensor has to be operated under 10Mhz MCLK. Its functionalities are CMOS Image Sensor Data Interfacing (based on PCLK, VSYNC, HREF and Pixel Data Bus), Pixel Data Gathering (two 8bits pixel data merge to 16bits data to be able to save on SRAM), USB FIFO Interfacing (based on nFLAGB, nSLWR, 16bits FD). Here is verilog HDL code.


`timescale 1ns / 1ps


`define USE_FULL_FLAG


module cam2usb(RESET, TRIG, 
VSYNC, HREF, /* MCLK, */ PCLK, D,
nWE, nOE, A, IO,
IFCLK, nFLAGB, nSLWR, FD/*, LED*/);


// 정의 되지 않은 내부 reg값을 정해진 초기값으로 설정할때 사용 하는 Reset Pin
input wire RESET;
// 이미지 센서로 부터의 영상획득 시점을 알려주는 영상회득 개시용 pin
input wire TRIG;
// 이미지 센서로 부터 전달되는 한 화면 혹은 한 라인의 동기화 신호 
input wire VSYNC;
input wire HREF;
// 이미지 센서의 동작 클럭
//output wire MCLK;
// 이미지 센서의 한 화소의 전송 속도를 나타내는 동기화 클럭
input wire PCLK;
// 이미지 센서의 한 화소의 디지털화된 데이터 
input wire [7:0] D;
// USB 인터 페이스 칩와 FPGA 사이의 데이터 전송시 병목 현상을 차단하기 위한 메모리 인터페이스 
output reg nWE;
output reg nOE;
parameter ADDR_SIZE = 18;
output wire [ADDR_SIZE-1:0] A;
inout wire [15:0] IO;
// USB 인터페이스 칩의 동기화된 전송을 위한 인터페이스 클럭
output wire IFCLK;
// USB 인터페이스 내부 메모리의 FULL상태를 지시하는 플래그 
input wire nFLAGB;
// USB 인터페이스로의 데이터 전송을 지시하는 인터페이스 Pin
output reg nSLWR;
// USB 인터페이스로 전송할 데이터 버스
output reg [15:0] FD;
// output wire [3:0] LED;

/* 외부 메모리를 FIFO로 사용할 수 있게 해주는 인터페이스 
실제 외부로 노출되는 어트레스는 상위 한비트를 제외한 나머지 부분이다.
상위 한바이트는 FIFO의 FULL과 EMPTY상태를 구분하기 위해서 사용된다. */
reg [ADDR_SIZE:0] read_addr;
/*
always @(posedge PCLK) begin
if (RESET) read_addr <= 0;
else if (~nOE) read_addr <= read_addr+1;
end
*/
always @(posedge nOE) begin
if (RESET) read_addr <= 0;
else read_addr <= read_addr+1;
end


reg [ADDR_SIZE:0] write_addr;
/*
always @(posedge PCLK) begin
if (RESET) write_addr <= 0;
else if (~nWE) write_addr <= write_addr+1;
end
*/
always @(posedge nWE) begin
if (RESET) write_addr <= 0;
else write_addr <= write_addr+1;
end


`ifdef USE_FULL_FLAG
reg empty_flag;
reg full_flag;
always @(write_addr or read_addr) begin
if (~|(write_addr[ADDR_SIZE-1:0]^read_addr[ADDR_SIZE-1:0])) begin
if (~|(write_addr[ADDR_SIZE]^read_addr[ADDR_SIZE])) begin
empty_flag <= 1'b1;
full_flag <= 1'b0;
end else begin
empty_flag <= 1'b0;
full_flag <= 1'b1;
end
end else begin
empty_flag <= 1'b0;
full_flag <= 1'b0;
end
end
`else
reg empty_flag;
always @(write_addr or read_addr) begin
if (~|(write_addr[ADDR_SIZE:0]^read_addr[ADDR_SIZE:0])) empty_flag <= 1'b1;
else empty_flag <= 1'b0;
end
`endif


// 이미지 센서의 신호선의 상태를 제어하는 State Machine
// 픽셀 데이터를 2 byte단위로 포집해서 FIFO에 주기적으로 저장한다.
parameter CAMERA_HDLR_STATE_SIZE = 6;
parameter CAMERA_HDLR_IDLE       = 6'b000001;
parameter CAMERA_HDLR_WAIT_VSYNC = 6'b000010;
parameter CAMERA_HDLR_VSYNC      = 6'b000100;
parameter CAMERA_HDLR_WAIT_HREF  = 6'b001000;
parameter CAMERA_HDLR_HREF0      = 6'b010000;
parameter CAMERA_HDLR_HREF1      = 6'b100000;


reg [7:0] lower_byte;
reg [7:0] higher_byte;
reg [CAMERA_HDLR_STATE_SIZE-1:0] camera_hdlr_state;
always @(posedge PCLK) begin
if (RESET) begin
camera_hdlr_state <= CAMERA_HDLR_IDLE;
nWE <= 1;
end else begin
case (camera_hdlr_state)
CAMERA_HDLR_IDLE: begin
if (TRIG) camera_hdlr_state <= CAMERA_HDLR_WAIT_VSYNC;
nWE <= 1;
end
CAMERA_HDLR_WAIT_VSYNC: begin
if (VSYNC) camera_hdlr_state <= CAMERA_HDLR_VSYNC;
nWE <= 1;
end
CAMERA_HDLR_VSYNC: begin
if (~VSYNC) camera_hdlr_state <= CAMERA_HDLR_WAIT_HREF;
nWE <= 1;
end
CAMERA_HDLR_WAIT_HREF: begin
if (HREF) begin
camera_hdlr_state <= CAMERA_HDLR_HREF0;
lower_byte <= D;
end else if (VSYNC) begin
camera_hdlr_state <= CAMERA_HDLR_IDLE;
end
nWE <= 1;
end
CAMERA_HDLR_HREF0: begin
camera_hdlr_state <= CAMERA_HDLR_HREF1;
higher_byte <= D;
nWE <= 0;
end
CAMERA_HDLR_HREF1: begin
if (HREF) begin
camera_hdlr_state <= CAMERA_HDLR_HREF0;
lower_byte <= D;
end else begin
camera_hdlr_state <= CAMERA_HDLR_WAIT_HREF;
end
nWE <= 1;
end
default: begin
camera_hdlr_state <= CAMERA_HDLR_IDLE;
nWE <= 1;
end
endcase
end
end


// FIFO의 상태와 USB 인터페이스의 상태, 이미지 센서 State Machine의
// 상태에 따라서 저장되있던 픽셀 데이터를 읽어 온다.
always @(posedge PCLK) begin
if (nOE &                                     // 최소 두 클럭당 한번의 읽기가 가능하다.
(|(camera_hdlr_state^CAMERA_HDLR_HREF0)) & // 메모리 Write단계일 때는 read 금지
(~empty_flag) &                            // 메모리가 비워져 있을때는 읽기 금지
nFLAGB) begin                              // USB 인터페이스가 꽉 찼을때는 읽기 금지
nOE <= 1'b0;
end else begin
nOE <= 1'b1;
end
end


assign A = (nOE ? write_addr[ADDR_SIZE-1:0] : read_addr[ADDR_SIZE-1:0]);
assign IO = (nOE ? {higher_byte, lower_byte} : 16'hz);


// FIFO에서 읽어온 데이터를 USB 인터페이스에 전송한다.
always @(posedge PCLK) begin
if (nOE) nSLWR <= 1;
else nSLWR <= 0;
end
/*
always @(posedge PCLK) begin
if (~nOE) FD <= IO;
end
*/
always @(posedge nOE) begin
FD <= IO;
end


assign IFCLK = PCLK;
// assign LED[0] = ~|(camera_hdlr_state^CAMERA_HDLR_IDLE);
// assign LED[1] = empty_flag;
// assign LED[2] = full_flag;
//assign LED[3] = 


endmodule

USB FIFO Module

Cypress FX2LP USB FIFO has several operation modes. In here, Slave FIFO mode is proper to interface with CPLD. It's scheme is informing internal status of 2k bytes fifo ram on FX2LP, allowing data transferring via CPLD under not-FULL internal status (nFLAGB's high state) and transferring via USB.


#pragma NOIV               // Do not generate interrupt vectors
#include
#include
#include            // SYNCDELAY macro
#include "counter0.h"
#include "binary.h"


typedef enum {
IDLE_STATE     = 0x00,
ON_STATE       = 0x01,
OFF_STATE      = 0x02,
AUTO_INV_STATE = 0x04
} state_t;


//#define BLINK_COUNT 2000 // 500us
#define BLINK_COUNT 4000 // 1ms


state_t state_PA0 = IDLE_STATE;
unsigned short count_PA0;
state_t state_PA1 = IDLE_STATE;
unsigned short count_PA1;
state_t state_PA3 = IDLE_STATE;
unsigned short count_PA3;
state_t state_PA7 = IDLE_STATE;
unsigned short count_PA7;


extern BOOL   GotSUD;         // Received setup data flag
extern BOOL   Sleep;
extern BOOL   Rwuen;
extern BOOL   Selfpwr;


enum {
    High_Alt0_BulkIN = 0,
    High_Alt1_IsocTripleIN,
    High_Alt2_IsocIN
};


enum {
    Full_Alt0_BulkIN = 0,
    Full_Alt1_IsocIN
};


BYTE    Configuration;      // Current configuration
BYTE    AlternateSetting = High_Alt0_BulkIN;   // Alternate settings


void Slave_Fifo_Init(void)
{
PA0 = 0;
PA1 = 0; // TRIG (active high)
PA3 = 0; // PWDN (active high)
PA7 = 0; // FSIN (active high)


/* 1. Configure bits IFCONFIG[7:4] to define the behavior of the interface clock. */
// IFCONFIG
// bit7 : IFCLKSRC(0 -> exernal clock, 1 -> internal clock)
// bit6 : 3048MHZ(0 -> 30Mhz, 1 -> 48Mhz)
// bit5 : IFCLKOE(0 -> disable, 1-> enable internal clock output)
// bit4 : IFCLKPOL(invert external or internal clock)
// bit3 : ASYNC(0 -> synchronous, 1 -> asynchronous)
// bit2 : GSTATE(0 -> disable GSTATE, 1-> enable GSTATE)
// bit1 : IFCFG[1:0] (0b00: ports, 0b01: reserved, 0b10: GPIF, 0b11: Slave fifo)
// bit0 : 
IFCONFIG = b01010000; // ext, 48Mhz, disable OE, invert, synchronous, disable GSTATE, ports
//IFCONFIG = b11110000; // int, 48Mhz, enable OE, invert, synchronous, disable GSTATE, ports
// SYNCDELAY;


/* 2. Set bits IFCFG1:0=11. */
IFCONFIG |= b00000011;
SYNCDELAY;


/* 3. Set REVCTL.0 and REVCTL.1 to 1. */
REVCTL = 0x03;
SYNCDELAY;


/* 4. Configure EPxCFG. */
// Default interface uses endpoint 2, zero the valid bit on all others
// Just using endpoint 2, zero the valid bit on all others
EP1OUTCFG = 0xA0; //bmVALID | bmBULK;
SYNCDELAY;
EP1INCFG = 0xA0; //bmVALID | bmBULK;
SYNCDELAY;
// EPxCFG
EP2CFG = 0xE0;  //bmVALID | bmIN | bmBULK; //EP2 is DIR=IN, TYPE=BULK, SIZE=512, BUF=4x
SYNCDELAY;
EP4CFG = (EP4CFG & 0x7F); //non-valid
SYNCDELAY;
EP6CFG = (EP6CFG & 0x7F); //non-valid
SYNCDELAY;
EP8CFG = (EP8CFG & 0x7F); //non-valid
SYNCDELAY;


// EPxFIFOCFG
// bit7 : reserved
// bit6 : INFM1(IN Full Minus One)
// bit5 : OEP2(OUT Empty Plus One)
// bit4 : AUTOOUT
// bit3 : AUTOIN
// bit2 : ZEROLENIN(Enable Zero-length IN Packets)
// bit1 : reserved
// bit0 : WORDWIDE(Select Byte/Word FIFOs on PORTB/D Pins)
EP2FIFOCFG = 0x01;
//EP2FIFOCFG = 0x00; // 8bit FD
SYNCDELAY;
EP4FIFOCFG = 0x00;
SYNCDELAY;
EP6FIFOCFG = 0x00;
SYNCDELAY;
EP8FIFOCFG = 0x00;
SYNCDELAY;


PINFLAGSAB = 0x00;   // defines FLAGA as prog-level flag, pointed to by FIFOADR[1:0]
SYNCDELAY;           // FLAGB as full flag, as pointed to by FIFOADR[1:0]
PINFLAGSCD = 0x00;   // FLAGC as empty flag, as pointed to by FIFOADR[1:0]
SYNCDELAY;           // won't generally need FLAGD


/* 5. Reset the FIFOs. */
FIFORESET = 0x80;             // activate NAK-ALL to avoid race conditions
SYNCDELAY;                    // 
FIFORESET = 0x02;             // reset, FIFO 2
SYNCDELAY;                    // 
FIFORESET = 0x00;             // deactivate NAK-ALL
SYNCDELAY;                    // 


/* 6. Set bit EPxFIFOCFG.3=1. */
EP2FIFOCFG |= 0x08; // AUTOIN


/* 7. Set the size via the EPxAUTOINLENH:L registers. */
// this is the length for high speed
EP2AUTOINLENH = MSB(512);
SYNCDELAY;
EP2AUTOINLENL = LSB(512);
SYNCDELAY;


// FLAGA asserts when current fifo is at or less than 3pkts+508
EP2FIFOPFH = 0x19; // DECIS=0, PKTSTAT=0, PKTS[2]=0, PKTS[1]=1, PKTS[0]=1, 0, 0, PFC[8]=1
SYNCDELAY;
EP2FIFOPFL = 0xfc; // PFC[7:0] = 0b11111100
SYNCDELAY;


// Reset data toggle to 0
TOGCTL = 0x12;  // EP2 IN
TOGCTL = 0x32;  // EP2 IN Reset

// We want to get SOF interrupts
USBIE |= bmSOF;
}


//-----------------------------------------------------------------------------
// Task Dispatcher hooks
//   The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------
void TD_Init(void)             // Called once at startup
{
WORD i;
// when IFCFG[1:0] = 0b11,
// FIFOADR[1:0], PKTEND, and SLOE are automatically configured
// for PORTA(IO PORTA Alternate Configuration)
// PA.7(PORTACFG.7=0, PORTACFG.6=0) as FSIN pin
// PA.1(PORTACFG.1=0) as TRIG pin
// PA.0(PORTACFG.0=0) as RESET pin 
PORTACFG = 0;


// PA.3(WU2EN=0) as PWDN pin
WAKEUPCS &= ~0x02; // WU2EN=0
OEA = 0x08b; // Input FIFOADR[0:1], PKTEND, SLOE, OUTPUT(PA0, PA1, PA3)
//OEA = 0x03; // Input FIFOADR[0:1], PKTEND, PA3, OUTPUT(PA0, PA1)


IOA = 0x00; // pull up off
PA0 = 1; // RESET (active high)
for (i = 0; i < 200; i++);
PA0 = 0;


PA1 = 0; // TRIG (active high)
PA3 = 0; // PWDN (active high)
PA7 = 0; // FSIN (active high)

// When IFCFG.1 = 1
// PB[0:7] is configured as FD[0:7]
OEB = 0; // Input as FD[0:7]
IOB = 0;

// When IFCFG.1 = 1 and any WORDWIDE bit = 1
// PD[0:7] is configured as FD[8:15]
OED = 0; // Input as FD[8:15]
IOD = 0;


PORTECFG = 0x03; // needs to be set GSTATE to zero
OEE = 0x03; // IFCLK, CLKOUT
IOE = 0;


// set the CPU clock to 48MHz
// CPUCS
// bit7 :
// bit6 :
// bit5 : PORTCSTB (0 -> disable, 1-> enable RD#/WR# strobes of PORTC)
// bit4 : CLKSPD1
// bit3 : CLKSPD0 (00 -> 12Mhz, 01 -> 24Mhz, 10 -> 48Mhz, 11 -> x)
// bit2 : CLKINV (0 -> disable, 1 -> enable inverting CLKOUT)
// bit1 : CLKOE (0 -> disable, 1 -> enable CLKOUT signal)
// bit0 : 8051RES (1 -> reset 8051)
//CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1 | bmCLKOE);
CPUCS = 0x12;
SYNCDELAY;


Slave_Fifo_Init();
// EZUSB_InitI2C(); // Initialize EZ-USB I2C controller
// counter0_init();
}


/*
*/
void TD_Poll(void)             // Called repeatedly while the device is idle
{


switch (state_PA0) {
case IDLE_STATE: break;
case ON_STATE:
PA0 = 1;
count_PA0 = counter0_get();
state_PA0 = AUTO_INV_STATE;
break;
case OFF_STATE:
PA0 = 0;
count_PA0 = counter0_get();
state_PA0 = AUTO_INV_STATE;
break;
case AUTO_INV_STATE:
if ((((DWORD)counter0_get() - (DWORD)count_PA0 + 0x10000) % 0x10000) >= BLINK_COUNT) {
PA0 ^= 1;
state_PA0 = IDLE_STATE;
Slave_Fifo_Init();
}
break;
}


switch (state_PA1) {
case IDLE_STATE: break;
case ON_STATE:
PA1 = 1;
count_PA1 = counter0_get();
state_PA1 = AUTO_INV_STATE;
break;
case OFF_STATE:
PA1 = 0;
count_PA1 = counter0_get();
state_PA1 = AUTO_INV_STATE;
break;
case AUTO_INV_STATE:
if ((((DWORD)counter0_get() - (DWORD)count_PA1 + 0x10000) % 0x10000) >= BLINK_COUNT) {
PA1 ^= 1;
state_PA1 = IDLE_STATE;
}
break;
}


switch (state_PA3) {
case IDLE_STATE: break;
case ON_STATE:
PA3 = 1;
count_PA3 = counter0_get();
state_PA3 = AUTO_INV_STATE;
break;
case OFF_STATE:
PA3 = 0;
count_PA3 = counter0_get();
state_PA3 = AUTO_INV_STATE;
break;
case AUTO_INV_STATE:
if ((((DWORD)counter0_get() - (DWORD)count_PA3 + 0x10000) % 0x10000) >= BLINK_COUNT) {
PA3 ^= 1;
state_PA3 = IDLE_STATE;
}
break;
}


switch (state_PA7) {
case IDLE_STATE: break;
case ON_STATE:
PA7 = 1;
count_PA7 = counter0_get();
state_PA7 = AUTO_INV_STATE;
break;
case OFF_STATE:
PA7 = 0;
count_PA7 = counter0_get();
state_PA7 = AUTO_INV_STATE;
break;
case AUTO_INV_STATE:
if ((((DWORD)counter0_get() - (DWORD)count_PA7 + 0x10000) % 0x10000) >= BLINK_COUNT) {
PA7 ^= 1;
state_PA7 = IDLE_STATE;
}
break;
}
}


BOOL TD_Suspend(void)          // Called before the device goes into suspend mode
{
return(TRUE);
}


BOOL TD_Resume(void)          // Called after the device resumes
{
return(TRUE);
}


//-----------------------------------------------------------------------------
// Device Request hooks
//   The following hooks are called by the end point 0 device request parser.
//-----------------------------------------------------------------------------


BOOL DR_GetDescriptor(void)
{
return(TRUE);
}


BOOL DR_SetConfiguration(void)   // Called when a Set Configuration command is received
{
Configuration = SETUPDAT[2];
return(TRUE);            // Handled by user code
}


BOOL DR_GetConfiguration(void)   // Called when a Get Configuration command is received
{
EP0BUF[0] = Configuration;
EP0BCH = 0;
EP0BCL = 1;
return(TRUE);            // Handled by user code
}


BOOL DR_SetInterface(void)       // Called when a Set Interface command is received
{
BYTE updateDisplay = TRUE;
AlternateSetting = SETUPDAT[2];


// ...FX2 in high speed mode
if (EZUSB_HIGHSPEED()) {
// Change configuration based upon the Alt. Interface selected
switch (AlternateSetting) {
case High_Alt0_BulkIN:
EP2CFG = 0xE0; //bmVALID | bmIN | bmBULK; // EP2 is DIR=IN, TYPE=BULK, SIZE=512, BUF=4x
SYNCDELAY;
// Clear out any committed packets
FIFORESET = 0x80;
SYNCDELAY;
FIFORESET = 0x02;
SYNCDELAY;
FIFORESET = 0x00;
SYNCDELAY;
// this is the length for high speed
EP2AUTOINLENH = MSB(512);
SYNCDELAY;
EP2AUTOINLENL = LSB(512);
SYNCDELAY;
// Reset data toggle to 0
TOGCTL = 0x12;  // EP2 IN
TOGCTL = 0x32;  // EP2 IN Reset
       break;
case High_Alt1_IsocTripleIN:
// Only using endpoint 2, zero the valid bit on all others
EP2CFG = 0xD8; //bmVALID | bmIN | bmISOC | bm1024 | bmQUAD // EP2 is DIR=IN, TYPE=ISOC, SIZE=1024, BUF=4x
SYNCDELAY;
// Clear out any committed packets
FIFORESET = 0x80;
SYNCDELAY;
FIFORESET = 0x02;
SYNCDELAY;
FIFORESET = 0x00;
SYNCDELAY;
// this is the length for high speed
EP2AUTOINLENH = MSB(1024);
SYNCDELAY;
EP2AUTOINLENL = LSB(1024);
SYNCDELAY;
// This register sets the number of Isoc packets to send per
// uFrame.  This register is only valid in high speed.
EP2ISOINPKTS = 0x03;
       break;
        case High_Alt2_IsocIN:
EP2CFG = 0xD8; //bmVALID | bmIN | bmISOC | bm1024 | bmQUAD // EP2 is DIR=IN, TYPE=ISOC, SIZE=1024, BUF=4x
SYNCDELAY;
// Clear out any committed packets
FIFORESET = 0x80;
SYNCDELAY;
FIFORESET = 0x02;
SYNCDELAY;
FIFORESET = 0x00;
SYNCDELAY;
// this is the length for high speed
EP2AUTOINLENH = MSB(1024);
SYNCDELAY;
EP2AUTOINLENL = LSB(1024);
SYNCDELAY;
// This register sets the number of Isoc packets to send per
// uFrame.  This register is only valid in high speed.
EP2ISOINPKTS = 0x01;
       break;
}
} else {
// Change configuration based upon the Alt. Interface selected
switch (AlternateSetting) {
case Full_Alt0_BulkIN:
EP2CFG = 0xE0; //bmVALID | bmIN | bmBULK; // EP2 is DIR=IN, TYPE=BULK, SIZE=512, BUF=4x
            SYNCDELAY;
// Clear out any committed packets
            FIFORESET = 0x80;
            SYNCDELAY;
            FIFORESET = 0x02;
            SYNCDELAY;
            FIFORESET = 0x00;
            SYNCDELAY;
// this is the length for high speed
EP2AUTOINLENH = MSB(512);
SYNCDELAY;
EP2AUTOINLENL = LSB(512);
SYNCDELAY;
            // Reset data toggle to 0
            TOGCTL = 0x12;  // EP2 IN
            TOGCTL = 0x32;  // EP2 IN Reset
break;
case Full_Alt1_IsocIN:
EP2CFG = 0xD8;  // EP2 is DIR=IN, TYPE=ISOC, SIZE=1024, BUF=4x
            SYNCDELAY;
// Clear out any committed packets
            FIFORESET = 0x80;
            SYNCDELAY;
            FIFORESET = 0x02;
            SYNCDELAY;
            FIFORESET = 0x00;
            SYNCDELAY;
// this is the length for high speed
EP2AUTOINLENH = MSB(1023);
SYNCDELAY;
EP2AUTOINLENL = LSB(1023);
SYNCDELAY;
            // This register sets the number of Isoc packets to send per
            // uFrame.  This register is only valid in high speed.
            EP2ISOINPKTS = 0x01;
break;
}
}
return(TRUE);            // Handled by user code
}


BOOL DR_GetInterface(void)       // Called when a Set Interface command is received
{
EP0BUF[0] = AlternateSetting;
EP0BCH = 0;
EP0BCL = 1;
return(TRUE);            // Handled by user code
}


BOOL DR_GetStatus(void)
{
return(TRUE);
}


BOOL DR_ClearFeature(void)
{
return(TRUE);
}


BOOL DR_SetFeature(void)
{
return(TRUE);
}


#include "../commands.h"


#define bRequestType    SETUPDAT[0] 
#define bRequest        SETUPDAT[1] 
#define wValueL         SETUPDAT[2] 
#define wValueH         SETUPDAT[3] 
#define wIndexL         SETUPDAT[4] 
#define wIndexH         SETUPDAT[5] 
#define wLengthL        SETUPDAT[6] 
#define wLengthH        SETUPDAT[7] 


BOOL DR_VendorCmnd(void)
{
BYTE xdata i2c_id;
BYTE xdata tmp[2];


switch (bRequest) {
case VRQ_GET_STATUS:
EP0BUF[0] = IFCONFIG;
SYNCDELAY;
EP0BCH = 0;
EP0BCL = 1;
EP0CS |= bmHSNAK;
break;
case VRQ_PA0_CTRL:
if (state_PA0 != IDLE_STATE)
break;
#if 0
// Clear out any committed packets
            FIFORESET = 0x80;
            SYNCDELAY;
            FIFORESET = 0x02;
            SYNCDELAY;
            FIFORESET = 0x00;
            SYNCDELAY;


// Reset data toggle to 0
TOGCTL = 0x12;  // EP2 IN
TOGCTL = 0x32;  // EP2 IN Reset
#endif


if (wIndexL) {
if (wValueL) PA0 = 1;
else PA0 = 0;
} else {
if (wValueL) state_PA0 = ON_STATE;
else state_PA0 = OFF_STATE;
}
break;
case VRQ_PA1_CTRL:
if (state_PA1 != IDLE_STATE)
break;
if (wIndexL) {
if (wValueL) PA1 = 1;
else PA1 = 0;
} else {
if (wValueL) state_PA1 = ON_STATE;
else state_PA1 = OFF_STATE;
}
break;
case VRQ_PA3_CTRL:
if (state_PA3 != IDLE_STATE)
break;
if (wIndexL) {
if (wValueL) PA3 = 1;
else PA3 = 0;
} else {
if (wValueL) state_PA3 = ON_STATE;
else state_PA3 = OFF_STATE;
}
break;
case VRQ_PA7_CTRL:
if (state_PA7 != IDLE_STATE)
break;
if (wIndexL) {
if (wValueL) PA7 = 1;
else PA7 = 0;
} else {
if (wValueL) state_PA7 = ON_STATE;
else state_PA7 = OFF_STATE;
}
break;
case VRQ_I2C_WRITE:
i2c_id = wIndexL;
tmp[0] = wValueL;
if (EZUSB_WriteI2C(i2c_id, 1, &(tmp[0])) != I2C_OK) return TRUE;
//EZUSB_WriteI2C(i2c_id, 2, &(tmp[0]));
EZUSB_WaitForEEPROMWrite(i2c_id);
break;
case VRQ_I2C_READ:
//IOA ^= 0x04;
i2c_id = wIndexL;


if (EZUSB_ReadI2C(i2c_id, 1, &(tmp[0])) != I2C_OK) return TRUE;
EZUSB_WaitForEEPROMWrite(i2c_id);


EP0BUF[0] = (BYTE)(wIndexL);
EP0BUF[1] = (BYTE)(tmp[0]);
EP0BCL = 0x02;
break;
case VRQ_I2C_WRITE_REG:
i2c_id = wIndexL;
tmp[0] = wValueH;
tmp[1] = wValueL;
if (EZUSB_WriteI2C(i2c_id, 2, &(tmp[0])) != I2C_OK) return TRUE;
//EZUSB_WriteI2C(i2c_id, 2, &(tmp[0]));
EZUSB_WaitForEEPROMWrite(i2c_id);
break;
case VRQ_I2C_READ_REG:
//IOA ^= 0x04;
i2c_id = wIndexL;
tmp[0] = wValueH;
if (EZUSB_WriteI2C(i2c_id, 1, &(tmp[0])) != I2C_OK) return TRUE;
EZUSB_WaitForEEPROMWrite(i2c_id);
if (EZUSB_ReadI2C(i2c_id, 1, &(tmp[0])) != I2C_OK) return TRUE;
EZUSB_WaitForEEPROMWrite(i2c_id);


EP0BUF[0] = (BYTE)(wIndexL);
EP0BUF[1] = (BYTE)(wValueH);
EP0BUF[2] = (BYTE)(tmp[0]);
EP0BUF[3] = (BYTE)(0xff);


EP0BCL = 0x04;
//EP0CS |= bmHSNAK;
// EP0BUF[0] = tmp[0];
// SYNCDELAY;
// EP0BCH = 0;
// EP0BCL = 1;
// EP0CS |= bmHSNAK;
//EP1INBUF[0] = tmp[0]; SYNCDELAY;
// EP1INBC = 1; SYNCDELAY; // arm EP6IN
break;
default: return TRUE;
}


return FALSE;
}


//-----------------------------------------------------------------------------
// USB Interrupt Handlers
//   The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------


// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
GotSUD = TRUE;            // Set flag
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUDAV;         // Clear SUDAV IRQ
}


// Setup Token Interrupt Handler
void ISR_Sutok(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUTOK;         // Clear SUTOK IRQ
}


void ISR_Sof(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmSOF;            // Clear SOF IRQ
}


void ISR_Ures(void) interrupt 0
{
// Whenever we get a USB Reset, we should revert to full speed mode
pConfigDscr = pFullSpeedConfigDscr;
((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
pOtherConfigDscr = pHighSpeedConfigDscr;
((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;

EZUSB_IRQ_CLEAR();
USBIRQ = bmURES;         // Clear URES IRQ
#if 0
if (EZUSB_HIGHSPEED()) {
pConfigDscr = pHighSpeedConfigDscr;
pOtherConfigDscr = pFullSpeedConfigDscr;
} else {
pConfigDscr = pFullSpeedConfigDscr;
pOtherConfigDscr = pHighSpeedConfigDscr;
}

EZUSB_IRQ_CLEAR();
USBIRQ = bmURES;         // Clear URES IRQ
#endif
}


void ISR_Susp(void) interrupt 0
{
Sleep = TRUE;
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUSP;
}


void ISR_Highspeed(void) interrupt 0
{
if (EZUSB_HIGHSPEED()) {
pConfigDscr = pHighSpeedConfigDscr;
((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
pOtherConfigDscr = pFullSpeedConfigDscr;
((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
// This register sets the number of Isoc packets to send per
// uFrame.  This register is only valid in high speed.
EP2ISOINPKTS = 0x03;
} else {
pConfigDscr = pFullSpeedConfigDscr;
pOtherConfigDscr = pHighSpeedConfigDscr;
}


EZUSB_IRQ_CLEAR();
USBIRQ = bmHSGRANT;
#if 0
if (EZUSB_HIGHSPEED()) {
pConfigDscr = pHighSpeedConfigDscr;
pOtherConfigDscr = pFullSpeedConfigDscr;
// This register sets the number of Isoc packets to send per
// uFrame.  This register is only valid in high speed.
EP2ISOINPKTS = 0x03;
} else {
pConfigDscr = pFullSpeedConfigDscr;
pOtherConfigDscr = pHighSpeedConfigDscr;
}

EZUSB_IRQ_CLEAR();
USBIRQ = bmHSGRANT;
#endif
}


void ISR_Ep0ack(void) interrupt 0
{
}
void ISR_Stub(void) interrupt 0
{
}
void ISR_Ep0in(void) interrupt 0
{
}
void ISR_Ep0out(void) interrupt 0
{
}
void ISR_Ep1in(void) interrupt 0
{
}
void ISR_Ep1out(void) interrupt 0
{
}


// ISR_Ep2inout is called on every OUT packet receieved.
// We don't do anything with the data.  We just indicate we are done with the buffer.
void ISR_Ep2inout(void) interrupt 0
{
    // Perform USB activity based upon the Alt. Interface selected 
/*
     switch (AlternateSetting)
    {
        case Alt1_BulkOUT:
        case Alt4_IsocOUT:
           // check EP2 EMPTY(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is empty
            if(!(EP2468STAT & bmEP2EMPTY))
            { 
                EP2BCL = 0x80;          // re(arm) EP2OUT
            }
        break;


        case Alt2_BulkINOUT:
        case Alt6_IsocINOUT:
            // check EP6 EMPTY(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is empty
            if(!(EP2468STAT & bmEP6EMPTY))
            { 
                EP6BCL = 0x80;          // re(arm) EP6OUT
            }
        break;
   }
*/
}


void ISR_Ep4inout(void) interrupt 0
{
}
void ISR_Ep6inout(void) interrupt 0
{
}
void ISR_Ep8inout(void) interrupt 0
{
}
void ISR_Ibn(void) interrupt 0
{
}
void ISR_Ep0pingnak(void) interrupt 0
{
}
void ISR_Ep1pingnak(void) interrupt 0
{
}
void ISR_Ep2pingnak(void) interrupt 0
{
}
void ISR_Ep4pingnak(void) interrupt 0
{
}
void ISR_Ep6pingnak(void) interrupt 0
{
}
void ISR_Ep8pingnak(void) interrupt 0
{
}
void ISR_Errorlimit(void) interrupt 0
{
}
void ISR_Ep2piderror(void) interrupt 0
{
}
void ISR_Ep4piderror(void) interrupt 0
{
}
void ISR_Ep6piderror(void) interrupt 0
{
}
void ISR_Ep8piderror(void) interrupt 0
{
}
void ISR_Ep2pflag(void) interrupt 0
{
}
void ISR_Ep4pflag(void) interrupt 0
{
}
void ISR_Ep6pflag(void) interrupt 0
{
}
void ISR_Ep8pflag(void) interrupt 0
{
}
void ISR_Ep2eflag(void) interrupt 0
{
}
void ISR_Ep4eflag(void) interrupt 0
{
}
void ISR_Ep6eflag(void) interrupt 0
{
}
void ISR_Ep8eflag(void) interrupt 0
{
}
void ISR_Ep2fflag(void) interrupt 0
{
}
void ISR_Ep4fflag(void) interrupt 0
{
}
void ISR_Ep6fflag(void) interrupt 0
{
}
void ISR_Ep8fflag(void) interrupt 0
{
}
void ISR_GpifComplete(void) interrupt 0
{
}
void ISR_GpifWaveform(void) interrupt 0
{
}


PC-based Software

USB driver is from open source libusb-win32, and application is written in Visual C++ 6.0. Its source code is so big to list. To access them, please leave a message.

Result

This is grepped image in PC-monitor.