/* 4                              5678901234567
 
  ┌─────────────────────────────────────────────┐
 
  │Detecting mouse...                           │03
 
  │FF FA AA 00                                  │
 
  │Customization...                             │
 
  │F3 FA C8 FA F3 FA 64 FA F3 FA 50 FA          │
 
  │F2 FA 03                                     │
 
  │E8 FA 02 FA E6 FA F3 FA 64 FA F4 FA          │
 
  │Let's go!                                    │
 
  │08 00 00 00                    ┌───────────┐ │10
 
  │                               │███        │ │11
 
  │                               │█L█  M   R │ │12
 
  │                               │███        │ │13
 
  │                               │           │ │14
 
  │                               │ Wheel = 1 │ │15
 
  │                               │           │ │16
 
  │                               │ X  =  123 │ │17
 
  │                               │ Y  =   58 │ │18
 
  │                               └───────────┘ │
 
  └─────────────────────────────────────────────┘
 
   4                              5678901234567  */
 
//-----------------------------------------------------------------------------
 
 
 
#include "_global.h"
 
#include "_screen.h"
 
#include "_t_ps2m.h"
 
#include "_ps2k.h"
 
#include "_uart.h"
 
#include <avr/interrupt.h>
 
#include <util/delay_basic.h>
 
 
 
//-----------------------------------------------------------------------------
 
 
 
volatile u8 ps2m_bit_count, ps2m_data, ps2m_raw_ready, ps2m_raw_code;
 
volatile u8 ps2m_flags;
 
u8 tpsm_id;
 
 
 
//-----------------------------------------------------------------------------
 
 
 
#define ps2m_dataline_up()    { DDRD&=~(1<<PD7); PORTD|=(1<<PD7); }
 
#define ps2m_dataline_down()  { PORTD&=~(1<<PD7); DDRD|=(1<<PD7); }
 
#define ps2m_clockline_up()   { DDRE&=~(1<<PE5); PORTE|=(1<<PE5); }
 
#define ps2m_clockline_down() { PORTE&=~(1<<PE5); DDRE|=(1<<PE5); }
 
 
 
//-----------------------------------------------------------------------------
 
 
 
const WIND_DESC wind_t_ps2m_1 PROGMEM = {  3, 2,47,19,0xdf,0x01 };
 
const WIND_DESC wind_t_ps2m_2 PROGMEM = {  9,10,34, 4,0xaf,0x01 };
 
const WIND_DESC wind_t_ps2m_3 PROGMEM = { 35,10,13,10,0xdf,0x00 };
 
#define p_wind_t_ps2m_1 ((const P_WIND_DESC)&wind_t_ps2m_1)
 
#define p_wind_t_ps2m_2 ((const P_WIND_DESC)&wind_t_ps2m_2)
 
#define p_wind_t_ps2m_3 ((const P_WIND_DESC)&wind_t_ps2m_3)
 
 
 
const u8 ps2msetup1[] PROGMEM = { 0xf3,200,0xf3,100,0xf3,80,0xff };
 
const u8 ps2msetup2[] PROGMEM = { 0xe8,0x02,0xe6,0xf3,100,0xf4,0xff };
 
 
 
//-----------------------------------------------------------------------------
 
 
 
u8 ps2m_send_byte(u8 data)
 
{
 
 u8 temp;
 
 temp=0;
 
 do
 
 {
 
  if (!(PINE&(1<<PE5))) temp=0;
 
 }while (--temp);
 
 cli();
 
 ps2m_data=data;
 
 ps2m_flags=1<<PS2M_BIT_TX;
 
 ps2m_bit_count=0;
 
 ps2m_raw_ready=0;
 
 ps2m_clockline_down();
 
 sei();
 
 _delay_loop_2(359);                            // 130 us
 
 ps2m_dataline_down();
 
 _delay_loop_1(74);                             // 20 us
 
 u16 to;
 
 set_timeout_ms(&to,15);
 
 ps2m_clockline_up();
 
 do
 
 {
 
  if (check_timeout_ms(&to))  return 0;
 
 }while (!(ps2m_flags&(1<<PS2M_BIT_ACKBIT)));
 
 return 1;
 
}
 
 
 
//-----------------------------------------------------------------------------
 
 
 
u8 ps2m_receive_byte(u8 *data)
 
{
 
 ps2m_raw_ready=0;
 
 u16 to;
 
 set_timeout_ms(&to,7);
 
 do
 
 {
 
  if (ps2m_raw_ready)
 
  {
 
   *data=ps2m_raw_code;
 
   ps2m_raw_ready=0;
 
   return 1;
 
  }
 
 }while (!(check_timeout_ms(&to)));
 
 return 0;
 
}
 
 
 
//-----------------------------------------------------------------------------
 
 
 
u8 ps2m_detect_send(u8 data)
 
{
 
 print_hexbyte_for_dump(data);
 
 if (ps2m_send_byte(data))
 
 {
 
  u8 response;
 
  if (ps2m_receive_byte(&response))
 
  {
 
   print_hexbyte_for_dump(response);
 
   if (response==0xfa) return 1;
 
  }
 
 }
 
 return 0;
 
}
 
 
 
//-----------------------------------------------------------------------------
 
 
 
u8 ps2m_detect_sendmulti(const u8 * array)
 
{
 
 u8 data;
 
 do
 
 {
 
  data=pgm_read_byte(array);
 
  array++;
 
  if (data!=0xff)
 
  {
 
   if (!(ps2m_detect_send(data))) return 0;
 
  }
 
 }while (data!=0xff);
 
 return 1;
 
}
 
 
 
//-----------------------------------------------------------------------------
 
 
 
u8 ps2m_detect_receive(u8 expected)
 
{
 
 u8 data;
 
 if (ps2m_receive_byte(&data))
 
 {
 
  print_hexbyte_for_dump(data);
 
  if (data==expected) return 1;
 
 }
 
 return 0;
 
}
 
 
 
//-----------------------------------------------------------------------------
 
 
 
u8 t_psm_detect(void)
 
{
 
 u8 go2;
 
 do
 
 {
 
  cli();
 
  ps2m_dataline_up();
 
  ps2m_clockline_up();
 
  EICRB=(EICRB&~((1<<ISC51)|(1<<ISC50)))|((1<<ISC51)|(0<<ISC50));
 
  EIMSK|=(1<<INT5);
 
  ps2m_flags=0;
 
  ps2m_bit_count=0;
 
  ps2m_raw_ready=0;
 
  sei();
 
 
 
  scr_window(p_wind_t_ps2m_1);
 
  scr_set_cursor(4,3);
 
  uart_crlf();
 
  print_mlmsg(mlmsg_mouse_detect);
 
  scr_set_cursor(4,4);
 
  uart_crlf();
 
 
 
  do
 
  {
 
   go2=GO_REPEAT;
 
   ps2m_raw_ready=0;
 
   u16 to;
 
   set_timeout_ms(&to,2);
 
   while (ps2m_raw_ready==0)
 
   {
 
    if (check_timeout_ms(&to))
 
    {
 
     go2=GO_CONTINUE;
 
     break;
 
    }
 
   }
 
  }while (go2==GO_REPEAT);
 
 
 
  const u8 * const *errmlmsg=mlmsg_mouse_fail0;
 
  go2=GO_ERROR;
 
  print_hexbyte_for_dump(0xff);
 
  if (ps2m_send_byte(0xff))
 
  {
 
   u8 temp;
 
   if (ps2m_receive_byte(&temp))
 
   {
 
    print_hexbyte_for_dump(temp);
 
    if (temp==0xfa)
 
    {
 
     //ps2m_raw_ready=0;
 
     errmlmsg=mlmsg_mouse_fail1;
 
     u16 to;
 
     set_timeout_ms(&to,1000);
 
     while (!(check_timeout_ms(&to)))
 
     {
 
      if (ps2m_raw_ready)
 
      {
 
       go2=GO_CONTINUE;
 
       break;
 
      }
 
     }
 
     if (go2==GO_CONTINUE)
 
     {
 
      go2=GO_ERROR;
 
      if (ps2m_raw_code==0xaa)
 
      {
 
       if (ps2m_detect_receive(0x00))
 
       {
 
        scr_set_cursor(4,5);
 
        uart_crlf();
 
        print_mlmsg(mlmsg_mouse_setup);
 
        scr_set_cursor(4,6);
 
        uart_crlf();
 
        if (ps2m_detect_sendmulti(ps2msetup1))
 
        {
 
         scr_set_cursor(4,7);
 
         uart_crlf();
 
         if (ps2m_detect_send(0xf2))
 
         {
 
          ps2m_raw_ready=0;
 
          set_timeout_ms(&to,20);
 
          while (!(check_timeout_ms(&to)))
 
          {
 
           if (ps2m_raw_ready)
 
           {
 
            go2=GO_CONTINUE;
 
            break;
 
           }
 
          }
 
          if (go2==GO_CONTINUE)
 
          {
 
           go2=GO_ERROR;
 
           temp=ps2m_raw_code;
 
           tpsm_id=temp;
 
           print_hexbyte_for_dump(temp);
 
           if ( (temp==0x00) || (temp==0x03) )
 
           {
 
            scr_set_cursor(4,8);
 
            uart_crlf();
 
            if (ps2m_detect_sendmulti(ps2msetup2))
 
            {
 
             scr_set_cursor(4,9);
 
             uart_crlf();
 
             go2=GO_CONTINUE;
 
            }
 
           }
 
          }
 
         }
 
        }
 
       }
 
      }
 
     }
 
    }
 
   }
 
  }
 
 
 
  if (go2!=GO_CONTINUE)
 
  {
 
   scr_window(p_wind_t_ps2m_2);
 
   scr_set_cursor(10,11);
 
   uart_crlf();
 
   print_mlmsg(errmlmsg);
 
   scr_set_cursor(10,12);
 
   print_mlmsg(mlmsg_mouse_restart);
 
   do
 
   {
 
    u16 key;
 
    key=waitkey();
 
    if ((u8)(key>>8)==KEY_ENTER)
 
     go2=GO_RESTART;
 
    else if ( (!((u8)key&(1<<PS2K_BIT_EXTKEY))) && ((u8)(key>>8)==KEY_ESC) )
 
     go2=GO_EXIT;
 
   }while (go2==GO_CONTINUE);
 
  }
 
 
 
 }while ( (go2!=GO_CONTINUE) && (go2!=GO_EXIT) );
 
 
 
 return go2;
 
}
 
 
 
//-----------------------------------------------------------------------------
 
 
 
void Test_PS2Mouse(void)
 
{
 
 flags1&=0b11111011;
 
 flags1|=0b00000010;
 
 print_mlmsg(mlmsg_mouse_test);
 
 flags1|=0b00000100;
 
 
 
 if (t_psm_detect()!=GO_EXIT)
 
 {
 
  print_mlmsg(mlmsg_mouse_letsgo);
 
  uart_crlf();
 
  flags1&=0b11111100;
 
  int6vect=0b00000010;
 
  fpga_reg(INT_CONTROL,int6vect);
 
  scr_window(p_wind_t_ps2m_3);
 
  if (tpsm_id)
 
   scr_print_msg(msg_tpsm_1);
 
  else
 
   scr_print_msg(msg_tpsm_1+10);
 
  u16 tpsm_x;
 
  u8 tpsm_y, tpsm_z, tpsm_btn;
 
  u8 tpsm_byte1, tpsm_byte2, tpsm_byte3, tpsm_byte4;
 
  tpsm_x=150;
 
  tpsm_y=120;
 
  tpsm_z=0;
 
  tpsm_btn=0;
 
  ps2m_raw_ready=0;
 
 
 
  u8 go2;
 
  do
 
  {
 
   if (tpsm_id)
 
   {
 
    scr_set_cursor(45,15);
 
    print_hexhalf(tpsm_z);
 
   }
 
   scr_set_cursor(41,17);
 
   print_dec16(tpsm_x);
 
   scr_set_cursor(41,18);
 
   print_dec16(tpsm_y);
 
 
 
   u8 temp;
 
   temp=11;
 
   do
 
   {
 
    scr_set_cursor(36,temp);
 
    u8 attr;
 
    if (tpsm_btn&0x01) attr=0xae; else attr=0xdf;
 
    scr_fill_attr(attr,3);
 
    scr_fill_attr(0xdf,1);
 
    if (tpsm_btn&0x04) attr=0xae; else attr=0xdf;
 
    scr_fill_attr(attr,3);
 
    scr_fill_attr(0xdf,1);
 
    if (tpsm_btn&0x02) attr=0xae; else attr=0xdf;
 
    scr_fill_attr(attr,3);
 
   }while (++temp<14);
 
 
 
   do
 
   {
 
    go2=GO_REPEAT;
 
    if (newframe)
 
    {
 
     newframe=0;
 
     u16 w;
 
     w=tpsm_x+98;
 
     fpga_reg(SCR_MOUSE_TEMP,(u8)(w>>8));
 
     fpga_reg(SCR_MOUSE_X,(u8)w);
 
     w=tpsm_y+43;
 
     fpga_reg(SCR_MOUSE_TEMP,(u8)(w>>8));
 
     fpga_reg(SCR_MOUSE_Y,(u8)w);
 
    }
 
 
 
    if (ps2m_raw_ready)
 
    {
 
     ps2m_raw_ready=0;
 
     temp=ps2m_raw_code;
 
     if (temp&0b00001000)
 
     {
 
      tpsm_byte1=temp;
 
      if (ps2m_receive_byte(&tpsm_byte2))
 
      {
 
       if (ps2m_receive_byte(&tpsm_byte3))
 
       {
 
        if (tpsm_id) temp=ps2m_receive_byte(&tpsm_byte4);
 
        if (temp)
 
        {
 
         tpsm_btn=tpsm_byte1&0x07;
 
 
 
         if (tpsm_byte1&0b00010000)
 
         {
 
          u16 w;
 
          w=0xff00|tpsm_byte2;
 
          tpsm_x+=w;
 
          if (tpsm_x>317) tpsm_x=0;
 
         }
 
         else
 
         {
 
          tpsm_x+=tpsm_byte2;
 
          if (tpsm_x>317) tpsm_x=317;
 
         }
 
 
 
         if (tpsm_byte1&0b00100000)
 
         {
 
          u16 w;
 
          w=(u16)tpsm_y-(0xff00|tpsm_byte3);
 
          if (w>249) tpsm_y=249; else tpsm_y=(u8)w;
 
         }
 
         else
 
         {
 
          u16 w;
 
          w=(u16)tpsm_y-tpsm_byte3;
 
          if (w>249) tpsm_y=0; else tpsm_y=(u8)w;
 
         }
 
 
 
         if (tpsm_id)  tpsm_z=(tpsm_z+tpsm_byte4)&0x0f;
 
 
 
         scr_set_cursor(4,10);
 
         scr_set_attr(0xdf);
 
         flags1|=0b00000010;
 
         print_hexbyte(tpsm_byte1);
 
         put_char(0x20);
 
         print_hexbyte(tpsm_byte2);
 
         put_char(0x20);
 
         print_hexbyte(tpsm_byte3);
 
         put_char(0x20);
 
         if (tpsm_id)
 
         {
 
          print_hexbyte(tpsm_byte4);
 
          put_char(0x20);
 
         }
 
         put_char(0x20);
 
         flags1&=0b11111100;
 
         go2=GO_REDRAW;
 
        }
 
       }
 
      }
 
     }
 
    }
 
 
 
    u16 key;
 
    if (inkey(&key))
 
    {
 
     if ( (!((u8)key&(1<<PS2K_BIT_EXTKEY))) && ((u8)(key>>8)==KEY_ESC) )
 
      go2=GO_EXIT;
 
    }
 
 
 
   }while (go2==GO_REPEAT);
 
 
 
  }while (go2!=GO_EXIT);
 
 
 
 }
 
 
 
 int6vect=0b00000000;
 
 fpga_reg(INT_CONTROL,int6vect);
 
 fpga_reg(SCR_MOUSE_TEMP,0);
 
 fpga_reg(SCR_MOUSE_X,0);
 
 fpga_reg(SCR_MOUSE_Y,0);
 
 cli();
 
 ps2m_dataline_up();
 
 ps2m_clockline_up();
 
 EIMSK&=~(1<<INT5);
 
 sei();
 
 flags1|=0b00000010;
 
}
 
 
 
//-----------------------------------------------------------------------------