/* Filename: kitsrus.cc Interface to Tony Nixon's PIC Programmers via the Kitsrus protocol This works for Kits 128, 149A, 149B, 150, 182 Copyright (c) 2005, Terran Development Corporation All rights reserved. This code is made available to the public under a BSD-like license, a copy of which should have been provided with this code in the file LICENSE. For a copy of the BSD license template please visit http://www.opensource.org/licenses/bsd-license.php $Id: kitsrus.cc,v 1.4 2007/06/17 05:03:20 bfoz Exp $ * */ #include #include #include "kitsrus.h" #include "intelhex.h" namespace kitsrus { #ifndef Q_WS_WIN #define HIBYTE(a) (uint8_t)(a>>8) #define LOBYTE(a) (uint8_t)(a&0x00FF) #endif //Q_WS_WIN //Switch from power-on mode to command mode bool kitsrus_t::command_mode() { write('P'); if( read() == 'P' ) return true; else return false; } //Do a soft reset of the device //Send a 1 to the device. If it is in the command table it will reset. Either way it should return 'Q' bool kitsrus_t::soft_reset() { //Send a 1 to the device. // If it is in the command table it will reset. Either way it should return 'Q' write(CMD_RESET); if((read()) == 'Q') return true; else return false; } //Do a hard reset of the device bool kitsrus_t::hard_reset() { set_dtr(); //Set DTR high #ifdef Q_WS_WIN //Deal with win32 stupidity Sleep(100); #else usleep(10); //Delay #endif clear_dtr(); //Set DTR low if( read()=='B' ) { read(); //Ignore the firmware type return true; } else return false; } bool kitsrus_t::init_program_vars() { write(CMD_INITVAR); write(HIBYTE(info.rom_size)); write(LOBYTE(info.rom_size)); write(HIBYTE(info.eeprom_size)); write(LOBYTE(info.eeprom_size)); write(info.core_type); //FIXME CoreType uint8_t i = (info.cal_word)?0x01:0x00; i |= (info.band_gap)?0x02:0x00; i |= (info.single_panel)?0x04:0x00; i |= (info.fast_power)?0x08:0x00; write(i); //Program flags write(info.program_delay); write(info.power_sequence); write(info.erase_mode); write(info.program_tries); write(info.over_program); if(read() == 'I') return true; return false; } bool kitsrus_t::chip_power_on() { write(CMD_VPP_ON); if( read() == 'V' ) return true; else return false; } bool kitsrus_t::chip_power_off() { write(CMD_VPP_OFF); if( read() == 'v' ) return true; else return false; } bool kitsrus_t::chip_power_cycle() { write(CMD_VPP_CYCLE); if( read() == 'V' ) return true; else return false; } bool kitsrus_t::write_rom(intelhex::hex_data &HexData) { // uint8_t c; uint8_t i; intelhex::hex_data::address_t j(0); uint16_t k; intelhex::hex_data::size_type size; //Figure out how many ROM words need to be written size = 1 + HexData.max_addr_below(info.rom_size-1); // std::cout << __FUNCTION__ << ": size = " << size << std::endl; //Send program rom command write(CMD_WRITE_ROM); write( (size & 0xFF00) >> 8); //Send size hi write(size & 0x00FF); //Send size low while(1) { switch(read()) { case 'P': // std::cout << ".\n"; emit_callback((j>size)?size:j,size); return true; case 'N': std::cerr << __FUNCTION__ << ": Got N at address "; k = read(); k = k << 8; k |= (0x00FF & read()); std::cerr << std::hex << k; std::cerr << " with word "; k = read(); k = k << 8; k |= (0x00FF & read()); std::cerr << std::hex << k; std::cerr << std::endl; return false; case 'Y': for(i=0; i<(32/2); ++i) { // std::cout << __FUNCTION__ << ": Pre get\n"; const intelhex::hex_data::element a = HexData.get(j, info.get_blank_value()); // std::cout << __FUNCTION__ << ": " << std::hex << a << " @ " << std::hex << j << "\n"; write( (a & 0xFF00) >> 8); write( a & 0x00FF); ++j; } if( !emit_callback((j>size)?size:j,size) ) //Emit callback and check for cancellation return false; // std::cout << "." << std::flush; break; default: std::cerr << __FUNCTION__ << ": Got unexpected character\n"; return false; } } return true; } //#define WRITE_EEPROM_DEBUG bool kitsrus_t::write_eeprom(intelhex::hex_data &HexData) { // uint8_t c; // uint8_t i; intelhex::hex_data::address_t j(info.get_eeprom_start()); intelhex::hex_data::address_t eeprom_start(info.get_eeprom_start()); intelhex::hex_data::address_t eeprom_end; uint16_t progress; intelhex::hex_data::size_type size; //Ideally we would figure out how many ROM words are going to be written // and then write only that. But, to make things simpler we'll just write // to all of the ROM. #if defined(WRITE_EEPROM_DEBUG) std::cout << __FUNCTION__ << ": eeprom_start = " << std::hex << j << std::endl; std::cout << __FUNCTION__ << ": eeprom_size = " << std::hex << info.eeprom_size << std::endl; #endif size = HexData.size_in_range(j, info.get_eeprom_start() + info.eeprom_size); //Make size an even number if( (size % 2) != 0 ) ++size; eeprom_end = j + size - 1; #if defined(WRITE_EEPROM_DEBUG) std::cout << __FUNCTION__ << ": size = " << size << std::endl; std::cout << __FUNCTION__ << ": eeprom_end = " << std::hex << eeprom_end << std::endl; #endif //Send program rom command write(CMD_WRITE_EEPROM); write( (size & 0xFF00) >> 8); //Send size hi write(size & 0x00FF); //Send size low while(1) { switch(read()) { case 'P': // std::cout << ".\n"; emit_callback((progress>size)?size:progress,size); return true; case 'Y': #if !defined(WRITE_EEPROM_DEBUG) // std::cout << "." << std::flush; #endif write( HexData.get(j, 0xFF) & 0x00FF); #if defined(WRITE_EEPROM_DEBUG) std::cout << __FUNCTION__ << ": wrote " << std::hex << HexData[j] << "\n"; #endif ++j; write( HexData.get(j, 0xFF) & 0x00FF); #if defined(WRITE_EEPROM_DEBUG) std::cout << __FUNCTION__ << ": wrote " << std::hex << HexData[j] << "\n"; #endif ++j; progress = j - eeprom_start; if( !emit_callback((progress>size)?size:progress,size) ) //Emit callback and check for cancellation return false; break; default: std::cerr << __FUNCTION__ << ": Got unexpected character\n"; return false; } } return true; } bool kitsrus_t::write_config(intelhex::hex_data &HexData) { std::vector tmp_config(22, 0xFF); // std::cout << __FUNCTION__ << std::endl; intelhex::hex_data::address_t i; if( info.is14bit() ) { //If the ID bits were specified use them // otherwise use blanks i = info.get_id_start(); if( HexData.isset(i) ) { tmp_config[0] = HexData[i++]; tmp_config[1] = HexData[i++]; tmp_config[2] = HexData[i++]; tmp_config[3] = HexData[i]; } tmp_config[4] = 'F'; tmp_config[5] = 'F'; tmp_config[6] = 'F'; tmp_config[7] = 'F'; i = info.get_config_start(); if( HexData.isset(i) ) { tmp_config[8] = HexData[i] & 0x00FF; tmp_config[9] = (HexData[i] & 0xFF00) >> 8; } else { std::cerr << __FUNCTION__ << ": no config bits\n"; return false; //FIXME } } write(CMD_WRITE_CONFIG); write('0'); write('0'); for( i=0; i<22; ++i) { write(tmp_config[i]); if( !emit_callback(i+1+2, 22+2) ) //Emit callback and check for cancellation return false; } // std::cout << __FUNCTION__ << "1" << std::endl; read(); //Throw away the ack // std::cout << __FUNCTION__ << "2" << std::endl; return true; } void kitsrus_t::write_calibration() {} //Read from a PIC into a hex_data structure bool kitsrus_t::read_rom(intelhex::hex_data &HexData) { intelhex::hex_data::element a; write(CMD_READ_ROM); // std::cout << "About to read " << info.rom_size << " words\n"; for(unsigned i=0; i