void SMoHVSP::EnterProgmode() { #ifdef DEBUG_HVSP SMoDebugInit(); #endif // const uint8_t stabDelay = SMoCommand::gBody[1]; // const uint8_t cmdexeDelay = SMoCommand::gBody[2]; const uint8_t syncCycles = SMoCommand::gBody[3]; // const uint8_t latchCycles = SMoCommand::gBody[4]; // const uint8_t toggleVtg = SMoCommand::gBody[5]; const uint8_t powoffDelay = SMoCommand::gBody[6]; const uint8_t resetDelay1 = SMoCommand::gBody[7]; const uint8_t resetDelay2 = SMoCommand::gBody[8]; pinMode(HVSP_VCC, OUTPUT); digitalWrite(HVSP_VCC, LOW); digitalWrite(HVSP_RESET, HIGH); // Set BEFORE pinMode, so we don't glitch LOW pinMode(HVSP_RESET, OUTPUT); pinMode(HVSP_SCI, OUTPUT); digitalWrite(HVSP_SCI, LOW); pinMode(HVSP_SDI, OUTPUT); digitalWrite(HVSP_SDI, LOW); pinMode(HVSP_SII, OUTPUT); digitalWrite(HVSP_SII, LOW); pinMode(HVSP_SDO, OUTPUT); // progEnable[2] on tinyX5 digitalWrite(HVSP_SDO, LOW); delay(powoffDelay); digitalWrite(HVSP_VCC, HIGH); delayMicroseconds(80); for (uint8_t i=0; i<syncCycles; ++i) { digitalWrite(HVSP_SCI, HIGH); delayMicroseconds(10); digitalWrite(HVSP_SCI, LOW); } digitalWrite(HVSP_RESET, LOW); delayMicroseconds(1); pinMode(HVSP_SDO, INPUT); SMoCommand::SendResponse(); }
void SMoISP::EnterProgmode() { #ifdef DEBUG_ISP SMoDebugInit(); // SMoDebug.print("Pin layout "); // SMoDebug.print(SMO_LAYOUT); SMoDebug.print(" RESET "); SMoDebug.println(ISP_RESET); #endif // const uint8_t timeOut = SMoCommand::gBody[1]; const uint8_t stabDelay = SMoCommand::gBody[2]; // const uint8_t cmdexeDelay = SMoCommand::gBody[3]; // const uint8_t synchLoops = SMoCommand::gBody[4]; // const uint8_t byteDelay = SMoCommand::gBody[5]; const uint8_t pollValue = SMoCommand::gBody[6]; const uint8_t pollIndex = SMoCommand::gBody[7]; const uint8_t * command = &SMoCommand::gBody[8]; // // Set up SPI // #if SMO_LAYOUT==SMO_LAYOUT_HVPROG2 // make sure that 12V regulator is shutdown digitalWrite(SMO_HVENABLE, LOW); pinMode(SMO_HVENABLE, OUTPUT); #endif // to avoid glitch in SCK and MOSI we must set CPOL before SPI.begin() SPCR &= ~_BV(CPOL) & ~_BV(CPHA); // idle LOW for SPI_MODE0 // SPI.begin(); SPI.beginTransaction(SMoGeneral::gSCKDuration > 2 ? ISPSPISetting[2] : ISPSPISetting[SMoGeneral::gSCKDuration]); ISPAssertReset(); pinMode(ISP_RESET, OUTPUT); delay(stabDelay); // // Set up clock generator on OC1A (OC2A or OC2 if HVPROG2) // pinMode(MCU_CLOCK, OUTPUT); #if SMO_LAYOUT==SMO_LAYOUT_HVPROG2 #ifdef TCCR2 TCCR2 = _BV(COM20) | _BV(WGM21); // Stop Timer 2 TCNT2 = 0xFF; // Initialize counter value OCR2 = SMoGeneral::gClockMatch; // Set compare match value // CTC mode, Toggle OC2 on Compare Match. Set timer operation mode and prescaler TCCR2 = _BV(COM20) | _BV(WGM21) | (0x07 & SMoGeneral::gPrescale); #else TCCR2B = 0; // Stop Timer 2 TCCR2A = _BV(COM2A0) | _BV(WGM21); // CTC mode, Toggle OC2A on Compare Match TCNT2 = 0xFF; // Initialize counter value OCR2A = SMoGeneral::gClockMatch; // Set compare match value TCCR2B = 0x07 & SMoGeneral::gPrescale;// Set timer operation mode and prescaler #endif #else TCCR1B = 0; // Stop clock generator TCCR1A = _BV(COM1A0); // CTC mode, toggle OC1A on comparison with OCR1A OCR1A = 0; // F(OC1A) = 16MHz / (2*8*(1+0)) == 1MHz TIMSK1 = 0; TCCR1B = _BV(WGM12) | _BV(CS11); // Prescale by 8 TCNT1 = 0; #endif // // Now issue the programming mode instruction // digitalWrite(SCK, LOW); uint8_t response = SPITransaction(command, pollIndex-1); if (response != pollValue) { // // Ooops, that's bad. Try again in limp mode // SPI.endTransaction(); SPI.end(); sSPILimpMode = 2; // Start at 16µs, 60kHz bit clock pinMode(MOSI, OUTPUT); pinMode(SCK, OUTPUT); pinMode(MISO, INPUT); do { #ifdef DEBUG_ISP SMoDebug.print("Retrying in limp mode "); SMoDebug.print(sSPILimpMode); SMoDebug.print(" ("); SMoDebug.print(1000.0 / (4 << sSPILimpMode)); SMoDebug.println("kHz)."); #endif ISPDeassertReset(); digitalWrite(SCK, LOW); delay(50); ISPAssertReset(); delay(50); response = SPITransaction(command, pollIndex-1); } while (response != pollValue && sSPILimpMode++ < kMaxLimp); } SMoCommand::SendResponse(response==pollValue ? STATUS_CMD_OK : STATUS_CMD_FAILED); }