|
|
|
|
@ -10,8 +10,6 @@ volatile uint8_t main_loop=1; |
|
|
|
|
|
|
|
|
|
static int vendor=0x0403, device=0x6001; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int is_output(unsigned offset){ |
|
|
|
|
return !!((USB_GPIO_DDR)&(1<<offset)); |
|
|
|
|
} |
|
|
|
|
@ -20,74 +18,90 @@ static int is_high(unsigned offset){ |
|
|
|
|
return !!((USB_GPIO_PORT)&(1<<offset)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
This will update the data direction according to the current |
|
|
|
|
USB_GPIO_DDR value |
|
|
|
|
*/ |
|
|
|
|
static int update_mode(void){ |
|
|
|
|
if( ftdi_set_bitmode(&ftdic, USB_GPIO_DDR, BITMODE_BITBANG)<0 ){ |
|
|
|
|
printf("%s: Can't enter FTDIs bitbang mode (%04x:%04x)!\n",MOD_NAME,vendor,device); |
|
|
|
|
printf("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
LOG("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
return -EIO; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
If in output this will allways return 0 |
|
|
|
|
in input it will return the logic level of the pin |
|
|
|
|
*/ |
|
|
|
|
static int get_value(unsigned offset){ |
|
|
|
|
DEBUG_OUT("%s: GET_VALUE of pin%d ",MOD_NAME,offset); |
|
|
|
|
DEBUG_OUT("%s: GET_VALUE of pin%d\n",MOD_NAME,offset); |
|
|
|
|
|
|
|
|
|
if( !is_output(offset) ){ |
|
|
|
|
while( ftdic.readbuffer_remaining > 0 ){ |
|
|
|
|
if( ftdi_read_data(&ftdic,&USB_GPIO_PIN,1) < 0){ |
|
|
|
|
printf("%s: Unable to read pin%d \n",MOD_NAME,offset); |
|
|
|
|
} |
|
|
|
|
if( ftdi_read_pins(&ftdic,&USB_GPIO_PIN) < 0){ |
|
|
|
|
LOG("%s: Unable to read pin%d \n",MOD_NAME,offset); |
|
|
|
|
} |
|
|
|
|
return !!((USB_GPIO_PIN) & (1<<offset)); |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
If in input this will turn on/off the pullup |
|
|
|
|
in output it will simply turn on/off the logic level of the pin |
|
|
|
|
*/ |
|
|
|
|
static void set_value(unsigned offset, int value){ |
|
|
|
|
DEBUG_OUT("%s: SET_VALUE of pin%d to %d",MOD_NAME,offset,value); |
|
|
|
|
DEBUG_OUT("%s: SET_VALUE of pin%d to %d\n",MOD_NAME,offset,value); |
|
|
|
|
|
|
|
|
|
if( !is_output(offset) ){ |
|
|
|
|
if(value && !is_high(offset)){ |
|
|
|
|
if( ftdi_write_data(&ftdic,&USB_GPIO_PORT,1) < 0){ |
|
|
|
|
printf("%s: Unable to set pin%d to value %d\n",MOD_NAME,offset,value); |
|
|
|
|
if(value){ |
|
|
|
|
USB_GPIO_PORT |= (1<<offset); |
|
|
|
|
}else{ |
|
|
|
|
USB_GPIO_PORT &= ~(1<<offset); |
|
|
|
|
} |
|
|
|
|
}else if(!value && is_high(offset)){ |
|
|
|
|
if( ftdi_write_data(&ftdic,&USB_GPIO_PORT,1) < 0){ |
|
|
|
|
printf("%s: Unable to set pin%d to value %d\n",MOD_NAME,offset,value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
LOG("%s: Unable to set pin%d to value %d\n",MOD_NAME,offset,value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
This will set the pin as input.
|
|
|
|
|
Warning: if the pin is HIGH at the moment you put the pin to input |
|
|
|
|
the pull-up of that pin will be enabled |
|
|
|
|
*/ |
|
|
|
|
static int set_in(unsigned offset){ |
|
|
|
|
DEBUG_OUT("%s: SET_INPUT of pin%d ",MOD_NAME,offset); |
|
|
|
|
DEBUG_OUT("%s: SET_INPUT of pin%d\n",MOD_NAME,offset); |
|
|
|
|
|
|
|
|
|
USB_GPIO_DDR &= ~(1<<offset);
|
|
|
|
|
return update_mode(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
This will set the pin as output and drive its logic level according |
|
|
|
|
to value. |
|
|
|
|
*/ |
|
|
|
|
static int set_out(unsigned offset, int value){ |
|
|
|
|
DEBUG_OUT("%s: SET_OUTPUT of pin%d to %d",MOD_NAME,offset,value); |
|
|
|
|
DEBUG_OUT("%s: SET_OUTPUT of pin%d to %d\n",MOD_NAME,offset,value); |
|
|
|
|
|
|
|
|
|
USB_GPIO_DDR |= (1<<offset);
|
|
|
|
|
set_value(offset,value); |
|
|
|
|
return update_mode(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ftdi_chip_init(){ |
|
|
|
|
// Init FTDI lib
|
|
|
|
|
DEBUG_OUT("INIT libftdi\n");
|
|
|
|
|
if( ftdi_init(&ftdic)<0 ){ |
|
|
|
|
printf("%s: Can't initialize FTDI-lib!\n",MOD_NAME); |
|
|
|
|
LOG("%s: Can't initialize FTDI-lib!\n",MOD_NAME); |
|
|
|
|
return ENOMEM; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Open device
|
|
|
|
|
DEBUG_OUT("Opening device (%04x:%04x) \n",vendor,device);
|
|
|
|
|
if(ftdi_usb_open(&ftdic, vendor, device)<0) { |
|
|
|
|
printf("%s: Can't open FTDI chip (%04x:%04x)!\n",MOD_NAME,vendor,device); |
|
|
|
|
printf("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
LOG("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
return ENXIO; |
|
|
|
|
} |
|
|
|
|
// Put device into bitbang modes
|
|
|
|
|
if( ftdi_set_bitmode(&ftdic, 0x00, BITMODE_BITBANG)<0 ){ |
|
|
|
|
printf("%s: Can't enter FTDIs bitbang mode (%04x:%04x)!\n",MOD_NAME,vendor,device); |
|
|
|
|
printf("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
return EIO; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//All pins input
|
|
|
|
|
@ -95,14 +109,68 @@ static int ftdi_chip_init(){ |
|
|
|
|
//No port set
|
|
|
|
|
USB_GPIO_PORT = 0x00; |
|
|
|
|
|
|
|
|
|
// Put device into bitbang mode
|
|
|
|
|
DEBUG_OUT("Putting device (%04x:%04x) into bitbang mode\n",vendor,device);
|
|
|
|
|
if( ftdi_set_bitmode(&ftdic, 0x00, BITMODE_BITBANG)<0 ){ |
|
|
|
|
printf("%s: Can't enter FTDIs bitbang mode (%04x:%04x)!\n",MOD_NAME,vendor,device); |
|
|
|
|
LOG("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
return EIO; |
|
|
|
|
} |
|
|
|
|
// Set all pins low
|
|
|
|
|
if( ftdi_write_data(&ftdic,&USB_GPIO_PORT,1) < 0){ |
|
|
|
|
LOG("%s: Unable to set pins to low\n",MOD_NAME); |
|
|
|
|
return EIO; |
|
|
|
|
}
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ftdi_chip_exit(){ |
|
|
|
|
if( ftdi_disable_bitbang(&ftdic)<0 ){ |
|
|
|
|
printf("%s: Can't reset FTDI (%04x:%04x)!\n",MOD_NAME,vendor,device); |
|
|
|
|
LOG("%s: Can't reset FTDI (%04x:%04x)!\n",MOD_NAME,vendor,device); |
|
|
|
|
} |
|
|
|
|
if( ftdi_usb_close(&ftdic) < 0){ |
|
|
|
|
LOG("%s: Unable to close FTDI-Device!\n",MOD_NAME); |
|
|
|
|
LOG("%s: %s\n",MOD_NAME,ftdi_get_error_string(&ftdic)); |
|
|
|
|
} |
|
|
|
|
ftdi_deinit(&ftdic); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum cmd_states {CMD_PORT_NUM, CMD_CMD}; |
|
|
|
|
|
|
|
|
|
static int cmd_fsm(char c){ |
|
|
|
|
static int state = CMD_PORT_NUM; |
|
|
|
|
static char pin = 0; |
|
|
|
|
int ret; |
|
|
|
|
switch(state){ |
|
|
|
|
case CMD_PORT_NUM: |
|
|
|
|
pin=c; |
|
|
|
|
state=CMD_CMD; |
|
|
|
|
break; |
|
|
|
|
case CMD_CMD: |
|
|
|
|
state = CMD_PORT_NUM; |
|
|
|
|
// Pin commands
|
|
|
|
|
switch(c){ |
|
|
|
|
case CMD_IN: |
|
|
|
|
return set_in((unsigned)pin); |
|
|
|
|
case CMD_OUTH: |
|
|
|
|
return set_out((unsigned)pin,1); |
|
|
|
|
case CMD_OUTL: |
|
|
|
|
return set_out((unsigned)pin,0); |
|
|
|
|
case CMD_H: |
|
|
|
|
set_value((unsigned)pin,1); |
|
|
|
|
return 0; |
|
|
|
|
case CMD_L: |
|
|
|
|
set_value((unsigned)pin,0); |
|
|
|
|
return 0; |
|
|
|
|
case CMD_READ: |
|
|
|
|
ret = get_value((unsigned)pin); |
|
|
|
|
DEBUG_OUT("Value of %d is %d\n", pin,ret); |
|
|
|
|
fputc((char)ret,stdout); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int main(void){ |
|
|
|
|
int ret=ftdi_chip_init(); |
|
|
|
|
@ -111,7 +179,13 @@ int main(void){ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for(;main_loop;){ |
|
|
|
|
//Sleep mostly
|
|
|
|
|
//kernel will write commands to the stdin
|
|
|
|
|
ret = fgetc(stdin); |
|
|
|
|
if( ret!=EOF ){ |
|
|
|
|
cmd_fsm(ret); |
|
|
|
|
}else{ |
|
|
|
|
//main_loop=0;
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ftdi_chip_exit(); |
|
|
|
|
|