#include<stdio.h>
#include <dev/ppbus/ppi.h>
#include <dev/ppbus/ppbconf.h>
#include <fcntl.h>
#include <unistd.h>
int fd;
u_int8_t pp_data,pp_ctrl,pp_stat;

void fault(){
  perror("I/O error");
  exit(1);  
}

int is_bidir(){
  u_int8_t val;
  /*$BF~NO%b!<%I$K$9$k(B*/
  ioctl(fd, PPIGECR, &val);
  val = (val&0x1f)|0x20;
  ioctl(fd, PPISECR, &val);

  ioctl(fd, PPIGCTRL, &val);
  val |= PCD;
  val &= ~0x10;
  ioctl(fd, PPISCTRL, &val);

  /*$BF~NO%b!<%I$K$J$C$?$+3NG'(B*/
  val=0x0f;
  ioctl(fd, PPISDATA, &val);
  ioctl(fd, PPIGDATA, &val);
  if(val==0x0f){
    val=0xf0;
    ioctl(fd, PPISDATA, &val);
    ioctl(fd, PPIGDATA, &val);
    if(val==0xf0)return 0;
  }
  return 1;
}
void set_default(){
  ioctl(fd, PPIGDATA, &pp_data);
  ioctl(fd, PPIGCTRL, &pp_ctrl);
  ioctl(fd, PPIGSTATUS, &pp_stat);
}

void set_rclk(u_int8_t in){
  if(!in){
    pp_ctrl |= AUTOFEED;
  }else{
    pp_ctrl &= ~AUTOFEED;
  }
  if(-1==ioctl(fd,PPISCTRL,&pp_ctrl))fault();
}
void set_go(u_int8_t in){
  if(in){
    pp_ctrl |=  nINIT;
  }else{
    pp_ctrl &= ~nINIT;
  }
  if(-1==ioctl(fd,PPISCTRL,&pp_ctrl))fault();
}

u_int8_t get_end(){
  if(-1==ioctl(fd,PPIGSTATUS,&pp_stat))fault();
  if(pp_stat & 8)return 1;
  else return 0;
}
u_int8_t get_ack(){
  if(-1==ioctl(fd,PPIGSTATUS,&pp_stat))fault;
  if(pp_stat & 0x40)return 1;
  else return 0;
}

u_int8_t get_data(){
  if(-1==ioctl(fd,PPIGDATA,&pp_data))fault();
  return pp_data;
}

void dump_data(){
  int i;
  u_int8_t data;
  int seted[8];
  for(i=0;i<8;i++){
    seted[i]=0;
  }


  set_go(1);
  usleep(1000*1000/60);
  while(get_end()==0);
  for(i=0;i<50000;i++){
    int j;
    set_rclk(0);
    while(get_ack()==1)fprintf(stderr,"n0?\n");
    set_rclk(1);
    while(get_ack()==0)fprintf(stderr,"n1?\n");
  
    data=get_data();
    /*$BG[@~$r4V0c$($?;~$K%W%m%0%i%`$GBP=h(B*/
    {
      u_int8_t tmp;
      tmp   = (data & 1) ?   2   :0;
      tmp  |= (data & 2) ?   1   :0;
      tmp  |= (data & 4) ?   8   :0;
      tmp  |= (data & 8) ?   4   :0;
      tmp  |= (data & 16) ?  32  :0;
      tmp  |= (data & 32) ?  16  :0;
      tmp  |= (data & 64) ?  128 :0;
      tmp  |= (data & 128) ? 64  :0;
      data=tmp;
    }
    /*$B3F%S%C%H$,2?2s(BH$B$K$J$C$?$+?t$($F$_$k(B*/
    if(data &1)seted[0]++;
    if(data &2)seted[1]++;
    if(data &4)seted[2]++;
    if(data &8)seted[3]++;
    if(data &16)seted[4]++;
    if(data &32)seted[5]++;
    if(data &64)seted[6]++;
    if(data &128)seted[7]++;
    
    if(data != 255){
      printf("%d\n",(unsigned int)data);
    }else{
      printf("\n");
    }
    
  }

  set_go(0);
  for(i=0;i<8;i++){
    fprintf(stderr,"%d\t%d\n",i,seted[i]);    
  }
}

main(){
  u_int8_t val;
  fd=open("/dev/ppi0",O_RDWR);
  if(fd<0){
    perror("cannt open ");
    return 1;
  }
  
  /*$B%b!<%I@_Dj(B*/
  if(!is_bidir()){
    fprintf(stderr,"It's not bidirection port\n");
    return 1;
  }
  set_default();

  set_go(0);
  set_rclk(0);
  usleep(1); 
  dump_data();
}









