CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Connecting 16F877A to Wiimote using I2C

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Sodrohu



Joined: 16 Jul 2010
Posts: 4

View user's profile Send private message

Connecting 16F877A to Wiimote using I2C
PostPosted: Wed Sep 01, 2010 11:59 am     Reply with quote

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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 01, 2010 4:11 pm     Reply with quote

You want to read multiple bytes from a PIC i2c slave. The code shown
in the following post shows how to do that for a Master and a Slave:
http://www.ccsinfo.com/forum/viewtopic.php?t=39565&start=4
Sodrohu



Joined: 16 Jul 2010
Posts: 4

View user's profile Send private message

PostPosted: Thu Sep 02, 2010 12:51 pm     Reply with quote

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?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 02, 2010 2:50 pm     Reply with quote

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.
Sodrohu



Joined: 16 Jul 2010
Posts: 4

View user's profile Send private message

PostPosted: Tue Sep 07, 2010 11:19 am     Reply with quote

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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 07, 2010 12:14 pm     Reply with quote

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.
Sodrohu



Joined: 16 Jul 2010
Posts: 4

View user's profile Send private message

PostPosted: Sat Sep 18, 2010 7:24 pm     Reply with quote

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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Sep 18, 2010 7:30 pm     Reply with quote

Post your latest code.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group