Browse Source

M355 S0, S1 fixes & faster LCD, SD card

fix Travis error
Christopher Pepper 7 years ago
parent
commit
bea3ec2724

+ 3 - 0
.gitignore

@@ -158,6 +158,9 @@ src/.vs/
 #Visual Studio Code
 .vscode
 
+#Visual Studio Code
+.vscode
+
 #cmake
 CMakeLists.txt
 src/CMakeLists.txt

+ 2 - 1
Marlin/Configuration.h

@@ -1233,8 +1233,9 @@
  * SD CARD: SPI SPEED
  *
  * Enable one of the following items for a slower SPI transfer speed.
- * This may be required to resolve "volume init" errors.
+ * This may be required to resolve "volume init" errors or LCD issues.
  */
+ 
 //#define SPI_SPEED SPI_HALF_SPEED
 //#define SPI_SPEED SPI_QUARTER_SPEED
 //#define SPI_SPEED SPI_EIGHTH_SPEED

+ 1 - 47
Marlin/src/HAL/HAL.h

@@ -29,53 +29,7 @@
 #ifndef _HAL_H
 #define _HAL_H
 
-#include <stdint.h>
-
-/**
- * SPI speed where 0 <= index <= 6
- *
- * Approximate rates :
- *
- *  0 :  8 - 10 MHz
- *  1 :  4 - 5 MHz
- *  2 :  2 - 2.5 MHz
- *  3 :  1 - 1.25 MHz
- *  4 :  500 - 625 kHz
- *  5 :  250 - 312 kHz
- *  6 :  125 - 156 kHz
- *
- *  On AVR, actual speed is F_CPU/2^(1 + index).
- *  On other platforms, speed should be in range given above where possible.
- */
-
-/** Set SCK to max rate */
-uint8_t const SPI_FULL_SPEED = 0;
-/** Set SCK rate to half max rate. */
-uint8_t const SPI_HALF_SPEED = 1;
-/** Set SCK rate to quarter max rate. */
-uint8_t const SPI_QUARTER_SPEED = 2;
-/** Set SCK rate to 1/8 max rate. */
-uint8_t const SPI_EIGHTH_SPEED = 3;
-/** Set SCK rate to 1/16 of max rate. */
-uint8_t const SPI_SIXTEENTH_SPEED = 4;
-/** Set SCK rate to 1/32 of max rate. */
-uint8_t const SPI_SPEED_5 = 5;
-/** Set SCK rate to 1/64 of max rate. */
-uint8_t const SPI_SPEED_6 = 6;
-
-// Standard SPI functions
-/** Initialise SPI bus */
-void spiBegin(void);
-/** Configure SPI for specified SPI speed */
-void spiInit(uint8_t spiRate);
-/** Write single byte to SPI */
-void spiSend(uint8_t b);
-/** Read single byte from SPI */
-uint8_t spiRec(void);
-/** Read from SPI into buffer */
-void spiRead(uint8_t* buf, uint16_t nbyte);
-/** Write token and then write from 512 byte buffer to SPI (for SD card) */
-void spiSendBlock(uint8_t token, const uint8_t* buf);
+#include "src/inc/SPI.h"
 
 #ifdef __AVR__
   #include "HAL_AVR/HAL_AVR.h"

+ 165 - 37
Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp

@@ -1,6 +1,6 @@
 /**
  * Marlin 3D Printer Firmware
- * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  *
  * Based on Sprinter and grbl.
  * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
@@ -30,13 +30,32 @@
  * For TARGET_LPC1768
  */
 
+/**
+ * Hardware SPI and a software SPI implementations are included in this file.
+ * The hardware SPI runs faster and has higher throughput but is not compatible
+ * with some LCD interfaces/adapters.
+ *
+ * Control of the slave select pin(s) is handled by the calling routines.
+ *
+ * Some of the LCD interfaces/adapters result in the LCD SPI and the SD card
+ * SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
+ * WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
+ * active.  If any of these pins are shared then the software SPI must be used.
+ *
+ * A more sophisticated hardware SPI can be found at the following link.  This
+ * implementation has not been fully debugged.
+ * https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
+ */
+
 #ifdef TARGET_LPC1768
 
 // --------------------------------------------------------------------------
 // Includes
 // --------------------------------------------------------------------------
 
-#include "../../inc/MarlinConfig.h"
+//#include "../../../MarlinConfig.h"  //works except in U8g
+#include "spi_pins.h"
+#include "fastio.h"
 
 // --------------------------------------------------------------------------
 // Public Variables
@@ -47,87 +66,122 @@
 // Public functions
 // --------------------------------------------------------------------------
 
-#if ENABLED(SOFTWARE_SPI)
+#if ENABLED(LPC_SOFTWARE_SPI)
   // --------------------------------------------------------------------------
   // software SPI
   // --------------------------------------------------------------------------
-  // bitbanging transfer
-  // run at ~100KHz (necessary for init)
-  static uint8_t spiTransfer(uint8_t b) { // using Mode 0
-    for (int bits = 0; bits < 8; bits++) {
-      if (b & 0x80) {
-        WRITE(MOSI_PIN, HIGH);
-      }
-      else {
-        WRITE(MOSI_PIN, LOW);
+
+  /**
+   * This software SPI runs at three rates. The SD software provides an index
+   * (spiRate) of 0-6. The mapping is:
+   *     0-1 - about 5 MHz peak
+   *     2-3 - about 2 MHz peak
+   *     all others - about 250 KHz
+   */
+
+  static uint8_t SPI_speed = 0;
+
+  static uint8_t spiTransfer(uint8_t b) {
+
+    if (!SPI_speed) {       // fastest - about 5 MHz peak
+      for (int bits = 0; bits < 8; bits++) {
+        if (b & 0x80) {
+          WRITE(MOSI_PIN, HIGH);
+          WRITE(MOSI_PIN, HIGH);  // delay to (hopefully) guarantee setup time
+        }
+        else {
+          WRITE(MOSI_PIN, LOW);
+          WRITE(MOSI_PIN, LOW);  // delay to (hopefully) guarantee setup time
+        }
+        b <<= 1;
+        WRITE(SCK_PIN, HIGH);
+        if (READ(MISO_PIN)) {
+          b |= 1;
+        }
+        WRITE(SCK_PIN, LOW);
       }
-      b <<= 1;
+    }
+    else if (SPI_speed == 1) { // medium - about 1 MHz
+      for (int bits = 0; bits < 8; bits++) {
+        if (b & 0x80) {
+          for (uint8_t i = 0; i < 8; i++) WRITE(MOSI_PIN, HIGH);
+        }
+        else {
+          for (uint8_t i = 0; i < 8; i++) WRITE(MOSI_PIN, LOW);
+        }
+        b <<= 1;
+
+        for (uint8_t i = 0; i < 6; i++) WRITE(SCK_PIN, HIGH);
 
-      WRITE(SCK_PIN, HIGH);
-      delayMicroseconds(3U);
+        if (READ(MISO_PIN)) {
+          b |= 1;
+        }
+        WRITE(SCK_PIN, LOW);
+      }
+    }
+    else { // slow - about 250 KHz
+      for (int bits = 0; bits < 8; bits++) {
+        if (b & 0x80) {
+          WRITE(MOSI_PIN, HIGH);
+        }
+        else {
+          WRITE(MOSI_PIN, LOW);
+        }
+        b <<= 1;
+        delayMicroseconds(1U);
+        WRITE(SCK_PIN, HIGH);
+        delayMicroseconds(2U);
 
-      if (READ(MISO_PIN)) {
-        b |= 1;
+        if (READ(MISO_PIN)) {
+          b |= 1;
+        }
+        WRITE(SCK_PIN, LOW);
+        delayMicroseconds(1U);
       }
-      WRITE(SCK_PIN, LOW);
-      delayMicroseconds(3U);
     }
     return b;
   }
 
   void spiBegin() {
-    SET_OUTPUT(SS_PIN);
-    WRITE(SS_PIN, HIGH);
     SET_OUTPUT(SCK_PIN);
     SET_INPUT(MISO_PIN);
     SET_OUTPUT(MOSI_PIN);
   }
 
   void spiInit(uint8_t spiRate) {
-    UNUSED(spiRate);
-    WRITE(SS_PIN, HIGH);
+    SPI_speed = spiRate >> 1;
     WRITE(MOSI_PIN, HIGH);
     WRITE(SCK_PIN, LOW);
   }
 
   uint8_t spiRec() {
-    WRITE(SS_PIN, LOW);
     uint8_t b = spiTransfer(0xff);
-    WRITE(SS_PIN, HIGH);
     return b;
   }
 
   void spiRead(uint8_t*buf, uint16_t nbyte) {
     if (nbyte == 0) return;
-    WRITE(SS_PIN, LOW);
     for (int i = 0; i < nbyte; i++) {
       buf[i] = spiTransfer(0xff);
     }
-    WRITE(SS_PIN, HIGH);
   }
 
   void spiSend(uint8_t b) {
-    WRITE(SS_PIN, LOW);
     uint8_t response = spiTransfer(b);
     UNUSED(response);
-    WRITE(SS_PIN, HIGH);
   }
 
   static void spiSend(const uint8_t* buf, size_t n) {
     uint8_t response;
     if (n == 0) return;
-    WRITE(SS_PIN, LOW);
     for (uint16_t i = 0; i < n; i++) {
       response = spiTransfer(buf[i]);
     }
     UNUSED(response);
-    WRITE(SS_PIN, HIGH);
   }
 
   void spiSendBlock(uint8_t token, const uint8_t* buf) {
     uint8_t response;
-
-    WRITE(SS_PIN, LOW);
     response = spiTransfer(token);
 
     for (uint16_t i = 0; i < 512; i++) {
@@ -136,29 +190,97 @@
     UNUSED(response);
     WRITE(SS_PIN, HIGH);
   }
+
 #else
-  void spiBegin() {
+
+  // hardware SPI
+
+  #include <lpc17xx_pinsel.h>
+  #include <lpc17xx_ssp.h>
+  #include <lpc17xx_clkpwr.h>
+
+  void spiBegin() {  // setup SCK, MOSI & MISO pins for SSP0
+
+    PINSEL_CFG_Type PinCfg;  // data structure to hold init values
+    PinCfg.Funcnum = 2;
+    PinCfg.OpenDrain = 0;
+    PinCfg.Pinmode = 0;
+    PinCfg.Pinnum = pin_map[SCK_PIN].pin;
+    PinCfg.Portnum = pin_map[SCK_PIN].port;
+    PINSEL_ConfigPin(&PinCfg);
+    SET_OUTPUT(SCK_PIN);
+
+    PinCfg.Pinnum = pin_map[MISO_PIN].pin;
+    PinCfg.Portnum = pin_map[MISO_PIN].port;
+    PINSEL_ConfigPin(&PinCfg);
+    SET_INPUT(MISO_PIN);
+
+    PinCfg.Pinnum = pin_map[MOSI_PIN].pin;
+    PinCfg.Portnum = pin_map[MOSI_PIN].port;
+    PINSEL_ConfigPin(&PinCfg);
+    SET_OUTPUT(MOSI_PIN);
   }
 
+
   void spiInit(uint8_t spiRate) {
+
+   // table to convert Marlin spiRates (0-5 plus default) into bit rates
+    uint32_t Marlin_speed[7]; // CPSR is always 2
+    Marlin_speed[0] = 8333333; //(SCR:  2)  desired: 8,000,000  actual: 8,333,333  +4.2%  SPI_FULL_SPEED
+    Marlin_speed[1] = 4166667; //(SCR:  5)  desired: 4,000,000  actual: 4,166,667  +4.2%  SPI_HALF_SPEED
+    Marlin_speed[2] = 2083333; //(SCR: 11)  desired: 2,000,000  actual: 2,083,333  +4.2%  SPI_QUARTER_SPEED
+    Marlin_speed[3] = 1000000; //(SCR: 24)  desired: 1,000,000  actual: 1,000,000         SPI_EIGHTH_SPEED
+    Marlin_speed[4] =  500000; //(SCR: 49)  desired:   500,000  actual:   500,000         SPI_SPEED_5
+    Marlin_speed[5] =  250000; //(SCR: 99)  desired:   250,000  actual:   250,000         SPI_SPEED_6
+    Marlin_speed[6] =  125000; //(SCR:199)  desired:   125,000  actual:   125,000         Default from HAL.h
+
+
+   // select 50MHz PCLK for SSP0
+    CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_SSP0, CLKPWR_PCLKSEL_CCLK_DIV_2);
+
+   // setup for SPI mode
+    SSP_CFG_Type HW_SPI_init; // data structure to hold init values
+    SSP_ConfigStructInit(&HW_SPI_init);  // set values for SPI mode
+    HW_SPI_init.ClockRate = Marlin_speed[MIN(spiRate, 6)]; // put in the specified bit rate
+    SSP_Init(LPC_SSP0, &HW_SPI_init);  // puts the values into the proper bits in the SSP0 registers
+
+    SSP_Cmd(LPC_SSP0, ENABLE);  // start SSP0 running
   }
 
-  void spiSend(byte b) {
+  void spiSend(uint8_t b) {
+    while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL));   // wait for room in the buffer
+    SSP_SendData(LPC_SSP0, b & 0x00FF);
+    while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY));  // wait for it to finish
   }
 
+
   void spiSend(const uint8_t* buf, size_t n) {
+    if (n == 0) return;
+    for (uint16_t i = 0; i < n; i++) {
+      while (!SSP_GetStatus(LPC_SSP0, SSP_STAT_TXFIFO_NOTFULL));   // wait for room in the buffer
+      SSP_SendData(LPC_SSP0, buf[i] & 0x00FF);
+    }
+    while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY));  // wait for it to finish
   }
 
   void spiSend(uint32_t chan, byte b) {
   }
 
   void spiSend(uint32_t chan, const uint8_t* buf, size_t n) {
+  }
 
+
+  uint8_t get_one_byte() {
+   // send a dummy byte so can clock in receive data
+    SSP_SendData(LPC_SSP0,0x00FF);
+    while (SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY));  // wait for it to finish
+    return SSP_ReceiveData(LPC_SSP0) & 0x00FF;
   }
 
   // Read single byte from SPI
   uint8_t spiRec() {
-    return 0;
+    while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0);  //flush the receive buffer
+    return get_one_byte();
   }
 
   uint8_t spiRec(uint32_t chan) {
@@ -167,11 +289,17 @@
 
   // Read from SPI into buffer
   void spiRead(uint8_t*buf, uint16_t nbyte) {
+    while (SSP_GetStatus(LPC_SSP0, SSP_STAT_RXFIFO_NOTEMPTY) || SSP_GetStatus(LPC_SSP0, SSP_STAT_BUSY)) SSP_ReceiveData(LPC_SSP0);  //flush the receive buffer
+    if (nbyte == 0) return;
+    for (int i = 0; i < nbyte; i++) {
+      buf[i] = get_one_byte();
+    }
   }
 
   // Write from buffer to SPI
   void spiSendBlock(uint8_t token, const uint8_t* buf) {
   }
-#endif // ENABLED(SOFTWARE_SPI)
+#endif // ENABLED(LPC_SOFTWARE_SPI)
 
 #endif // TARGET_LPC1768
+

+ 10 - 0
Marlin/src/HAL/HAL_LPC1768/LPC1768_PWM.h

@@ -399,6 +399,16 @@ bool LPC1768_PWM_detach_pin(uint8_t pin) {
   return 1;
 }
 
+
+bool useable_hardware_PWM(uint8_t pin) {
+  COPY_ACTIVE_TABLE;  // copy active table into work table
+  for (uint8_t i = 0; i < NUM_PWMS; i++)         // see if it's already setup
+    if (work_table[i].logical_pin == pin && work_table[i].sequence) return true;
+  for (uint8_t i = 0; i < NUM_PWMS; i++)         // see if there is an empty slot
+    if (!work_table[i].sequence) return true;
+  return false;    // only get here if neither the above are true
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 #define HAL_PWM_LPC1768_ISR  extern "C" void PWM1_IRQHandler(void)

+ 3 - 0
Marlin/src/HAL/HAL_LPC1768/fastio.h

@@ -38,6 +38,9 @@
 #include "arduino.h"
 #include "pinmapping.h"
 
+bool useable_hardware_PWM(uint8_t pin);
+#define USEABLE_HARDWARE_PWM(pin) useable_hardware_PWM(pin)
+
 #define LPC_PORT_OFFSET         (0x0020)
 #define LPC_PIN(pin)            (1UL << pin)
 #define LPC_GPIO(port)          ((volatile LPC_GPIO_TypeDef *)(LPC_GPIO0_BASE + LPC_PORT_OFFSET * port))

+ 8 - 1
Marlin/src/HAL/HAL_LPC1768/spi_pins.h

@@ -23,7 +23,8 @@
 #ifndef SPI_PINS_LPC1768_H
 #define SPI_PINS_LPC1768_H
 
-#define SOFTWARE_SPI
+#define LPC_SOFTWARE_SPI
+
 /** onboard SD card */
 //#define SCK_PIN           P0_7
 //#define MISO_PIN          P0_8
@@ -34,4 +35,10 @@
 #define MISO_PIN          50 //P0_17
 #define MOSI_PIN          51 //P0_18
 #define SS_PIN            53 //P1_23
+#define SDSS              SS_PIN
+
+#if (defined(IS_REARM) && !(defined(LPC_SOFTWARE_SPI)))   // signal LCDs that they need to use the hardware SPI
+  #define SHARED_SPI
+#endif
+
 #endif /* SPI_PINS_LPC1768_H */

+ 20 - 1
Marlin/src/feature/caselight.cpp

@@ -27,19 +27,38 @@
 uint8_t case_light_brightness = CASE_LIGHT_DEFAULT_BRIGHTNESS;
 bool case_light_on = CASE_LIGHT_DEFAULT_ON;
 
+/**
+ * The following are needed because ARM chips ignore a "WRITE(CASE_LIGHT_PIN,x)" command to the pins that
+ * are directly controlled by the PWM module. In order to turn them off the brightness level needs to be
+ * set to off.  Since we can't use the pwm register to save the last brightness level we need a variable
+ * to save it.
+ */
+uint8_t case_light_brightness_sav;   // saves brighness info so can restore when "M355 S1" received
+bool case_light_arg_flag;  // flag to notify if S or P arguement type
+
 #ifndef INVERT_CASE_LIGHT
   #define INVERT_CASE_LIGHT false
 #endif
 
 void update_case_light() {
   SET_OUTPUT(CASE_LIGHT_PIN);
+
+  if (!(case_light_arg_flag && !case_light_on))
+    case_light_brightness_sav = case_light_brightness;  // save brightness except if this is an S0 arguement
+  if (case_light_arg_flag && case_light_on)
+    case_light_brightness = case_light_brightness_sav;  // restore last brightens if this is an S1 arguement
+
   if (case_light_on) {
     if (USEABLE_HARDWARE_PWM(CASE_LIGHT_PIN)) {
       analogWrite(CASE_LIGHT_PIN, INVERT_CASE_LIGHT ? 255 - case_light_brightness : case_light_brightness );
     }
     else WRITE(CASE_LIGHT_PIN, INVERT_CASE_LIGHT ? LOW : HIGH);
   }
-  else WRITE(CASE_LIGHT_PIN, INVERT_CASE_LIGHT ? HIGH : LOW);
+  else {
+    if (USEABLE_HARDWARE_PWM(CASE_LIGHT_PIN))
+      analogWrite(CASE_LIGHT_PIN, INVERT_CASE_LIGHT ? 255 : 0 );  // turn the light off
+    WRITE(CASE_LIGHT_PIN, INVERT_CASE_LIGHT ? HIGH : LOW);
+  }
 }
 
 #endif // HAS_CASE_LIGHT

+ 2 - 0
Marlin/src/feature/caselight.h

@@ -25,6 +25,8 @@
 
 extern uint8_t case_light_brightness;
 extern bool case_light_on;
+extern uint8_t case_light_brightness_sav;   // saves brighness info when case_light_on is false
+extern bool case_light_arg_flag;  // flag to notify if S or P arguement type
 
 void update_case_light();
 

+ 8 - 2
Marlin/src/gcode/feature/caselight/M355.cpp

@@ -43,8 +43,14 @@
 void GcodeSuite::M355() {
   #if HAS_CASE_LIGHT
     uint8_t args = 0;
-    if (parser.seenval('P')) ++args, case_light_brightness = parser.value_byte();
-    if (parser.seenval('S')) ++args, case_light_on = parser.value_bool();
+    if (parser.seenval('P')) {
+      ++args, case_light_brightness = parser.value_byte();
+      case_light_arg_flag = false;
+    }  
+    if (parser.seenval('S')) {
+      ++args, case_light_on = parser.value_bool();
+      case_light_arg_flag = true;
+    }
     if (args) update_case_light();
 
     // always report case light status

Some files were not shown because too many files changed in this diff