Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
+ www.lufa-lib.org
*/
/*
{
if (!(PINB & (1 << 1)))
{
- if (SoftSPI_Data & 0x80)
+ if (SoftSPI_Data & (1 << 7))
PORTB |= (1 << 2);
else
PORTB &= ~(1 << 2);
TCCR1B = 0;
if (PINB & (1 << 3))
- SoftSPI_Data |= 0x01;
+ SoftSPI_Data |= (1 << 0);
}
- PORTB ^= (1 << 1);
+ /* Fast toggle of PORTB.1 via the PIN register (see datasheet) */
+ PINB |= (1 << 1);
}
/** Initialises the appropriate SPI driver (hardware or software, depending on the selected ISP speed) ready for
* communication with the attached target.
*/
-void ISPTarget_Init(void)
+void ISPTarget_EnableTargetISP(void)
{
uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
DDRB |= ((1 << 1) | (1 << 2));
PORTB |= ((1 << 0) | (1 << 3));
- TIMSK1 = (1 << OCIE1A);
- OCR1A = pgm_read_word(&TimerCompareFromSCKDuration[SCKDuration - sizeof(SPIMaskFromSCKDuration)]);
+ ISPTarget_ConfigureSoftwareISP(SCKDuration);
}
}
/** Shuts down the current selected SPI driver (hardware or software, depending on the selected ISP speed) so that no
* further communications can occur until the driver is re-initialized.
*/
-void ISPTarget_ShutDown(void)
+void ISPTarget_DisableTargetISP(void)
{
if (HardwareSPIMode)
{
{
DDRB &= ~((1 << 1) | (1 << 2));
PORTB &= ~((1 << 0) | (1 << 3));
+
+ ISPTarget_ConfigureRescueClock();
}
}
+/** Configures the AVR to produce a .5MHz rescue clock out of the OCR1A pin of the AVR, so
+ * that it can be fed into the XTAL1 pin of an AVR whose fuses have been misconfigured for
+ * an external clock rather than a crystal. When used, the ISP speed must be 125KHz for this
+ * functionality to work correctly.
+ */
+void ISPTarget_ConfigureRescueClock(void)
+{
+ #if defined(XCK_RESCUE_CLOCK_ENABLE)
+ /* Configure XCK as an output for the specified AVR model */
+ DDRD |= (1 << 5);
+
+ /* Start USART to generate a 4MHz clock on the XCK pin */
+ UBRR1 = ((F_CPU / 2 / ISP_RESCUE_CLOCK_SPEED) - 1);
+ UCSR1B = (1 << TXEN1);
+ UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
+ #else
+ /* Configure OCR1A as an output for the specified AVR model */
+ #if defined(USB_SERIES_2_AVR)
+ DDRC |= (1 << 6);
+ #else
+ DDRB |= (1 << 5);
+ #endif
+
+ /* Start Timer 1 to generate a 4MHz clock on the OCR1A pin */
+ TIMSK1 = 0;
+ TCNT1 = 0;
+ OCR1A = ((F_CPU / 2 / ISP_RESCUE_CLOCK_SPEED) - 1);
+ TCCR1A = (1 << COM1A0);
+ TCCR1B = ((1 << WGM12) | (1 << CS10));
+ #endif
+}
+
+/** Configures the AVR's timer ready to produce software ISP for the slower ISP speeds that
+ * cannot be obtained when using the AVR's hardware SPI module.
+ *
+ * \param[in] SCKDuration Duration of the desired software ISP SCK clock
+ */
+void ISPTarget_ConfigureSoftwareISP(const uint8_t SCKDuration)
+{
+ /* Configure Timer 1 for software ISP using the specified SCK duration */
+ TIMSK1 = (1 << OCIE1A);
+ TCNT1 = 0;
+ OCR1A = pgm_read_word(&TimerCompareFromSCKDuration[SCKDuration - sizeof(SPIMaskFromSCKDuration)]);
+ TCCR1A = 0;
+ TCCR1B = 0;
+}
+
/** Sends and receives a single byte of data to and from the attached target via software SPI.
*
* \param[in] Byte Byte of data to send to the attached target