View previous topic :: View next topic |
Author |
Message |
Sodrohu
Joined: 16 Jul 2010 Posts: 4
|
Connecting 16F877A to Wiimote using I2C |
Posted: Wed Sep 01, 2010 11:59 am |
|
|
So this is what I've done so far....
I've gone thru a similar topic posted here:
http://www.ccsinfo.com/forum/viewtopic.php?t=32753
and based on http://www.windmeadow.com/node/37.
What I wanted to do is to connect the 16F877A to the Wiimote, thru I2C, with the 16F emulating a Nunchuk. The Wiimote uses Fast 400 kHz I2C and the nunchuk's address is 0xA4.
I'm pretty certain at this point that the Nunchuk, and hence the uC 16F is slave to the Wiimote, based on the Arduino codes from Windmeadows.
This is my current code. The original code comes from CCS examples. I'm using CCS ver 4.078:
Code: |
#use delay(clock=20000000)
#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0xA4)
void encrypt_init_encode(void);
void encrypt_init_nocode(void);
char nunchuk_encode_byte(char x);
void flashled1(void);
void flashled2(void);
void flashled3(void);
void flashled4(void);
int8 bufnocode[6];
int8 bufencode[6];
int8 bufoutput[6];
BYTE address, buffer[0x10];
#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
{
flashled1();
address = incoming;
}
if(state == 2) //Second received byte is data
{
buffer[address] = incoming;
flashled2();
}
}
if(state == 0x80) //Master is requesting data
{
//i2c_write(buffer[address]);
i2c_write(bufencode[0]);
i2c_write(bufencode[1]);
i2c_write(bufencode[2]);
i2c_write(bufencode[3]);
i2c_write(bufencode[4]);
i2c_write(bufencode[5]);
flashled3();
}
flashled4();
}
void main ()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
encrypt_init_encode();
encrypt_init_nocode();
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {}
}
//=======================================================
void encrypt_init_encode(void)
{
bufencode[0] = nunchuk_encode_byte(125); // joystick X
bufencode[1] = nunchuk_encode_byte(126); // joystick Y
bufencode[2] = nunchuk_encode_byte(227); // Axis X
bufencode[3] = nunchuk_encode_byte(241); // Axis Y
bufencode[4] = nunchuk_encode_byte(140); // Axis Z
bufencode[5] = nunchuk_encode_byte(1); // Press C button, byte[5] is buttons
//C,Z and accelaration data
//outbuf[5] = nunchuk_encode_byte(2); // Press Z button
//outbuf[5] = nunchuk_encode_byte(0); // Press Z and C button
}
//=======================================================
void encrypt_init_nocode(void)
{
bufnocode[0] = 125; // joystick X
bufnocode[1] = 126; // joystick Y
bufnocode[2] = 227; // Axis X
bufnocode[3] = 241; // Axis Y
bufnocode[4] = 140; // Axis Z
bufnocode[5] = 1; // Press C button, byte[5] is buttons
}
//=======================================================
// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_encode_byte(char x)
{
x = x - 0x17;
x = (x ^ 0x17);
return x;
}
//======================================================
void flashled1(void)
{
output_high(PIN_B7);
delay_ms(50);
output_low(PIN_B7);
}
//=======================================================
void flashled2(void)
{
output_high(PIN_B6);
delay_ms(50);
output_low(PIN_B6);
}
//=======================================================
void flashled3(void)
{
output_high(PIN_B5);
delay_ms(50);
output_low(PIN_B5);
}
//=======================================================
void flashled4(void)
{
output_high(PIN_B4);
delay_ms(50);
output_low(PIN_B4);
}
|
Right now it doesn't work. I dunno why; perhaps there is a problem with the sending of data when requested. I'll try to do some changes to see what the problem is. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
Sodrohu
Joined: 16 Jul 2010 Posts: 4
|
|
Posted: Thu Sep 02, 2010 12:51 pm |
|
|
For this part
Code: | if(state >= 0x80) // Master is requesting data from slave
{
index = state & 7; // Lower 3 bits of state = the index
i2c_write(buffer[index]);
} |
especially this
Code: | index = state & 7; // Lower 3 bits of state = the index |
How does it work? I assume that since the program wants the slave to send 8 bytes of data, so it becomes state & 7. If I want to get 6 bytes of data instead, should it be state & 5? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 02, 2010 2:50 pm |
|
|
No. You're converting the value from i2c_isr_state() into an array index.
The value increments as 0x80, 0x81, 0x82, ....., etc. You could simply
mask off the top bit, but I like to mask it down to only the needed bits.
That's the lowest 3 bits, so a mask of 0x07 is used. If you use 0-5, it
still takes 3 bits for the 0x05, so leave the mask at 0x07. |
|
![](templates/subSilver/images/spacer.gif) |
Sodrohu
Joined: 16 Jul 2010 Posts: 4
|
|
Posted: Tue Sep 07, 2010 11:19 am |
|
|
The code that I've updated is below there. The Connection is still not working.
Code: | #INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;
state = i2c_isr_state();
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
{
flashled1();
address = incoming;
}
if(state == 2) //Second received byte is data
{
buffer[address] = incoming;
flashled2();
}
}
if(state == 0x80) //Master is requesting data
{
index = state & 7; // Lower 3 bits of state = the index
i2c_write(bufencode[index]);
//! i2c_write(buffer[address]);
//! i2c_write(bufencode[0]);
//! i2c_write(bufencode[1]);
//! i2c_write(bufencode[2]);
//! i2c_write(bufencode[3]);
//! i2c_write(bufencode[4]);
//! i2c_write(bufencode[5]);
flashled3();
}
//flashled4();
} |
I suspect that the handshaking is to be blamed here. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 07, 2010 12:14 pm |
|
|
Quote: |
if(state == 0x80) //Master is requesting data
{
|
You have changed the operator in the if() statement. You want the if()
statement to execute if the value from i2c_isr_state() is 0x80 or higher.
But you have blocked out all values above 0x80. You need to fix that. |
|
![](templates/subSilver/images/spacer.gif) |
Sodrohu
Joined: 16 Jul 2010 Posts: 4
|
|
Posted: Sat Sep 18, 2010 7:24 pm |
|
|
Sorry for the long delay....
Anyway, I implemented the code as you asked me to. The result is still the same; the Wiimote does not register the uc's data.
The Wiimote sends handshake to the Nunchuk and the Nunchuk replied back. What kind of data that the Nunchuk sends back as confirmation is what I don't know. Possibly it's the one that causes the entire thing to not work. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Sep 18, 2010 7:30 pm |
|
|
Post your latest code. |
|
![](templates/subSilver/images/spacer.gif) |
|