6767#include "ft245r.h"
6868#include "usbdevs.h"
6969
70+ #include "tpi.h"
71+
72+ #define TPIPCR_GT_0b 0x07
73+ #define TPI_STOP_BITS 0x03
74+
7075#if defined(_WIN32 )
7176#include <windows.h>
7277#endif
@@ -241,6 +246,9 @@ static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) {
241246 unsigned char cmd [4 ] = {0 ,0 ,0 ,0 };
242247 unsigned char res [4 ];
243248
249+ if (p -> flags & AVRPART_HAS_TPI )
250+ return avr_tpi_chip_erase (pgm , p );
251+
244252 if (p -> op [AVR_OP_CHIP_ERASE ] == NULL ) {
245253 avrdude_message (MSG_INFO , "chip erase instruction not defined for part \"%s\"\n" ,
246254 p -> desc );
@@ -280,6 +288,16 @@ static int ft245r_set_bitclock(PROGRAMMER * pgm) {
280288 return 0 ;
281289}
282290
291+ static int get_pin (PROGRAMMER * pgm , int pinname ) {
292+ uint8_t byte ;
293+
294+ if (ftdi_read_pins (handle , & byte ) != 0 )
295+ return -1 ;
296+ if (FT245R_DEBUG )
297+ avrdude_message (MSG_INFO , "%s: in 0x%02x\n" , __func__ , byte );
298+ return GET_BITS_0 (byte , pgm , pinname ) != 0 ;
299+ }
300+
283301static int set_pin (PROGRAMMER * pgm , int pinname , int val ) {
284302 unsigned char buf [1 ];
285303
@@ -375,6 +393,8 @@ static void ft245r_enable(PROGRAMMER * pgm) {
375393
376394static int ft245r_cmd (PROGRAMMER * pgm , const unsigned char * cmd ,
377395 unsigned char * res );
396+ static int ft245r_tpi_tx (PROGRAMMER * pgm , uint8_t byte );
397+ static int ft245r_tpi_rx (PROGRAMMER * pgm , uint8_t * bytep );
378398/*
379399 * issue the 'program enable' command to the AVR device
380400 */
@@ -383,6 +403,9 @@ static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p) {
383403 unsigned char res [4 ];
384404 int i ;
385405
406+ if (p -> flags & AVRPART_HAS_TPI )
407+ return avr_tpi_program_enable (pgm , p , TPIPCR_GT_0b );
408+
386409 if (p -> op [AVR_OP_PGM_ENABLE ] == NULL ) {
387410 avrdude_message (MSG_INFO , "%s: AVR_OP_PGM_ENABLE command not defined for %s\n" ,
388411 progname , p -> desc );
@@ -443,25 +466,73 @@ static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p) {
443466 */
444467 usleep (20000 ); // 20ms
445468
469+ if (p -> flags & AVRPART_HAS_TPI ) {
470+ bool io_link_ok = true;
471+ uint8_t byte ;
472+ int i ;
473+
474+ /* Since there is a single TPIDATA line, MOSI and MISO must be
475+ linked together through a 1kOhm resistor. Verify that
476+ everything we send on MOSI gets mirrored back on MISO. */
477+ set_pin (pgm , PIN_AVR_MOSI , 0 );
478+ if (get_pin (pgm , PIN_AVR_MISO ) != 0 ) {
479+ io_link_ok = false;
480+ avrdude_message (MSG_INFO , "MOSI->MISO 0 failed\n" );
481+ if (!ovsigck )
482+ return -1 ;
483+ }
484+ set_pin (pgm , PIN_AVR_MOSI , 1 );
485+ if (get_pin (pgm , PIN_AVR_MISO ) != 1 ) {
486+ io_link_ok = false;
487+ avrdude_message (MSG_INFO , "MOSI->MISO 1 failed\n" );
488+ if (!ovsigck )
489+ return -1 ;
490+ }
491+
492+ if (io_link_ok )
493+ avrdude_message (MSG_NOTICE2 , "MOSI-MISO link present\n" );
494+
495+ /* keep TPIDATA high for 16 clock cycles */
496+ set_pin (pgm , PIN_AVR_MOSI , 1 );
497+ for (i = 0 ; i < 16 ; i ++ ) {
498+ set_sck (pgm , 1 );
499+ set_sck (pgm , 0 );
500+ }
501+
502+ /* remove extra guard timing bits */
503+ ft245r_tpi_tx (pgm , TPI_CMD_SSTCS | TPI_REG_TPIPCR );
504+ ft245r_tpi_tx (pgm , 0x7 );
505+
506+ /* read TPI ident reg */
507+ ft245r_tpi_tx (pgm , TPI_CMD_SLDCS | TPI_REG_TPIIR );
508+ ft245r_tpi_rx (pgm , & byte );
509+ if (byte != 0x80 ) {
510+ avrdude_message (MSG_INFO , "TPIIR 0x%02x not correct\n" , byte );
511+ return -1 ;
512+ }
513+ }
446514 return ft245r_program_enable (pgm , p );
447515}
448516
517+ static inline void add_bit (PROGRAMMER * pgm , unsigned char * buf , int * buf_pos ,
518+ uint8_t bit ) {
519+ ft245r_out = SET_BITS_0 (ft245r_out ,pgm ,PIN_AVR_MOSI , bit );
520+ ft245r_out = SET_BITS_0 (ft245r_out ,pgm ,PIN_AVR_SCK ,0 );
521+ buf [* buf_pos ] = ft245r_out ;
522+ (* buf_pos )++ ;
523+
524+ ft245r_out = SET_BITS_0 (ft245r_out ,pgm ,PIN_AVR_SCK ,1 );
525+ buf [* buf_pos ] = ft245r_out ;
526+ (* buf_pos )++ ;
527+ }
528+
449529static inline int set_data (PROGRAMMER * pgm , unsigned char * buf , unsigned char data ) {
450530 int j ;
451531 int buf_pos = 0 ;
452532 unsigned char bit = 0x80 ;
453533
454534 for (j = 0 ; j < 8 ; j ++ ) {
455- ft245r_out = SET_BITS_0 (ft245r_out ,pgm ,PIN_AVR_MOSI ,data & bit );
456-
457- ft245r_out = SET_BITS_0 (ft245r_out ,pgm ,PIN_AVR_SCK ,0 );
458- buf [buf_pos ] = ft245r_out ;
459- buf_pos ++ ;
460-
461- ft245r_out = SET_BITS_0 (ft245r_out ,pgm ,PIN_AVR_SCK ,1 );
462- buf [buf_pos ] = ft245r_out ;
463- buf_pos ++ ;
464-
535+ add_bit (pgm , buf , & buf_pos , (data & bit ) != 0 );
465536 bit >>= 1 ;
466537 }
467538 return buf_pos ;
@@ -532,6 +603,123 @@ static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
532603 return 0 ;
533604}
534605
606+ static inline uint8_t extract_tpi_data (PROGRAMMER * pgm , unsigned char * buf ,
607+ int * buf_pos ) {
608+ uint8_t bit = 0x1 , byte = 0 ;
609+ int j ;
610+
611+ for (j = 0 ; j < 8 ; j ++ ) {
612+ (* buf_pos )++ ; // skip over falling clock edge
613+ if (GET_BITS_0 (buf [(* buf_pos )++ ], pgm , PIN_AVR_MISO ))
614+ byte |= bit ;
615+ bit <<= 1 ;
616+ }
617+ return byte ;
618+ }
619+
620+ static inline int set_tpi_data (PROGRAMMER * pgm , unsigned char * buf ,
621+ uint8_t byte ) {
622+ uint8_t bit = 0x1 , parity = 0 ;
623+ int j , buf_pos = 0 ;
624+
625+ // start bit:
626+ add_bit (pgm , buf , & buf_pos , 0 );
627+
628+ // 8 data bits:
629+ for (j = 0 ; j < 8 ; j ++ ) {
630+ add_bit (pgm , buf , & buf_pos , (byte & bit ) != 0 );
631+ parity ^= (byte & bit ) != 0 ;
632+ bit <<= 1 ;
633+ }
634+
635+ // parity bit:
636+ add_bit (pgm , buf , & buf_pos , parity );
637+ // stop bits:
638+ add_bit (pgm , buf , & buf_pos , 1 );
639+ add_bit (pgm , buf , & buf_pos , 1 );
640+ return buf_pos ;
641+ }
642+
643+ static int ft245r_tpi_tx (PROGRAMMER * pgm , uint8_t byte ) {
644+ uint8_t buf [128 ];
645+ int len ;
646+
647+ len = set_tpi_data (pgm , buf , byte );
648+ ft245r_send (pgm , buf , len );
649+ ft245r_recv (pgm , buf , len );
650+ return 0 ;
651+ }
652+
653+ static int ft245r_tpi_rx (PROGRAMMER * pgm , uint8_t * bytep ) {
654+ uint8_t buf [128 ], bit , parity ;
655+ int i , buf_pos = 0 , len = 0 ;
656+ uint32_t res , m , byte ;
657+
658+ /* Allow for up to 4 bits before we must see start bit; during
659+ that time, we must keep the MOSI line high. */
660+ for (i = 0 ; i < 2 ; ++ i )
661+ len += set_data (pgm , & buf [len ], 0xff );
662+
663+ ft245r_send (pgm , buf , len );
664+ ft245r_recv (pgm , buf , len );
665+
666+ res = (extract_tpi_data (pgm , buf , & buf_pos )
667+ | ((uint32_t ) extract_tpi_data (pgm , buf , & buf_pos ) << 8 ));
668+
669+ /* Look for start bit: */
670+ m = 0x1 ;
671+ while (m & res )
672+ m <<= 1 ;
673+ if (m >= 0x10 ) {
674+ avrdude_message (MSG_INFO , "%s: start bit missing (res=0x%04x)\n" ,
675+ __func__ , res );
676+ return -1 ;
677+ }
678+ byte = parity = 0 ;
679+ for (i = 0 ; i < 8 ; ++ i ) {
680+ m <<= 1 ;
681+ bit = (res & m ) != 0 ;
682+ parity ^= bit ;
683+ byte |= bit << i ;
684+ }
685+ m <<= 1 ;
686+ if (((res & m ) != 0 ) != parity ) {
687+ avrdude_message (MSG_INFO , "%s: parity bit wrong\n" , __func__ );
688+ return -1 ;
689+ }
690+ if (((res & (m << 1 )) == 0 ) || ((res & (m << 2 ))) == 0 ) {
691+ avrdude_message (MSG_INFO , "%s: stop bits wrong\n" , __func__ );
692+ return -1 ;
693+ }
694+ * bytep = (uint8_t ) byte ;
695+ return 0 ;
696+ }
697+
698+ static int ft245r_cmd_tpi (PROGRAMMER * pgm , const unsigned char * cmd ,
699+ int cmd_len , unsigned char * res , int res_len ) {
700+ int i , ret = 0 ;
701+
702+ pgm -> pgm_led (pgm , ON );
703+
704+ for (i = 0 ; i < cmd_len ; ++ i )
705+ ft245r_tpi_tx (pgm , cmd [i ]);
706+ for (i = 0 ; i < res_len ; ++ i )
707+ if ((ret = ft245r_tpi_rx (pgm , & res [i ])) < 0 )
708+ break ;
709+ if (verbose >= 2 ) {
710+ avrdude_message (MSG_NOTICE2 , "%s: [ " , __func__ );
711+ for (i = 0 ; i < cmd_len ; i ++ )
712+ avrdude_message (MSG_NOTICE2 , "%02X " , cmd [i ]);
713+ avrdude_message (MSG_NOTICE2 , "] [ " );
714+ for (i = 0 ; i < res_len ; i ++ )
715+ avrdude_message (MSG_NOTICE2 , "%02X " , res [i ]);
716+ avrdude_message (MSG_NOTICE2 , "]\n" );
717+ }
718+
719+ pgm -> pgm_led (pgm , OFF );
720+ return ret ;
721+ }
722+
535723/* lower 8 pins are accepted, they might be also inverted */
536724static const struct pindef_t valid_pins = {{0xff },{0xff }} ;
537725
@@ -985,6 +1173,7 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
9851173 pgm -> program_enable = ft245r_program_enable ;
9861174 pgm -> chip_erase = ft245r_chip_erase ;
9871175 pgm -> cmd = ft245r_cmd ;
1176+ pgm -> cmd_tpi = ft245r_cmd_tpi ;
9881177 pgm -> open = ft245r_open ;
9891178 pgm -> close = ft245r_close ;
9901179 pgm -> read_byte = avr_read_byte_default ;
0 commit comments