레이블이 Project인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Project인 게시물을 표시합니다. 모든 게시물 표시

2010년 5월 18일 화요일

Popup 노이즈


내 귀는 막귀라서 지금까지 popup 노이즈가 뭔지도 몰랐다.
마이크가 켜지는 소리라고 하는데-_-);;;;
디바이스가 켜지면서 팟!! 하고 나는 소리라고 한다.
얘기를 듣고 나서 들어보니까 그런 소리가 나는 것 같기도 하고... - _-);


이것을 처리하기 위한 방법은 두 가지가 있는데, 하나는 하드웨어적 다른 하나는 소프트웨어적인 방법이다.
하드웨어적인 방법은 간단하다.
마이크를 비싸고 좋은 걸 달아서 애초에 노이즈가 생기지 않게 하는 거다.
소프트웨어적인 방법은 마이크로 PCM 데이타가 들어올 때 처음 popup노이즈 부분을 제거하는 방법이다.
buffer의 일정 부분을 잘라버리든가 하는 방법으로..

처음에 이것을 처리할 때,
처음 popup노이즈 부분을 애초에 버퍼에 저장하지 않는 방법을 사용하려고 했지만,
프로세서가 수행되고 있지 않더라도 하위 버퍼에는 계속적으로 PCM 데이타가 들어오고 있으므로 소용이 없었다.
걍 buffer의 앞부분을 버리는게 방법.

2010년 5월 17일 월요일

라디오 주파수 수신 감도 조절


FM라디오 명령어 중에 seek라는 명령이 있는데,
이것이 하는 기능은 수신 가능한 채널을 자동으로 찾아주는 것이다.
device control 명령어로 수행되기에 하드웨어적으로 어떻게 처리되는지는 모르겠으나,
일단 입력값으로 값을 높게 주면 줄 수록 감도가 좋은 것을 받아온다.

즉, 입력값을 높은 값을 줄 수록 선명한 채널을 얻을 수 있지만,
수신 감도가 좋지 않은 채널에 대해서는 스킵 되므로 다양한 채널을 얻을 수 없게 될 수도 있다.
그렇다고 해서 입력값을 너무 작은 숫자를 주면,
다양한 채널을 얻을 수 있지만, 그 중에 청취 가능하지 않은 채널들이 많이 섞일 수 있다.

그래서 적절한 입력 값을 주는 것이 중요한데, 이것은 반복 테스트를 통해서 가능하다. (노가다-_-)

결국 16~17개의 채널을 찾아내는 값으로 설정했다.
여기서 좀 더 높이면 107.7을 잡지 못하길래.. -_-);

2010년 3월 4일 목요일

Wave file 만들기 (2)


mmio 함수들을 이용하여 만들기 귀찮다면, 이전 포스팅을 참고 하시길.

HMMIO hMmio = NULL;
MMCKINFO wavChunk;
MMCKINFO wavSubChunk;
//mm chunk 정보를 저장하기 위한 구조체 변수

MMRESULT mmResult;

WAVEFORMATEX WaveFormat;
WaveFormat.wFormatTag=WAVE_FORMAT_PCM;
WaveFormat.nChannels = 2;
WaveFormat.nSamplesPerSec = 11025;
WaveFormat.wBitsPerSample = 8;
WaveFormat.nBlockAlign = WaveFormat.nChannels*(WaveFormat.wBitsPerSample/8);
WaveFormat.nAvgBytesPerSec = WaveFormat.nSamplesPerSec*WaveFormat.nBlockAlign;
WaveFormat.cbSize = 0;
//Wave file format을 저장하는 구조체를 선언하고 알맞은 값으로 초기화.
//이 구조체에 대해서는 wave file header를 참고

hMmio = mmioOpen(L"test.wav", NULL,
MMIO_CREATE | MMIO_WRITE | MMIO_EXCLUSIVE |
MMIO_ALLOCBUF | MMIO_EXIST);
//MMIO handle을 받아온다.

if(hMmio == NULL) // 에러 처리 { RETAILMSG(1, (TEXT("fail create wave file\r\n"))); return false; }

ZeroMemory(&wavChunk, sizeof(wavChunk)); //메모리 초기화 wavChunk.fccType = mmioFOURCC('W','A','V','E'); //chunk 정보 입력 mmResult = mmioCreateChunk(hMmio, &wavChunk, MMIO_CREATERIFF); //chunk 생성

if(mmResult != MMSYSERR_NOERROR) // 에러 처리
{ RETAILMSG(1, (TEXT("error mmioCreateChunk (WAVE)\r\n"))); return false; }

//sub chunk 생성
ZeroMemory(&wavSubChunk, sizeof(wavSubChunk)); wavSubChunk.ckid = mmioFOURCC('f','m','t',' '); wavSubChunk.cksize = sizeof(WAVEFORMATEX) + WaveFormat.cbSize; mmResult = mmioCreateChunk(hMmio, &wavSubChunk, 0);
if(mmResult != MMSYSERR_NOERROR) // 에러 처리
{ RETAILMSG(1, (TEXT("error mmioCreateChunk (FMT)\r\n"))); return false; } mmResult = mmioWrite(hMmio, (char*)&WaveFormat, sizeof(WAVEFORMATEX)
+ WaveFormat.cbSize); if(mmResult != MMSYSERR_NOERROR) // 에러 처리
{ RETAILMSG(1, (TEXT("error mmioWrite\r\n"))); return false; } mmResult = mmioAscend(hMmio, &wavSubChunk, 0); if(mmResult != MMSYSERR_NOERROR) // 에러 처리
{ RETAILMSG(1, (TEXT("error mmioAscend\r\n"))); return false; } wavSubChunk.ckid = mmioFOURCC('d','a','t','a'); mmResult = mmioCreateChunk(hMmio, &wavSubChunk, 0); if(mmResult != MMSYSERR_NOERROR) // 에러 처리
{ RETAILMSG(1, (TEXT("error mmioCreateChunk (DATA)\r\n"))); return false; }

DWORD len = 0; len = mmipWrite(hMmio, pBuffer, BUFFERSIZE);  //data를 쓴다.
if(len <= 0) { RETAILMSG(1, (TEXT("error WRITE \r\n"))); return false; }

mmioClose(hMmio,0); //handle close



mmio 함수는 winCE에서는 지원하지 않으며, winmm.dll과 winmm.lib를 포함시켜 주어야 한다.

2010년 2월 26일 금요일

Wave file format

wave file format

offset

size(byte)

field

0

4

"RIFF" or "LIST"

4

4

file size (data size + 40)

8

4

"WAVE"

12

4

"fmr "

16

4

16

20

2

WAVE_FORMAT_PCM

22

2

1 = mono, 2 = strereo

24

4

sample rate

(11kHz: 11025, 22kHz: 22025, 44kHz: 44100)

28

4

bytes per sec

sample rate * channel * (bits per sample/8)

30

2

block align

channel * (bits per sample/8)

32

2

bits per sample (8, 16, ...)

36

4

"data"

40

4

data size


2010년 2월 25일 목요일

Wave file 만들기

winCE에서 winmm.lib를 쓸 수 없는 관계로,, mmio 함수들을 하나도 쓰지 못하고.ㅠㅜ
결국엔 wave file을 손수 만들어 주어야 하는 귀찮음에 봉착하였다.

wave file header 구조에 따라 다음과 같은 구조체를 선언한다.

typedef struct
{
           FOURCC ckID; // 'RIFF'인지 'LIST'인지 넣어준다.
           DWORD dwFileSize; // 전체 file크기 저장 (data크기 + 40)
           FOURCC fccType; // 'WAVE'
           FOURCC subckID; // 'fmr '
           DWORD dwSubChunkSize; // 16
           WORD wFormatTag; // WAVE_FORMAT_PCM
           WORD nChannels; // 1 = mono, 2 = stereo
           DWORD nSamplesPerSec; // 11025, 22050 등등등
           DWORD wBitsPerSample; // 8, 16, 등등등
           WORD nBlockAlign; // nChannels * wBitsPerSample/8
           WORD nAvgBytesPerSec; // nChannels * wBitsPerSample/8 * nSamplesPerSec
           FOURCC datackID; // 'data'
           DWORD dwDataSize; // data크기
} WaveFormChunk;


그리고 이 구조체에 대한 변수를 하나 선언하여 알맞은 값을 넣어주고,
파일의 맨 앞부분에 write한다.

WaveFormChunk WaveHeader;
WaveHeader.ckID = FOURCC_RIFF;
WaveHeader.dwFileSize = m_dwDataLen + 40;
WaveHeader. fccType = MAKEFOURCC('W', 'A', 'V', 'E');
WaveHeader.subckID = MAKEFOURCC('f', 'm', 't', ' ');
WaveHeader.dwSubChunkSize = 16;
WaveHeader. wFormatTag = WAVE_FORMAT_PCM;
WaveHeader. nChannels = 2;//pWaveFormat->nChannels;
WaveHeader. nSamplesPerSec = 11025;//pWaveFormat->nSamplesPerSec;
WaveHeader. wBitsPerSample = 8;//pWaveFormat->wBitsPerSample;
WaveHeader. nBlockAlign = WaveHeader. nChannels * WaveHeader. wBitsPerSample /8;
WaveHeader. nAvgBytesPerSec = WaveHeader. nSamplesPerSec * WaveHeader. nBlockAlign;          
WaveHeader.datackID = MAKEFOURCC('d','a','t','a');
WaveHeader.dwDataSize = m_dwDataLen;

WriteFile(hFile, & WaveHeader, sizeof(WaveFormChunk), &dwSize, NULL);
//파일 입출력 참고 (포스팅보러가기)

그리고 나머지  data를 write하면 wave 파일이 생성된다-_-)/

2010년 1월 22일 금요일

pixel clock

pixel clock(PCLK)은 1초에 pixel을 몇 개나 찍을 수 있는가 하는 것이다.
LCD는 보통 화면을 뿌려줄 때, 좌측 상단부터 가로로 나아가 뿌린다.
한 줄을 다 뿌리면 그 다음 줄 맨 왼쪽으로 와서 다시 가로로 나아가며 뿌린다.
한 줄을 다 뿌리면 그 다음 줄 맨 왼쪽으로 갈 수 있도록 줄바꾸기를 해주어야 하는데, 이것을 Hsync라 한다.
이런식으로 전체 화면 하나를 구성하고 나면 맨 오른쪽 하단에서 끝나게 되어 있는데, 그러면 다시 좌측 상단으로 올라가 화면을 다시 뿌린다.
이 과정에서 또한 맨 꼭대기로 올라갈 수 있게 해주어야 하는데, 이것을 Vsync라고 한다.

Vsync가 60Hz라고 한다면, 1초에 화면을 60번 뿌리는 것이 되겠다.


그렇다면, PCLK는 어떻게 계산할까.
LCD화면이 800X480이라고 가정하고 Vsync가 60Hz라고 가정한다면,
PCLK는 60X800X480Hz로 계산해낼 수 있다.
즉, 식을 도출해내면 다음과 같다.
PCLK = LCD_WIDTH * LCD_HEIGHT * Vsync



window 크기 변경

하드웨어마다 다르기는 하지만 보통 LCD는 여러 개의 window를 지원한다.
하여 각 window별로 LCD control register가 따로 존재하며, priority를 설정함으로써 overlap 관계를 조정할 수 있다.

여러 개의 window를 한꺼번에 사용하기 위해서는 우선 window를 enable 해주어야 한다.
아래와 같은 winenable register의 값을 설정한다.
이 register를 보면 window를 4개까지 지원하는 것을 알 수 있다.
각 field의 값이 1로 설정되면 해당되는 window가 enable된다. 물론 0일 경우 disable된다.


아무리 실제 LCD의 크기가 정해져 있다고 하더라도 window의 크기는 마음대로 변경할 수가 있다.
window의 크기와 origin을 변경한다면 화면 가운데에 조그맣게 무언가를 띄울 수도 있는 것이다. (origin 변경 포스트)
window 크기 변경은 LCD control register 1번에서 담당한다.
여기서 SZX는 width를 의미하며, SZY는 height를 의미한다.
이 field의 값을 설정해주면 그 값에 맞는 크기의 window가 하나 생성이 되며, PRI field의 값을 설정하여 우선순위를 부여하면 다른 window의 앞에 오거나 뒤에 서는 것이 가능하다.


위에서도 언급했지만 각 window별로 control register가 따로 존재하므로 각 window는 서로 다른 크기와 origin을 가질 수가 있고 이로써 많은 효과를 표현할 수 있다.








주의사항:
이 LCD control register는 RMI보드 Au1250 processor에 기반한 것이며,
각 하드웨어마다 다를 수 있음을 밝힙니다.

그림출처: RMI Alchemy Au1250 processor Data Book

2010년 1월 21일 목요일

origin값 변경

origin이라고 함은 정해진 window안에서의 왼쪽 최상단의 모서리를 origin이라고 한다.

전체 LCD의 해상도가 800X480이라고 가정할 때,
전체 window크기가 800X480이고 origin의 값이 0,0이라면
window에 있는 모든 pixel이 LCD화면에 나타나는 것을 볼 수 있을 것이다.

그러나, 같은 조건에서 origin의 값이 100,100이라면 오른쪽과 하단에서 100pixel만큼이 보이지 않을 것이다.
실제 window에서는 다 뿌렸어도, LCD의 100,100에서 부터 시작한다면 짤리는 것이 당연하다.

이처럼 origin의 값을 잘못 이용하게 되면 LCD화면에서 그림이 짤려 보이거나 한 쪽으로 치우쳐 보일 수 있다.
하지만 잘 사용하면 스크롤을 하는 듯한 효과를 줄 수 있다.
예를들어, origin의 Y값만을 주기적으로 변경한다면 그림이 화면에서 세로 방향으로 움직이게 된다.

이 origin의 값은 LCD control register 0번으로 제어한다.
OX와 OY field가 origin의 X, Y값이 된다.
이 field들을 제어하면 재미있는 화면의 움직임을 만들어 낼 수 있다.







주의사항:
이 LCD control register는 RMI보드 Au1250 processor에 기반한 것이며,
각 하드웨어마다 다를 수 있음을 밝힙니다.

그림출처: RMI Alchemy Au1250 processor Data Book

alpha값 적용

ARGB 시스템에서는 아래 그림과 같이 A,R,G,B가 각각 1byte씩 4byte가 frame buffer의 pixel 하나로 표현된다.
이 때 맨 앞의 A가 alpha값이다.

alpha값은 투명도를 뜻하는데, 이 값을 사용하기 위해서는 lcd control register에서 미리 설정 해두어야 한다.
alpha값을 제어 하는 register는 control register 0번이다.
AEN field의 값이 1이면 Full alpha, 0이면 Pixel alpha 이다.
Full alpha일 경우, 전체 window가 A field의 값으로 설정된다.
Pixel alpha일 경우, 위의 color register의 형태로 pixel값을 줄 때 A field에 있는 값을 alpha값으로 사용한다.

즉, pixel별로 alpha값을 다르게 주고 싶다면 AEN field의 값을 0으로 설정하고,
전체 화면의 alpha값이 모두 같게 하고 싶다면 AEN field의 값을 1로 설정하고 원하는 alpha값을 A field에 저장한다.







주의사항:
이 LCD control register는 RMI보드 Au1250 processor에 기반한 것이며,
각 하드웨어마다 다를 수 있음을 밝힙니다.

그림출처: RMI Alchemy Au1250 processor Data Book

MIPS memory map

MIPS 부트코드를 보다가 cached, uncached 라는 것을 발견해서 memory map을 좀 찾아 보았다.


이것이 MIPS의 메모리 구조이다.
각 영역에 대한 설명은 다음과 같다.

  • KUSEG
    • 사용자가 사용하는 공간
    • TLB를 통해 physical addr로 변환
  • KSEG0 (512M)
    • cached (항상 cache를 사용함)
    • cache 초기화 이후에 사용
    • 상위 1bit (최상위 bit)를 0으로 만들어 physical addr로 변환
    • TLB를 거치지 않고 access
    • 커널이 이 영역을 사용
  • KSEG1(512M)
    • uncached (cache를 사용하지 않음)
    • 시스템에서 cache가 정의되기 이전에 사용. (ex. reset vector addr = 0xBFC00000)
    • 상위 3bit를 0으로 만들어 physical addr로 변환
    • I/O 주변기기에 mapping (I/O 장치들은 그 특성상 cache를 사용해서는 안됨.)
  • KSEG2(512M)
    • 커널을 통해서 access 가능
    • TLB를 통해 physical addr로 변환

Nand Flash Block 구조

보드는 RMI, Au1250 MISP cpu를 사용하고.
아무튼, 부트로더를 올리기 위해서 nand flash 구조를 그려봤다.


알게 된 사실은 bootloader image를 2M까지 키워도 된다는 것.
용량 부담없이 마구 수정해야겠다-_-)> 훗.
엇, 부팅 이미지도 2M까지 받을 수 있구나. 이쁜 언냐로다가... 화질 좋은 걸로다가 ... 흐흐...


아, 또 하나.
nand에는 Large Block과 Small Block이 있는데, 둘의 차이는 page 크기의 차이로 보인다.

우선,
Large Block
1 Page = 2Kbytes
1 Block = 64Pages(0~63) = 128KB
NAND = 1024Blocks(0~1023) = 40M(맞나?;;)

Small Block
1 Page = 512Bytes
1 Block = 32Pages(0~31) = 16KB
NAND = 2048Blocks(0~2047) = 20M(맞나?;;)

2010년 1월 15일 금요일

BMP 파일 포멧


BMP파일을 에디터로 열어서 바이너리 모드로 확인해 보면 헤더부분이 보인다.
헤더가 끝난 이후로는 이미지 픽셀값이 들어있다.

offset

size(byte)

field

0

2

bmp file 식별코드. 항상 0x42 0x4D 들어간다.

2

4

bmp file size

6

2

reserved

8

2

reserved

10

4

offset. bmp data 시작 주소의 offset

14

4

header size. 항상 40byte.

18

4

bmp image width (pixel)

22

4

bmp image height (pixel)

26

2

color plane . 1 설정

28

2

pixel 비트 . 1,4,8,16,24,32.

30

4

압축방식 (0=none, 1=RLE-8, 2=RLE-4)

34

4

image data size (byte)

38

4

horizontal resolution (pixel/meter)

42

4

vertical resolution (pixel/meter)

46

4

팔레트의 or zero

50

4

중요한 or zero



출처는 위키백과