#include <stdexcept>
#include "dude.h"
	
std::vector<ProgrammerInfo> dude_programmers;
std::vector<PartInfo> dude_parts;

static void addpart(const std::string & name) {
    dude_parts.push_back(PartInfo());
    dude_parts.back().name = name;
    dude_parts.back().desc = name;
    dude_parts.back().cfgname = name;
    dude_parts.back().cfglineno = 0;
}

static void addprogrammer(const std::string & name) {
    dude_programmers.push_back(ProgrammerInfo());
    dude_programmers.back().name = name;
    dude_programmers.back().desc = name;
    dude_programmers.back().cfgname = name;
    dude_programmers.back().cfglineno = 0;
}

void dude_initialize() {
    addprogrammer("progbob-armswd");
    addpart("efm32");

    addprogrammer("avrispv2");
    addprogrammer("progbob-avrisp");
    addpart("atmega48a");
    addpart("atmega48pa");
    addpart("atmega8");
    addpart("atmega88");
    addpart("atmega88a");
    addpart("atmega88pa");
    addpart("atmega168");
    addpart("atmega168a");
    addpart("atmega168pa");
    addpart("atmega328");
    addpart("atmega328p");
}

void dude_loadAvrProgrammerConfig(AvrProgrammerConfig & cfg, const std::string & name) {
    if (name=="atmega48a") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega4");
        cfg.part_signature=0x1e9205;
        
    } else if (name=="atmega48pa") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega4");
        cfg.part_signature=0x1e920a;
        
    } else if (name=="atmega8") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e9307;
        
    } else if (name=="atmega88") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e930a;
        
    } else if (name=="atmega88a") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e930a;
        
    } else if (name=="atmega88pa") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e930f;
        
    } else if (name=="atmega168") { 
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e9406;
        
    } else if (name=="atmega168a") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e9406;
        
    } else if (name=="atmega168pa") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e940b;
        
    } else if (name=="atmega328") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e9514;
        
    } else if (name=="atmega328p") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmega8");
        cfg.part_signature=0x1e950f;

    } else if (name=="__base_atmegaXX") {
        cfg.isp_enter_timeout = 205;
        cfg.isp_enter_stabDelay = 100;
        cfg.isp_enter_cmdexeDelay =25;
        cfg.isp_enter_synchLoops = 32;
        cfg.isp_enter_byteDelay = 0;
        cfg.isp_enter_pollValue = 0x53;
        cfg.isp_enter_pollIndex = 3;
        cfg.isp_enter_cmd1 = 0xac;
        cfg.isp_enter_cmd2 = 0x53;
        cfg.isp_enter_cmd3 = 0x00;
        cfg.isp_enter_cmd4 = 0x00;
        cfg.isp_leave_preDelay = 1;
        cfg.isp_leave_postDelay = 1;
        cfg.isp_erase_eraseDelay = 9;
        cfg.isp_erase_pollMethod = 0;
        cfg.isp_erase_cmd1 = 0xac;
        cfg.isp_erase_cmd2 = 0x80;
        cfg.isp_erase_cmd3 = 0x00;
        cfg.isp_erase_cmd4 = 0x00;

        cfg.isp_program_flash_mode = 0xc1;
        cfg.isp_program_flash_delay = 6;
        cfg.isp_program_flash_cmd1 = 0x40;
        cfg.isp_program_flash_cmd2 = 0x4c;
        cfg.isp_program_flash_cmd3 = 0x20;
        cfg.isp_program_flash_poll1 = 0xff;
        cfg.isp_program_flash_poll2 = 0xff;
        cfg.isp_read_flash_cmd1 = 0x20;
        cfg.isp_program_eeprom_mode;
        cfg.isp_program_eeprom_delay;
        cfg.isp_program_eeprom_cmd1;
        cfg.isp_program_eeprom_cmd2;
        cfg.isp_program_eeprom_cmd3;
        cfg.isp_program_eeprom_poll1;
        cfg.isp_program_eeprom_poll2;
        cfg.isp_read_eeprom_cmd1 = 0xa0;
        cfg.isp_program_fuse_cmd1;
        cfg.isp_program_fuse_cmd2;
        cfg.isp_program_fuse_cmd3;
        cfg.isp_program_fuse_cmd4;
        cfg.isp_read_fuse_RetAddr = 4;
        cfg.isp_read_fuse_cmd1 = 0x50;
        cfg.isp_read_fuse_cmd2 = 0x00;
        cfg.isp_read_fuse_cmd3 = 0x00;
        cfg.isp_read_fuse_cmd4 = 0x00;
        cfg.isp_program_lock_cmd1;
        cfg.isp_program_lock_cmd2;
        cfg.isp_program_lock_cmd3;
        cfg.isp_program_lock_cmd4;
        cfg.isp_read_lock_RetAddr = 4;
        cfg.isp_read_lock_cmd1 = 0x58;
        cfg.isp_read_lock_cmd2 = 0x00;
        cfg.isp_read_lock_cmd3 = 0x00;
        cfg.isp_read_lock_cmd4 = 0x00;
        cfg.isp_read_signature_RetAddr = 4;
        cfg.isp_read_signature_cmd1 = 0x30;
        cfg.isp_read_signature_cmd2 = 0x00;
        cfg.isp_read_signature_cmd3 = 0x00;
        cfg.isp_read_signature_cmd4 = 0x00;
        cfg.isp_read_osccal_RetAddr = 4;
        cfg.isp_read_osccal_cmd1 = 0x38;
        cfg.isp_read_osccal_cmd2 = 0x00;
        cfg.isp_read_osccal_cmd3 = 0x00;
        cfg.isp_read_osccal_cmd4 = 0x00;
        
    } else if (name=="__base_atmega4") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmegaXX");
        cfg.part_flash_pagesize = 64;
        cfg.part_flash_pagecount = 64;
        cfg.part_eeprom_pagesize = 4;
        cfg.part_eeprom_pagecount = 64;
        
    } else if (name=="__base_atmega8") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmegaXX");
        cfg.part_flash_pagesize = 64;
        cfg.part_flash_pagecount = 128;
        cfg.part_eeprom_pagesize = 4;
        cfg.part_eeprom_pagecount = 128;
        
    } else if (name=="__base_atmega16") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmegaXX");
        cfg.part_flash_pagesize = 128;
        cfg.part_flash_pagecount = 128;
        cfg.part_eeprom_pagesize = 4;
        cfg.part_eeprom_pagecount = 128;
        
    } else if (name=="__base_atmega32") {
        dude_loadAvrProgrammerConfig(cfg, "__base_atmegaXX");
        cfg.part_flash_pagesize = 128;
        cfg.part_flash_pagecount = 256;
        cfg.part_eeprom_pagesize = 4;
        cfg.part_eeprom_pagecount = 256;
        
    } else {
        throw std::runtime_error("unknown microcontroller type");
    }
    
    cfg.name=name;
}

