Bugfix SPI-Clock too high for 16 MHz firmware
[pub/USBasp.git] / firmware / isp.c
index 50e6a26..fa6c7be 100644 (file)
@@ -17,6 +17,7 @@
 #define spiHWdisable() SPCR = 0
 
 uchar sck_sw_delay;
 #define spiHWdisable() SPCR = 0
 
 uchar sck_sw_delay;
+uchar sck_sw_delay_loops;
 uchar sck_spcr;
 uchar sck_spsr;
 uchar isp_hiaddr;
 uchar sck_spcr;
 uchar sck_spsr;
 uchar isp_hiaddr;
@@ -31,67 +32,102 @@ void ispSetSCKOption(uchar option) {
        if (option == USBASP_ISP_SCK_AUTO)
                option = USBASP_ISP_SCK_375;
 
        if (option == USBASP_ISP_SCK_AUTO)
                option = USBASP_ISP_SCK_375;
 
-       if (option >= USBASP_ISP_SCK_93_75) {
+       if (((F_CPU <= 12000000) && (option >= USBASP_ISP_SCK_93_75))
+        || ((F_CPU > 12000000) && (option >= USBASP_ISP_SCK_187_5))) {
                ispTransmit = ispTransmit_hw;
                sck_spsr = 0;
                sck_sw_delay = 1;       /* force RST#/SCK pulse for 320us */
                ispTransmit = ispTransmit_hw;
                sck_spsr = 0;
                sck_sw_delay = 1;       /* force RST#/SCK pulse for 320us */
+               sck_sw_delay_loops = 1;
 
                switch (option) {
 
                case USBASP_ISP_SCK_1500:
 
                switch (option) {
 
                case USBASP_ISP_SCK_1500:
-                       /* enable SPI, master, 1.5MHz, XTAL/8 */
-                       sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
-                       sck_spsr = (1 << SPI2X);
+#                      if (F_CPU <= 12000000)
+                               /* enable SPI, master, 1.5MHz, XTAL/8 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+                               sck_spsr = (1 << SPI2X);
+#                      else
+                               /* enable SPI, master, ~1.1MHz, XTAL/16 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+#                      endif
+                       break;
                case USBASP_ISP_SCK_750:
                case USBASP_ISP_SCK_750:
-                       /* enable SPI, master, 750kHz, XTAL/16 */
-                       sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+#                      if (F_CPU <= 12000000)
+                               /* enable SPI, master, 750kHz, XTAL/16 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+#                      else
+                               /* enable SPI, master, ~531kHz, XTAL/32 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+                               sck_spsr = (1 << SPI2X);
+#                      endif
                        break;
                case USBASP_ISP_SCK_375:
                default:
                        break;
                case USBASP_ISP_SCK_375:
                default:
-                       /* enable SPI, master, 375kHz, XTAL/32 (default) */
-                       sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
-                       sck_spsr = (1 << SPI2X);
+#                      if (F_CPU <= 12000000)
+                               /* enable SPI, master, 375kHz, XTAL/32 (default) */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+                               sck_spsr = (1 << SPI2X);
+#                      else
+                               /* enable SPI, master, ~265.6kHz XTAL/64 (default) */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+#                      endif
                        break;
                case USBASP_ISP_SCK_187_5:
                        break;
                case USBASP_ISP_SCK_187_5:
-                       /* enable SPI, master, 187.5kHz XTAL/64 */
-                       sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
-                       break;
-               case USBASP_ISP_SCK_93_75:
-                       /* enable SPI, master, 93.75kHz XTAL/128 */
-                       sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+#                      if (F_CPU <= 12000000)
+                               /* enable SPI, master, 187.5kHz XTAL/64 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+#                      else
+                               /* enable SPI, master, ~132.81kHz XTAL/128 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+#                      endif
                        break;
                        break;
+#              if (F_CPU <= 12000000)
+                       case USBASP_ISP_SCK_93_75:
+                               /* enable SPI, master, 93.75kHz XTAL/128 */
+                               sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+                               break;
+#              endif
                }
 
        } else {
                ispTransmit = ispTransmit_sw;
                }
 
        } else {
                ispTransmit = ispTransmit_sw;
+               sck_sw_delay_loops = 1;
+
                switch (option) {
 
                switch (option) {
 
+#              if (F_CPU > 12000000)
+                       case USBASP_ISP_SCK_93_75:
+                       sck_sw_delay = 2;
+
+                       break;
+#              endif
                case USBASP_ISP_SCK_32:
                case USBASP_ISP_SCK_32:
-                       sck_sw_delay = 3;
+                       sck_sw_delay = ((3 * (F_CPU/1000000L) + 11) / 12);
 
                        break;
                case USBASP_ISP_SCK_16:
 
                        break;
                case USBASP_ISP_SCK_16:
-                       sck_sw_delay = 6;
+                       sck_sw_delay = ((6 * (F_CPU/1000000L) + 11) / 12);
 
                        break;
                case USBASP_ISP_SCK_8:
 
                        break;
                case USBASP_ISP_SCK_8:
-                       sck_sw_delay = 12;
+                       sck_sw_delay = ((12 * (F_CPU/1000000L) + 11) / 12);
 
                        break;
                case USBASP_ISP_SCK_4:
 
                        break;
                case USBASP_ISP_SCK_4:
-                       sck_sw_delay = 24;
+                       sck_sw_delay = ((24 * (F_CPU/1000000L) + 11) / 12);
 
                        break;
                case USBASP_ISP_SCK_2:
 
                        break;
                case USBASP_ISP_SCK_2:
-                       sck_sw_delay = 48;
+                       sck_sw_delay = ((48 * (F_CPU/1000000L) + 11) / 12);
 
                        break;
                case USBASP_ISP_SCK_1:
 
                        break;
                case USBASP_ISP_SCK_1:
-                       sck_sw_delay = 96;
+                       sck_sw_delay = ((96 * (F_CPU/1000000L) + 11) / 12);
 
                        break;
                case USBASP_ISP_SCK_0_5:
 
                        break;
                case USBASP_ISP_SCK_0_5:
-                       sck_sw_delay = 192;
+                       sck_sw_delay = ((96 * (F_CPU/1000000L) + 11) / 12);
+                       sck_sw_delay_loops = 2;
 
                        break;
                }
 
                        break;
                }
@@ -101,7 +137,11 @@ void ispSetSCKOption(uchar option) {
 void ispDelay() {
 
        uint8_t starttime = TIMERVALUE;
 void ispDelay() {
 
        uint8_t starttime = TIMERVALUE;
-       while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) {
+       uint8_t loops = sck_sw_delay_loops;
+
+       while (loops--) {
+               while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) {
+               }
        }
 }
 
        }
 }