
//Miscellaneous defines


#define Port_Columns   0x4C
#define Port_Lines     0x54

#define MFD_NBCOL 8
#define MFD_NBLIGN 8

int device_address;

static key_cde mfd_keys[5];                                     //list of keys to send through USB

#define MAX_MFD_DELAY 0x000F
static int16 mfd_delay = MAX_MFD_DELAY;

static keypad_state mfd_state = IDLE;                          //machine state for port operation
static int mfd_col;

// Initialise the I2C bus and config register
void mfd_init(int addr )
{
int i;
   printf("\r\nI2C init");

   i2c_start();                   //reset I2C ???
   i2c_stop();

   addr+= 0x40;                   //MAX6956 addresses take the form 100xxxx
   device_address = addr;         //where xxxx is the user-selected address 0-15.

   //Device configuration
   i2c_start();
   i2c_write( (device_address<<1) & 0xFE );
   i2c_write( 0x04 );             //Select Config byte (0x04)
   i2c_write( 0x01 );             //Transition disable, Global current, no shutdown
   i2c_stop();

   //configure port 12 to 27
   i2c_start();
   i2c_write( (device_address<<1) & 0xFE );
   i2c_write( 0x0B );                                //set adress for P15, P14, P13, P12 port config
   printf("\r\n1:%u", i2c_write( 0x55 ));            //set GPIO Output
   printf("\r\n2:%u", i2c_write( 0x55 ));            //P19, P18, P17, P16:set GPIO Output
   printf("\r\n3:%u", i2c_write( 0xFF ));            //P23, P22, P21, P20:set GPIO Inputs With Pullup
   printf("\r\n4:%u", i2c_write( 0xFF ));            //P27, P26, P25, P24:set GPIO Inputs With Pullup
   i2c_stop();

   mfd_state = OUTPUT_COL;
   printf("\r\nI2C init done");
}



void write_port(int PortNum, Data)
{
   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write( (device_address<<1) & 0xFE);
   i2c_write( PortNum );
   i2c_write( Data );
   i2c_stop();

   enable_interrupts(GLOBAL);
}



int read_port(int PortNum)
{
   int data;

   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write( (device_address<<1) & 0xFE);
   i2c_write( PortNum );
   i2c_stop();

   i2c_start();
   i2c_write( (device_address<<1) | 0x01);
   data = i2c_read(0);
   i2c_stop();

   enable_interrupts(GLOBAL);

   return data;
}



int mfd_task(void){
  int all_ligns;
  int lign;
  int key_is_dwn;
  int nb_keys = 0;                                              //nb ok key having state update -> will be proceed in main()

  switch (mfd_state){
    case IDLE :
      mfd_init(0);
      mfd_state = OUTPUT_COL;
      break;

    case OUTPUT_COL :
      write_Port(Port_Columns, ~(1<<mfd_col));              //enable on column
      //printf("\r\nCol=%u", 1<<mfd_col);
      mfd_delay = MAX_MFD_DELAY;
      mfd_state = DELAY;
      break;

    case DELAY :
      if (! --mfd_delay ) {
         mfd_state = INPUT_DATA;
      }
      break;

    case INPUT_DATA :
      all_ligns = read_port(Port_Lines);

      //printf("\r\nCol=%u portB=%u", mfd_col, all_ligns);

      for (lign=0;lign<MFD_NBLIGN;++lign){

        key_is_dwn = !(all_ligns & (1<<lign) );

        //printf("key_is_dwn=%u", key_is_dwn);

        switch (mfd_keymaps[lign][mfd_col].pos) {
          case kpUp :
            if (key_is_dwn){
              mfd_keymaps[lign][mfd_col].idx = KEY_READ_COUNT;
              mfd_keymaps[lign][mfd_col].cpt_dwn = 0;
              mfd_keymaps[lign][mfd_col].pos = kpCpt;
              //printf("\r\nKey Lign[%u] Col[%u] now down", lign, mfd_col);
            }
            break;

          case kpCpt :
            if (key_is_dwn){
              ++mfd_keymaps[lign][mfd_col].cpt_dwn;        // MAJ du compteur de Dwn
              //printf("\r\nKey [%u][%u] cpt=%u", lign, col, key_states[lign][col].cpt_dwn);
            }

            if (!mfd_keymaps[lign][mfd_col].idx){          //les 10 lectures ont été faites
              if (mfd_keymaps[lign][mfd_col].cpt_dwn > KEY_READ_THRES){
                //printf("\r\nKey #%u debounced [%u][%u]", nb_keys, lign, col);

                //HERE update du tableau result
                mfd_keys[nb_keys].pos = kpDwn;
                mfd_keys[nb_keys].lign = lign;
                mfd_keys[nb_keys++].col = mfd_col;
              }
              mfd_keymaps[lign][mfd_col].pos = kpDwn;
            }
            --mfd_keymaps[lign][mfd_col].idx;              //MAJ du compteur de nb de lecture
            break;


          case kpDwn :
            if (!key_is_dwn){
              mfd_keymaps[lign][mfd_col].pos = kpUp;


              //HERE update du tableau result
              mfd_keys[nb_keys].pos = kpUp;
              mfd_keys[nb_keys].lign = lign;
              mfd_keys[nb_keys++].col = mfd_col;

              //printf("\r\nKey #%u released [%u][%u] %u", nb_keys, mfd_keys[nb_keys].lign, mfd_keys[nb_keys].col, mfd_keys[nb_keys].pos);
            }
            break;
         }//end Switch
      }//end For lign

      if (++mfd_col == MFD_NBCOL)                                 // gère les colones
        mfd_col = 0;
      mfd_state = OUTPUT_COL;
      break;

  }//end swtich

  return nb_keys;

}
