|
From: Kevin T. <lis...@pc...> - 2007-02-16 01:12:43
|
Here are my notes for the MCE2004/2005 IR transceivers...
Command Summary
---------------
80 End of tranmission
8x Data, length of x, x=[1...4]
9F 03 Ping?
9F 05 ???
9F 06 mm ff Set tx carrier mode and frequency
9F 07 Get tx carrier mode and frequency
9F 08 bb Set tx blaster bitmask
9F 0C msb lsb Set rx timeout (units of 50 microseconds)
9F 0D Get rx timeout
9F 0F ???
9F 13 Get tx blaster bitmask
9F 14 nn Set rx sensor (01 = long range demodulator, 02 =
short range detector)
9F 15 Get rx sensor
00 FF AA Reset - 00 seems to be optional
FF 0B Get hw/sw revision???
FF 18 ???
Response Summary
----------------
80 End of reception
8x Data, length of x, x=[1...4]
9F 01 nn Report rx sensor used
9F 03 Ping?
9F 04 xx xx Response to 9F 05 - MCE2004=00FA, MCE2005=01F4
9F 06 mm ff Confirm carrier mode and frequency setting
9F 08 bb Confirm tx blaster bitmask
9F 0C msb lsb Confirm rx timeout setting
9F 14 nn Confirm rx sensor setting
9F 15 msb lsb Report rx pulse count
9F FE Error! Hardware is probably wedged. Try a 00 FF AA reset.
--------------- Command Details -----------------------
80 End of tranmission
Send this after the last 8x block. Finalize IR transmission
8x Data, length of x, x=[1...4]
X data bytes follow. Each data byte has on/off state in bit 7, and
time in bits 0 to 6. Time is in units of 50 microseconds.
9F 05 ???
Unknown purpose. Response will be 9F 04 00 FA for MCE2004 or 9F 04 01
F4 for MCE2005
9F 06 mm ff Set tx carrier mode and frequency
mm clk
00 10000000
01 2500000
02 625000
03 156250
ff = ( clk / frequency ) - 1
frequency = clk / ( ff + 1 )
so...
9F 06 00 AE 57143 Hz 57 kHz
9F 06 00 AF 56818 Hz 57 kHz
9F 06 01 2B 56818 Hz 57 kHz
9F 06 01 3D 40323 Hz 40 kHz
9F 06 00 F9 40000 Hz 40 kHz
9F 06 01 3E 39682 Hz 40 kHz
9F 06 01 40 38462 Hz 38 kHz
9F 06 01 41 37879 Hz 38 kHz
9F 06 01 44 36232 Hz 36 kHz
9F 06 01 45 35714 Hz 36 kHz
Default frequency is 66 kHz! ( 9F 06 00 96 )
if mm == 0x80 then...
frequency = 9765.625 Hz (2500000/256, 102.4 uS period)
on time = ( 256 - ff ) * .4 uS
off time = ff * .4 uS
so...
9F 06 80 00 = no modulation
9F 06 80 80 = 9.765 kHz with 50% duty cycle
etc...
note: if bit 7 of mm is set, all other bits are ignored (prescaler is
not selectable)
9F 08 bb Set tx blaster bitmask - No confirmation?!
Enable specified IR blaster(s)
9F 0C msb lsb Set rx timeout (units of 50 microseconds)
When no IR has been seen for this amount of time, the 80 response
will be sent followed by 9F 01 and 9F 05 responses.
9F 0F ???
Unknown purpose. Response is 9F 0E 00
9F 14 nn Set rx sensor (01 = long range demodulator,
02 = short range detector)
The MCE hardware has a long rage IR demodulator for remote control
and a short range IR detector for learning. The short range sensor
can detect each IR pulse, so the 9F 15 response will be non-zero and
the carrier frequency can be estimated.
00 FF AA Reset
Try this if the hardware stops responding. The leading 00 seems to be optional.
FF 0B Get hw/sw revision???
MCE2004 will respond with FF 0B 45 FF 1B 08.
MCE2005 will respond with FF 0B 50 FF 1B 42.
MCE2004 FTDI chip initialization
--------------------------------
Send these USB control blocks...
Reset
40 00 00 00 00 00 00 00
Note: 64 bytes of garbage will be received, and must be discared
Get modem status (optional?)
C0 05 00 00 00 00 02 00 00 00 ..
Set bit rate to 38400 bps
40 03 4E C0 00 00 00 00
Set char length to 8 bits
40 04 08 08 00 00 00 00
Set handshaking to use DTR/DSR
40 02 00 00 00 01 00 00
Note: Each block received from the FTDI chip will have a 2 byte line
status header that can be discarded.
------------------------------------------
Sample code for rx...
static UINT rx_state=0;
static UINT total_on_pulses=0;
static UINT total_on_time=0;
static UINT mce2004=0;
static const UINT max_array_size=1024;
static int times[max_array_size];
static UINT array_size=0;
void ProcessRxMCE(UINT len, BYTE* data)
{
static BYTE mce_last_b=0x80;
static UINT mce_chunk_len;
static BYTE mce_rsp;
static UINT mce_rsp_data;
if(mce2004) {
if(len<2) return;
len-=2;
if(!len) return;
}
while(len--) {
const BYTE b=*data++;
switch(rx_state) {
case 0:
if((b & 0xE0) == 0x80) {
mce_chunk_len = b & 0x1F;
switch(mce_chunk_len) {
case 0:
TRACE0("End
of packet\n");
TRACE2("Total
on time: %i uS / %i periods\n",total_on_time,total_on_time/50);
if((array_size<max_array_size)
&& (times[array_size]!=0)) ++array_size;
AddRxToQueue();
array_size=0;
total_on_time=0;
total_on_pulses=0;
mce_last_b=0x80;
times[0]=0;
break;
case 0x1F:
rx_state=2;
break;
default:
rx_state=1;
break;
}
} else if(b==0xFF) {
rx_state=4;
} else {
TRACE1("Bogus data: %02X\n",b);
ASSERT(rx_state==0);
}
break;
case 1:
if(array_size < max_array_size) {
const int
t=50*((b&0x80)?b&0x7F:-static_cast<int>(b&0x7F));
if(((mce_last_b^b)&0x80)==0x80) {
mce_last_b=b;
if(times[array_size]>0)
total_on_time+=times[array_size];
if(++array_size <
max_array_size) {
times[array_size]=t;
}
} else
times[array_size]+=t;
}
if(!--mce_chunk_len) rx_state=0;
break;
case 2: // 9F response
mce_rsp_data=0;
++rx_state;
switch(mce_rsp=b) {
case 0x01: //
Rx sensor report
mce_chunk_len=1;
break;
case 0x15: //
Rx pulse count report
mce_chunk_len=2;
break;
case 0x04: //
??? - Response to 9F 05
mce_chunk_len=2;
break;
case 0x06: //
Tx carrier freq confirm
mce_chunk_len=2;
break;
case 0x08: //
Tx blaster confirm
mce_chunk_len=1;
break;
case 0x0C: //
Rx timeout confirm
mce_chunk_len=2;
break;
case 0x0E: // ???
mce_chunk_len=1;
break;
case 0x14: //
Rx sensor confirm
mce_chunk_len=1;
break;
case 0x03: // Ping ???
TRACE0("Ping?\n");
rx_state=0;
break;
case 0xFE:
rx_state=0;
TRACE0("Invalid 9F
command issued\n*** Dongle is probably wedged ***\n");
break;
default:
rx_state=0;
TRACE1("Invalid 9F
response: %02X\n",mce_rsp);
ASSERT(FALSE);
break;
}
break;
case 3:
mce_rsp_data=(mce_rsp_data<<8)|b;
if(!--mce_chunk_len) {
switch(mce_rsp) {
case
0x01: // Rx sensor report
TRACE1("Rx
input: %i\n",mce_rsp_data);
break;
case
0x15: // Rx pulse count report
TRACE1("Rx
pulse count: %i\n",mce_rsp_data);
total_on_pulses=mce_rsp_data;
break;
case
0x04: // Response to 9F 05
TRACE2("9F
05 response data: %04X (%i)\n",mce_rsp_data,mce_rsp_data);
break;
case
0x06: // Tx carrier freq confirm
if(mce_rsp_data
& 0x8000) {
TRACE1("Tx
pulse width: %i/256\n",256-(mce_rsp_data&0xFF));
} else {
static
const clocks[4]={10000000,2500000,625000,156250};
const
UINT clock=clocks[(mce_rsp_data>>8)&3];
TRACE1("Tx
clock: %i\n",clock);
TRACE1("Tx
frequency: %i Hz\n",clock/((mce_rsp_data&0xFF)+1));
}
break;
case 0x08: //
Tx blaster confirm
TRACE1("Tx
blaster bitmask: %02X\n",mce_rsp_data);
break;
case
0x0C: // Rx timeout confirm
TRACE1("Rx
timeout: %i mS\n",mce_rsp_data/20);
break;
case
0x14: // Rx sensor confirm
TRACE1("Rx
sensor: %i\n",mce_rsp_data);
break;
default:
TRACE2("9F
%02X response data: %X\n",mce_rsp,mce_rsp_data);
break;
}
rx_state=0;
}
break;
case 4: // FF response
mce_rsp_data=0;
++rx_state;
switch(mce_rsp=b) {
case 0x0B:
case 0x1B:
mce_chunk_len=1;
break;
case 0x18:
mce_chunk_len=4;
break;
case 0xFE:
rx_state=0;
TRACE0("Invalid FF
command issued\n");
TRACE0("*** Dongle
is probably wedged ***\n");
break;
default:
rx_state=0;
TRACE1("Invalid FF
response: %02X\n",mce_rsp);
ASSERT(FALSE);
break;
}
break;
case 5:
mce_rsp_data=(mce_rsp_data<<8)|b;
if(!--mce_chunk_len) {
switch(mce_rsp) {
case
0x0B: // ??? report
TRACE1("FF
0B response: %02X\n",mce_rsp_data);
break;
case
0x1B: // ?? report
TRACE1("FF
1B response: %02X\n",mce_rsp_data);
break;
case
0x18: // ??? report
TRACE1("FF
18 response: %08X\n",mce_rsp_data);
break;
default:
TRACE2("FF
%02X response data: %X\n",mce_rsp,mce_rsp_data);
break;
}
rx_state=0;
}
break;
}
}
}
|