'2008/06'에 해당되는 글 6건

  1. 2008/06/26 [C언어] #define이 필요한 이유
  2. 2008/06/26 [AVR] 외부장치 접근 메커니즘
  3. 2008/06/23 [AVR] 타이머 인터럽트
  4. 2008/06/18 만만치않은 UI 프로그래밍 (4)
  5. 2008/06/18 [액션스크립트 + UI] 다이얼로그 설계
  6. 2008/06/09 [프로그래밍] 변수이름만 잘지어도 50%는 먹고 들어간다 (3)
2008/06/26 18:41

[C언어] #define이 필요한 이유

대부분의 C언어책에서

define은 "단순 치환"의 기능을 가졌다고한다.

예를들어

#define PI 3.14

즉 PI 가 3.14를 가리킨다는 것이다.

물론 맞는 말이다. 하지만 define이 존재하는 근본적인 이유가 몇가지 있다.

1. RAM 의 메모리에 할당되지 않는다.

    int a = 1;
    이 코드 한줄이 실제로 어떻게수행되는지 보자.
    1) 램영역에 4바이트의 메모리가 할당된다.
    2) CPU는 이 할당된 영역에 0000 0000 0000 0000 0000 0000 0000 0001 이라는 데이타를 써넣는다.

   #define a = 1;
   하지만 이렇게 #define을 사용한다면 램영역에 메모리 할당은 없다.
   코드내의 a 는 1이라는 상수값으로 치환되어 컴파일 되는것이다.

   요약하면,
    전자는 메모리 할당이 일어나는 반면에, 후자는 메모리할당이 일어나지않는다.컴파일타임에 상수로 취급되어     버리기때문이다.

define을 썼을때의 장점이 느껴지는가?
1. 메모리 절약
2. 코드의 가독성 증가.

하지만 조금이라도 값이 바뀔 가능성이 존재한다면 define을 사용해서는 절대로 안된다.
물론 컴파일도 안될것이다.
define은 단지 상수를 위해 존재한다.

이올린에 북마크하기(0) 이올린에 추천하기(0)
Trackback 0 Comment 0
2008/06/26 18:26

[AVR] 외부장치 접근 메커니즘

LCD 모듈을 에로들어보자.
LCD 는 AVR 입장에서볼때 외부 I/O 장치이다.
즉 LCD 모듈에 접근하려면 어드레스버스데이타버스가 필요하다는 것이다.

AVR에서는 A0 ~ A15 까지(총 16개의 비트)를 어드레스 버스로 사용하고있다.
A0~A7 은 데이타버스로도 사용된다.

8비트 프로세서에서 어드레스버스가 16비트나 되는 이유가뭘까?
내생각으로는, 확장성을 위해서인것 같다. 어드레스 버스가 8비트밖에 되지않는다면
접근할수 있는 주소가 256개 밖에 되지않을것이다. 그러나 16비트라면 65536 개의 주소에 접근할 수 있다.
그만큼 외부 장치를 많이 연결할 수 있다는 말이다.

이 어드레스버스에 주소값을 넣으면 디코딩 회로는 이 주소값을 해석해서 하드웨어적으로 이 주소에 해당하는곳
을 활성화 시킨다. 이제 데이타버스는 이 활성화된 영역에 데이타를 쓰고, 읽을수가 있게된것이다.

이 메커니즘은 일반 PC 에서 CPU가 RAM 영역에 접근할때도 사용된다.
메모리의 주소값을 담은 어드레스버스가 디코딩회로에 의해 해석되면 데이타버스가 그 주소로 이동하고
이제 이 데이타버스에 데이타를 써넣으면 램에 데이타가 써지는 것이다.

이올린에 북마크하기(0) 이올린에 추천하기(0)
Trackback 0 Comment 0
2008/06/23 17:25

[AVR] 타이머 인터럽트

/* 이글은 걍 개인적으로 공부하면서 한번더 이해하기 위해 쓴글이니 설명이 난해하다고 뭐라하지마세요 ㅜ.ㅜ */

타이머는 avr 칩 내부에서 동작하는 넘이다. 그래서 i/o 포트와는 관련이 없음

Atmega128 에는 타이머가 총 4개가 존재한다.

타이머0 ,타이머1, 타이머2, 타이머3

이렇게 있는데, 타이머0, 타이머2는 8비트짜리고 타이머1, 타이머3은 16비트 짜리다.

여기서 비트가 의미하는건 최대 카운트 수이다.

8비트는 256까지 나타낼수 있으므로

타이머가 256까지 카운트를 세었을때 "타이머 오버플로우 인터럽트"가 발생하는것이고

16비트는  65536 까지 나타낼수 있으므로

타이머가 65536 까지 카운트를 세었을때 "타이머 오버플로우 인터럽트"가 발생하는 것이다.

타이머 인터럽트를 사용하기전에 설정해야할 레지스터들이 몇개있다

1. TCCR (Timer/Counter Control Register)
   카운터가 발생하는주기(프리스케일러 라고함) 를 설정할 뿐만 아니라 카운터의 전반적인것에 대해서 설정할 수 있다. 자세하게 들어가면 골치아프므로(나도 자세히는모름) 가장 많이쓰이는 프리스케일러 설정만 살펴보자

타이머1 에 대한 Control TCCR은 3개나 존재하더라..
TCCR1A, TCCR1B, TCCR1C (A,B,C 를 접미어로 붙여서 구분하는듯)

/* Timer1의 Compare 인터럽트 설정하는 레지스터인데 지금하는건
Timer Overflow 관련부분이니까 패스. 즉 0x00 으로 셋팅함으로써 사용안함을 명시. */
TCCR1A = 0x00;

/*
TCCR1B 하위 3비트(0비트, 1비트, 2비트)에서 프리스케일러를 설정한다.
1을 왼쪽으로 3번 비트연산한다는뜻. (CS12가 3을 나타내는듯함)
데이타시트 찾아보니까 100(2) 은 64 clk 를 나타내네. 즉 64 클록당 카운트 한개 증가시킨다는 소리.
64클록마다 카운트 한개씩 증가시켜서 타이머카운트 레지스터(TCNT1)값이 65536이 되었을때 인터럽트
발생함. 대략 몇 ms 걸릴까? 계산하기 귀찮다 -_-;
*/
TCCR1B = 1 << CS12;

/*
  이 레지스터도 0x00으로 셋팅해서 사용안함을 명시.
*/
TCCR1C = 0x00;

타이머1의 전반적인 설정을 끝냈으니

이제 타이머1 인터럽트를 인에이블(사용가능하게) 설정해야한다.

이것을 담당하는 레지스터는 TIMSK(Timer Interrupt Mask) 이다.

TIMSK = 1 << TOIE1;

이렇게 해주면 타이머1의 "타이머 오버플로우 인터럽트"가 인에이블 상태로된다.

참고로 TOIE는 Timer Overflow Interrupt Enable 의 약자이다.
이 TOIE1 비트는 TIMSK 레지스터의 하위 3번째 비트(비트번호 2)에 위치하고있다. 그래서
1 << TOIE1 하면 0000 0100; 이라는 결과값이 나와서 TIMSK 레지스터의 TOIE1 비트에 1이 셋팅되는듯.

TIMSK 는 총 8비트로 이루어져있는데 OCIEx(Output Compare Interrupt Enable) 와 TOIEx  로구성되어있다. 컴페어 인터럽트는 아직 안써봤으므로 언급하지않겠다...

이제 TIMSK 까지 설정했으면 타이머 인터럽트를 동작시키기위한 셋팅은 거의 끝났다고 볼수있다

그러나 한가지 더 해줘야할것이 있다!

바로 SREG(맞나?) 라는 상태레지스터의 8번쨰비트인 I-플래그 를 1로 셋팅해줘야한다.
sei() 라는 함수를 호출해주면 내부적으로 셋팅이된다.

cli(); // 전역 I-플래그를 클리어한다. 0 으로 셋팅하는듯
sei(); //전역 I-플래그를 셋한다. 1로 셋팅하는듯

자 이제 여기까지했으면 타이머 인터럽트가 동작하기 위한 모든준비가 끝난것이다!

코드까지 쓰려고했지만...-_- 글이너무 길어질것 같아서 오늘은 여기까지..




 

이올린에 북마크하기(0) 이올린에 추천하기(0)
Trackback 0 Comment 0
2008/06/18 12:20

만만치않은 UI 프로그래밍

 
사용자 삽입 이미지

PMP에 들어갈 모듈중 하나인 "파일브라우저" 하나를 구현하는데 벌써 클래스만 20개가 다되간다.
앞으로 구현해야할 모듈이 6개는 더되는데...
그래도 일단 파일브라우저 하나는 어느정도 끝이보이는지라... 중간 작업물을 올려본다.
그리고.. 몇가지 골치아팠던 부분...

1. Native c/c++ 와 통신을 하는지라 동기화를 철저히 해야했다.
    Native c/c++ 에서 던져주는 데이타들이 이벤트 기반이기때문에(block방식이 아님) 동기화에 상당히 많은 신경을 써야했다. 객체의 라이프사이클을 철저하게 관리해서 이 난제를 극복했다. 즉, 객체의 초기화와 그 이후의 행동에 대해서 철저하게 분리하여 프로그래밍 하는것이다. 또한 각 기능별로 매니저 클래스를 둠으로써 코드들을 깔끔하게 분리할 수 있었다. CDialogMgr, CFbMgr이 매니저 클래스이다.
매니저 클래스에서는 주로 Native 함수를 호출하고, 데이타를 전달받아 스크립트단 버퍼에 채워넣는 일을 한다.
만약 이러한 코드들이 매니저클래스없이 한클래스안에 묶여져있었다면 코드가 난잡해져서 가독성이 현저하게
떨어졌을 것이다.

2. 스크롤바.
    파일브라우저에서 리스들은 페이지단위로 스크롤 되어야하기떄문에 스크롤바또한 이것에 맞춰져야했다.
"스냅"(딱딱 달라붙는 듯한효과)방식으로 스크롤바를 만들었다.리스트가 갱신될때마다 총 페이지수를 구한후
스크롤바의 reInit(numPages) 함수를 호출하여 스크롤바또한 리프레쉬를 시켜준다.
리스트의 총페이지 수만큼 스크롤바의 스냅 포지션의 수가 정해진다. 이 스냅포지션은 arrPos라는 배열에 할당되며 사용자가 스크롤할때마다 arrPos의 포지션값중 가장 가까운 값을 찾아 그 위치로 스냅하게된다.
스크롤이벤트가 발생되면 스크롤바는 이벤트를 발생시켜 파일브라우저 리스트에 타겟 페이지넘버를 넘겨준다.
파일브라우저는 넘겨받은 타겟 페이지넘버를 가지고 보여져야할 파일객체의 시작인덱스를 계산하여
스크립트단 버퍼에 접근하여 파일객체들을 배열형태로 가지고온후에 리스트화면에 렌더링한다.


이올린에 북마크하기(0) 이올린에 추천하기(0)
Trackback 0 Comment 4
2008/06/18 11:15

[액션스크립트 + UI] 다이얼로그 설계

다이얼로그 라는것은 현재 보고있는 VIEW 위에 새로운 레이어(윈도우)가 추가되는 것이다.

다이얼로그가 생성되면 아래있는 VIEW및 컨트롤들은 커맨드불능 상태로 만들어야한다

이 구현을 위해 전역변수를 사용했다.(액션스크립트에서 _global 키워드는 전역변수 스코프를 의미한다)

_global.isFadeOut = true; //다이얼로그가 떴을때.

_global.isFadeOut=false //다이얼로그를 닫았을때.

다이얼로그 하위 레이어의 컨트롤들에는 다음과같은 코드를 추가해야 한다.

if(_global.isFadeOut == true){

     return false;

}else{

// 커맨드 코드

}

이올린에 북마크하기(0) 이올린에 추천하기(0)
Trackback 0 Comment 0
2008/06/09 00:36

[프로그래밍] 변수이름만 잘지어도 50%는 먹고 들어간다

플밍 입문자 들이 하는 최대의 실수중 하나가

변수명을

aa

bb

이런식으로 짓는것이다.


변수명에는 항상 의미를 부여해야 된다.

변수명에 의미를 부여하면 코드가 읽기 쉬워지므로 개발속도 향상뿐만 아니라 리팩터링 에도 큰 이점이 생긴다.

1. 변수명에는 자료형을 나타내라.

int age;  -> int numAge;
int total; -> double numTotal;
String name -> strName
String name[] -> arrName;

어떠한가? 오른쪽이 더 직관적이지 않은가?

2. 전역변수는 항상 대문자로, 지역변수 앞에는 언더바를.

class Person{
    public static String NUM_TOTAL; // 전역변수("클래스변수"가 정확하지만, 일단은 "전역변수"라고 해두자.)
    public String strName; // 일반 변수(멤버변수)
    public String setName(String _strName){ //지역변수(함수 지역변수)
         this.strName = _strName;
    }
}
이올린에 북마크하기(0) 이올린에 추천하기(0)
Trackback 0 Comment 3