Loop based controller for dual lane siemens siplace feeder.

Dependencies:   USBDevice mbed

Files at this revision

API Documentation at this revision

Comitter:
Issus
Date:
Sat Feb 04 01:27:29 2017 +0000
Parent:
0:617334d8e3bb
Commit message:
Minimum on time for cover tape pickup. Added IAP for getting mcu serial number and future eeprom use. Moved defs to .h file.

Changed in this revision

IAP_LPC11U.cpp Show annotated file Show diff for this revision Revisions of this file
IAP_LPC11U.h Show annotated file Show diff for this revision Revisions of this file
feeder.h Show annotated file Show diff for this revision Revisions of this file
feederController.cpp Show annotated file Show diff for this revision Revisions of this file
partNumbers.h Show annotated file Show diff for this revision Revisions of this file
diff -r 617334d8e3bb -r 4d3738338cf1 IAP_LPC11U.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IAP_LPC11U.cpp	Sat Feb 04 01:27:29 2017 +0000
@@ -0,0 +1,266 @@
+#if defined(TARGET_LPC11UXX) | defined(TARGET_LPC11U6X)
+ 
+#include "IAP_LPC11U.h"
+ 
+namespace
+{
+//This data must be global so it is not read from the stack
+unsigned int m_Command[5], m_Result[5];
+typedef void (*IAP)(unsigned int [], unsigned int []);
+const IAP IAP_Entry = (IAP)0x1FFF1FF1;
+}
+ 
+static inline void _iap_CriticalEntry()
+{
+    //Disable interrupts
+    __disable_irq();
+ 
+    //Safely perform IAP entry
+    IAP_Entry(m_Command, m_Result);
+ 
+    //Enable interrupts
+    __enable_irq();
+}
+ 
+IapReturnCode IAP_PrepareSectors(unsigned int sector_start, unsigned int sector_end)
+{
+    //Prepare the command array
+    m_Command[0] = 50;
+    m_Command[1] = sector_start;             //The start of the sector to be prepared
+    m_Command[2] = sector_end;               //The end of the sector to be prepared
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+IapReturnCode IAP_CopyRAMToFlash(void* ram_address, void* flash_address, unsigned int length)
+{
+    //Prepare the command array
+    m_Command[0] = 51;
+    m_Command[1] = (unsigned int)flash_address;     //Flash address where the contents are to be copied (it should be within 256bytes boundary)
+    m_Command[2] = (unsigned int)ram_address;       //RAM address to be copied (it should be in word boundary)
+    m_Command[3] = length;                          //Number of data to be copied in bytes: 256, 512, 1024, or 4096
+    m_Command[4] = SystemCoreClock / 1000;
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+IapReturnCode IAP_EraseSectors(unsigned int sector_start, unsigned int sector_end)
+{
+    //Prepare the command array
+    m_Command[0] = 52;
+    m_Command[1] = sector_start;             //The start of the sector to be erased
+    m_Command[2] = sector_end;               //The end of the sector to be erased
+    m_Command[3] = SystemCoreClock / 1000;   //System Clock Frequency (CCLK) in kHz
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+IapReturnCode IAP_BlankCheckSectors(unsigned int sector_start, unsigned int sector_end)
+{
+    //Prepare the command array
+    m_Command[0] = 53;
+    m_Command[1] = sector_start;                 //The start of the sector to be checked
+    m_Command[2] = sector_end;                   //The end of the sector to be checked
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+unsigned int IAP_ReadPartID()
+{
+    //Prepare the command array
+    m_Command[0] = 54;
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the part ID
+    unsigned int ret = m_Result[1];
+ 
+    //Return the part ID
+    return ret;
+}
+ 
+unsigned short IAP_ReadBootCodeVersion()
+{
+    //Prepare the command array
+    m_Command[0] = 55;
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the boot code version
+    unsigned int ret = (unsigned short)m_Result[1];
+ 
+    //Return the boot code version
+    return ret;
+}
+ 
+IapReturnCode IAP_Compare(void* address1, void* address2, unsigned int bytes)
+{
+    //Prepare the command array
+    m_Command[0] = 56;
+    m_Command[1] = (unsigned int)address1;   //Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
+    m_Command[2] = (unsigned int)address2;   //Starting flash or RAM address of data bytes to be compared. This address should be a word boundary.
+    m_Command[3] = bytes;                    //Number of bytes to be compared; should be a multiple of 4.
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+/* This function resets some microcontroller peripherals to reset
+ * hardware configuration to ensure that the USB In-System Programming module
+ * will work properly. It is normally called from reset and assumes some reset
+ * configuration settings for the MCU.
+ * Some of the peripheral configurations may be redundant in your specific
+ * project.
+ */
+void IAP_ReinvokeISP()
+{
+    //Make sure USB clock is turned on before calling ISP
+    //LPC_SYSCON->SYSAHBCLKCTRL |= 0x04000;
+ 
+    //Make sure 32-bit Timer 1 is turned on before calling ISP
+    //LPC_SYSCON->SYSAHBCLKCTRL |= 0x00400;
+ 
+    //Make sure GPIO clock is turned on before calling ISP
+    LPC_SYSCON->SYSAHBCLKCTRL |= 0x00040;
+ 
+    //Make sure IO configuration clock is turned on before calling ISP
+    //LPC_SYSCON->SYSAHBCLKCTRL |= 0x10000;
+ 
+#if defined(TARGET_LPC11U6X)
+    //Set the vector table offset to address 0
+    SCB->VTOR = 0;
+#endif
+ 
+    //Make sure AHB clock divider is 1:1
+    LPC_SYSCON->SYSAHBCLKDIV = 1;
+ 
+    //Prepare the command array
+    m_Command[0] = 57;
+ 
+    //Initialize the storage state machine
+    //*((unsigned int*)(0x10000054)) = 0x0;
+ 
+    //Set stack pointer to ROM value (reset default)
+    //This must be the last piece of code executed before calling ISP,
+    //because most C expressions and function returns will fail after the stack pointer is changed.
+    //__set_MSP(*((unsigned int*)0x00000000));
+ 
+    //Invoke IAP call...
+    IAP_Entry(m_Command, m_Result);
+ 
+    //Shouldn't return
+}
+ 
+UID IAP_ReadUID()
+{
+    //Prepare the command array
+    m_Command[0] = 58;
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the UID
+    UID ret = {
+        m_Result[1],
+        m_Result[2],
+        m_Result[3],
+        m_Result[4]
+    };
+ 
+    //Return the UID
+    return ret;
+}
+ 
+IapReturnCode IAP_ErasePage(unsigned int page_start, unsigned int page_end)
+{
+    //Prepare the command array
+    m_Command[0] = 59;
+    m_Command[1] = page_start;               //The start of the page to be erased
+    m_Command[2] = page_end;                 //The end of the page to be erased
+    m_Command[3] = SystemCoreClock / 1000;   //System Clock Frequency (CCLK) in kHz
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+IapReturnCode IAP_WriteEEPROM(unsigned int ee_address, char* buffer, unsigned int length)
+{
+    //Prepare the command array
+    m_Command[0] = 61;
+    m_Command[1] = ee_address;               //EEPROM address (byte, half-word or word aligned)
+    m_Command[2] = (unsigned int)buffer;     //RAM address (byte, half-word or word aligned)
+    m_Command[3] = length;                   //Number of bytes to be written (byte, half-word writes are ok)
+    m_Command[4] = SystemCoreClock / 1000;   //System Clock Frequency (CCLK) in kHz
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+ 
+    //Return the result code
+    return ret;
+}
+ 
+IapReturnCode IAP_ReadEEPROM(unsigned int ee_address, char* buffer, unsigned int length)
+{
+    //Prepare the command array
+    m_Command[0] = 62;
+    m_Command[1] = ee_address;               //EEPROM address (byte, half-word or word aligned)
+    m_Command[2] = (unsigned int)buffer;     //RAM address (byte, half-word or word aligned)
+    m_Command[3] = length;                   //Number of bytes to be read (byte, half-word reads are ok)
+    m_Command[4] = SystemCoreClock / 1000;   //System Clock Frequency (CCLK) in kHz
+ 
+    //Invoke critical IAP call...
+    _iap_CriticalEntry();
+ 
+    //Extract the result code
+    IapReturnCode ret = (IapReturnCode)m_Result[0];
+    
+    //Return the result code
+    return ret;
+}
+ 
+#endif
\ No newline at end of file
diff -r 617334d8e3bb -r 4d3738338cf1 IAP_LPC11U.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IAP_LPC11U.h	Sat Feb 04 01:27:29 2017 +0000
@@ -0,0 +1,48 @@
+#if defined(TARGET_LPC11UXX) | defined(TARGET_LPC11U6X)
+ 
+#ifndef IAP_LPC11UXX_H
+#define IAP_LPC11UXX_H
+ 
+#include "mbed.h"
+ 
+//128-bit unique ID struct typedef
+struct UID {
+    unsigned int word0; /**< Word 0 of 128-bit UID (bits 31 to 0) */
+    unsigned int word1; /**< Word 1 of 128-bit UID (bits 63 to 32) */
+    unsigned int word2; /**< Word 2 of 128-bit UID (bits 95 to 64) */
+    unsigned int word3; /**< Word 3 of 128-bit UID (bits 127 to 96) */
+};
+ 
+//IAP return code enumeration
+enum IapReturnCode {
+    IAP_CMD_SUCCESS = 0,
+    IAP_INVALID_COMMAND,
+    IAP_SRC_ADDR_ERROR,
+    IAP_DST_ADDR_ERROR,
+    IAP_SRC_ADDR_NOT_MAPPED,
+    IAP_DST_ADDR_NOT_MAPPED,
+    IAP_COUNT_ERROR,
+    IAP_INVALID_SECTOR,
+    IAP_SECTOR_NOT_BLANK,
+    IAP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
+    IAP_COMPARE_ERROR,
+    IAP_BUSY
+};
+ 
+//Function prototypes
+IapReturnCode IAP_PrepareSectors(unsigned int sector_start, unsigned int sector_end);
+IapReturnCode IAP_CopyRAMToFlash(void* ram_address, void* flash_address, unsigned int length);
+IapReturnCode IAP_EraseSectors(unsigned int sector_start, unsigned int sector_end);
+IapReturnCode IAP_BlankCheckSectors(unsigned int sector_start, unsigned int sector_end);
+unsigned int IAP_ReadPartID();
+unsigned short IAP_ReadBootCodeVersion();
+IapReturnCode IAP_Compare(void* address1, void* address2, unsigned int bytes);
+void IAP_ReinvokeISP();
+UID IAP_ReadUID();
+IapReturnCode IAP_ErasePage(unsigned int page_start, unsigned int page_end);
+IapReturnCode IAP_WriteEEPROM(unsigned int ee_address, char* buffer, unsigned int length);
+IapReturnCode IAP_ReadEEPROM(unsigned int ee_address, char* buffer, unsigned int length);
+ 
+#endif
+ 
+#endif
\ No newline at end of file
diff -r 617334d8e3bb -r 4d3738338cf1 feeder.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/feeder.h	Sat Feb 04 01:27:29 2017 +0000
@@ -0,0 +1,40 @@
+
+// HARDWARE PIN DEFS
+#define PIN_LED             P0_7
+#define PIN_VINREF          P0_23
+
+#define PIN_LED_YELLOW_0    P0_9
+#define PIN_LED_YELLOW_1    P1_13
+
+#define PIN_BTN_GREEN_0     P0_22
+#define PIN_BTN_GREEN_1     P1_14
+
+#define PIN_BOARD_FEED      P0_1
+
+#define PIN_GATE_0          P0_11
+#define PIN_GATE_1          P0_12
+#define PIN_GATE_2          P0_13
+#define PIN_GATE_3          P0_14
+
+#define PIN_LANECTL_0       P0_16
+#define PIN_LANECTL_1       P1_15
+
+#define PIN_RS485_DIR       P0_17
+#define PIN_UART_TXD        P0_18
+#define PIN_UART_RXD        P0_19
+
+#define PIN_SOLCTL_0        P1_19
+#define PIN_SOLCTL_1        P1_25
+
+#define PIN_BTN_LED_0       P1_29
+#define PIN_BTN_LED_1       P1_22
+
+#define PIN_H1_IN1          P0_20
+#define PIN_H1_IN2          P0_2
+#define PIN_H1_IN3          P1_26
+#define PIN_H1_IN4          P1_27
+
+#define PIN_H2_IN1          P1_28
+#define PIN_H2_IN2          P1_31
+#define PIN_H2_IN3          P0_8
+#define PIN_H2_IN4          P1_21
diff -r 617334d8e3bb -r 4d3738338cf1 feederController.cpp
--- a/feederController.cpp	Thu Feb 02 19:18:12 2017 +0000
+++ b/feederController.cpp	Sat Feb 04 01:27:29 2017 +0000
@@ -1,63 +1,26 @@
 #include "mbed.h"
 #include "USBSerial.h"
 #include "HBridge.h"
+#include "feeder.h"
+#include "IAP_LPC11U.h"
 
 extern "C" void mbed_mac_address(char *);
 
 /************
 TODO LIST:
 *************
-* Move defs to .h file
-* Move tape pickup into main loop. Interrupts on it dont seem to be entirely reliable (spurrious)
 * printf needs to be replace with a function that putc instead for non-formatted strings
 * Convert lanes to a class so they there isn't duplicate code
+* Store lane distance in EEPROM
+* Store retrievable aribitrary text for the lane in EEPROM (loaded part, openpnp part feeder name, whatever)
 *************/
 
-// HARDWARE PIN DEFS
-#define PIN_LED             P0_7
-#define PIN_VINREF          P0_23
-
-#define PIN_LED_YELLOW_0    P0_9
-#define PIN_LED_YELLOW_1    P1_13
-
-#define PIN_BTN_GREEN_0     P0_22
-#define PIN_BTN_GREEN_1     P1_14
-
-#define PIN_BOARD_FEED      P0_1
-
-#define PIN_GATE_0          P0_11
-#define PIN_GATE_1          P0_12
-#define PIN_GATE_2          P0_13
-#define PIN_GATE_3          P0_14
-
-#define PIN_LANECTL_0       P0_16
-#define PIN_LANECTL_1       P1_15
-
-#define PIN_RS485_DIR       P0_17
-#define PIN_UART_TXD        P0_18
-#define PIN_UART_RXD        P0_19
-
-#define PIN_SOLCTL_0        P1_19
-#define PIN_SOLCTL_1        P1_25
-
-#define PIN_BTN_LED_0       P1_29
-#define PIN_BTN_LED_1       P1_22
-
-#define PIN_H1_IN1          P0_20
-#define PIN_H1_IN2          P0_2
-#define PIN_H1_IN3          P1_26
-#define PIN_H1_IN4          P1_27
-
-#define PIN_H2_IN1          P1_28
-#define PIN_H2_IN2          P1_31
-#define PIN_H2_IN3          P0_8
-#define PIN_H2_IN4          P1_21
-
 
 // SETTINGS
-#define TAPE_MAX_PULL_TIME 2 // seconds
+#define TAPE_MAX_PULL_TIME 3 // seconds
+#define TAPE_MIN_PULL_TIME 1 // seconds
 
-#define FEED_FWD_ENC_PULSE 2 // actually this + 1
+#define FEED_FWD_ENC_PULSE 2 // it's actually this value + 1
 // encoder pulses: >(lane0FeedDistance * FEED_FWD_ENC_PULSE)
 // 3 for 1 position, 5 for 2 positions
 
@@ -95,10 +58,6 @@
 int lane0FeedDistance = 1; // 1 = 2mm, 2 = 4mm
 int lane1FeedDistance = 1;
 
-// LOOP COUNT FOR BUTTONS (incase Timer is too slow)
-int button0PressCount = 0;
-int button1PressCount = 0;
-
 // FEEDER END BUTTON STATES
 int button0LastState = 0;
 int button1LastState = 0;
@@ -115,9 +74,9 @@
 Timeout lane0Feedout;
 Timeout lane1Feedout;
 
-// PICKUP STOPPER
-Timeout lane0Pickupout;
-Timeout lane1Pickupout;
+// TAPE PICKUP STOPPER
+Timer tape0PullTime;
+Timer tape1PullTime;
 
 /*****************************************************************************
 **** HARDWARE
@@ -173,21 +132,17 @@
 
 void stopTapeL0() 
 { 
-    if (LN0_TAPEGATE)
-    {
-        tape0Takeup = 0; 
-        tapeMotor0.Coast(); 
-    }
+    tape0PullTime.stop();
+    tape0Takeup = 0; 
+    tapeMotor0.Coast(); 
 }
 
 
 void stopTapeL1() 
 { 
-    if (LN1_TAPEGATE)
-    {
-        tape1Takeup = 0; 
-        tapeMotor1.Coast(); 
-    }
+    tape1PullTime.stop();
+    tape1Takeup = 0; 
+    tapeMotor1.Coast(); 
 }
 
 
@@ -306,14 +261,14 @@
 {
     feedMotor0.Brake();
     
-    lane0Feedout.attach(&coastLane0, 0.020);
+    lane0Feedout.attach(&coastLane0, 0.010);
 }
 
 void stopLane1Reverse()
 {
     feedMotor1.Brake();
     
-    lane1Feedout.attach(&coastLane1, 0.020);
+    lane1Feedout.attach(&coastLane1, 0.010);
 }
 
 /*****************************************************************************
@@ -342,15 +297,13 @@
     LED_0 = 0;
     LED_1 = 0;
     
-    // clear terminal screen
+    // clear terminal screen - ignore compiler warning
     pc.printf("\x1Bc\x1B[2J");
     
     pc.printf("\r\nFeeder POST...\r\n\r\n");
     
-    char mac[6];
-    mbed_mac_address(mac);
-    uint32_t devId = mac[3] << 16 | mac[4] << 8 | mac[5];
-    pc.printf("Feeder ID: %d [%#04x::%#04x::%#04x]\r\n\r\n", devId, mac[3], mac[4], mac[5]);
+    UID feederID = IAP_ReadUID();
+    pc.printf("Feeder UID: {%#10x-%#10x-%#10x-%#10x }\r\n\r\n", feederID.word0, feederID.word1, feederID.word2, feederID.word3);
     
     pc.printf("Gate 0 (L0 Feed): %d\r\n", LN0_FEEDGATE.read());
     pc.printf("Gate 1 (L1 Feed): %d\r\n", LN1_FEEDGATE.read());
@@ -395,14 +348,16 @@
     // timer for button debouncing. oldass hardware buttons are bouncy!
     Timer button0Time;
     Timer button1Time;
+    float t0 = 0;
+    float t1 = 0;
     
     while(true)
     {
         /**********************************************************************
-        ** PC USB COMMS
+        ** PC USB COMMS - 2.01uS
         **********************************************************************/
-        // no pc comms checking when feeding, can't afford the time
-        if (lane0State == IDLE && lane1State == IDLE)
+        // no pc comms checking when feeding, no need
+        if ((lane0State == IDLE || lane0State == PICKING) && (lane1State == IDLE || lane1State == PICKING))
         { 
             while (pc.readable())
             {
@@ -519,12 +474,9 @@
                 }
             }
         }
-            
-        
-        LED_0 = 1; // for timing check with oscope/logic analyser
         
         /**********************************************************************
-        ** BUTTON CHECK
+        ** BUTTON CHECK - 3.65uS
         **********************************************************************/
         if (lane0State != FEEDING)
         {
@@ -542,7 +494,6 @@
                         button0Time.stop(); // no need to keep counting
                         
                         pc.printf("Picking 0\r\n");
-                        button0PressCount = 0;
                         setLane0Picking(); // open solenoid while button is down
                     }
                 }
@@ -550,7 +501,6 @@
             else if (!b0 && b0 != button0LastState) // low transition - button released
             {
                 button0LastState = b0;
-                button0PressCount = 0;
                 
                 if (lane0State == PICKING) // not just a bounce
                 {
@@ -565,7 +515,6 @@
                     button0Time.reset();
                     button0Time.start();
                 }
-                button0PressCount = 0;
             }
             
             button0LastState = b0;
@@ -584,7 +533,6 @@
                         button1Time.stop();
                         
                         pc.printf("Picking 1\r\n");
-                        button1PressCount = 0;
                         setLane1Picking();
                     }
                 }
@@ -592,7 +540,6 @@
             else if (!b1 && b1 != button1LastState) // low transition - button released
             {
                 button1LastState = b1;
-                button1PressCount = 0;
                 
                 if (lane1State == PICKING)
                 {
@@ -608,12 +555,11 @@
                     button1Time.start();
                 }
                 button1LastState = b1;
-                button1PressCount = 0;
             }
         }
         
         /**********************************************************************
-        ** ENCODER CHECK
+        ** ENCODER CHECK - 3.38uS
         **********************************************************************/
         
         b0 = LN0_FEEDGATE;
@@ -672,33 +618,44 @@
             lane1Feedout.attach(&stopLane1Reverse, 0.020);
             pc.printf("Idle 1\r\n");
         }
+        LED_0 = 1;
         
         /**********************************************************************
-        ** COVER TAPE CHECK
+        ** COVER TAPE CHECK - Gate closed: 41.98uS, Gate open 30.48uS
         **********************************************************************/
         b0 = LN0_TAPEGATE;
         b1 = LN1_TAPEGATE;
+        if (tape0Takeup)
+            t0 = tape0PullTime.read(); // very slow..
+        if (tape1Takeup)
+            t1 = tape0PullTime.read(); // very slow..
         
         // LANE 0
-        if (!b0 && !tape0Takeup)
+        if (!b0 && !tape0Takeup) // cover tape slacked enough to interrupt gate
         {
+            tape0PullTime.reset();
+            tape0PullTime.start();
+            
             tape0Takeup = 1;
             tapeMotor0.Forward();
-            lane0Pickupout.attach(&stopTapeL0, TAPE_MAX_PULL_TIME);
         }
-        else if (b0)
+        else if ((b0 && t0 > TAPE_MIN_PULL_TIME) ||
+                 (!b0 && tape0Takeup && t0 > TAPE_MAX_PULL_TIME))
         {
             stopTapeL0();
         }
         
         // LANE 1
-        if (!b1 && !tape1Takeup)
+        if (!b1 && !tape1Takeup) // gate opened
         {
+            tape1PullTime.reset();
+            tape1PullTime.start();
+            
             tape1Takeup = 1;
             tapeMotor1.Forward();
-            lane1Pickupout.attach(&stopTapeL1, TAPE_MAX_PULL_TIME);
         }
-        else if (b1)
+        else if ((b1 && t1 > TAPE_MIN_PULL_TIME) ||
+                 (!b1 && tape1Takeup && t1 > TAPE_MAX_PULL_TIME))
         {
             stopTapeL1();
         }
diff -r 617334d8e3bb -r 4d3738338cf1 partNumbers.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/partNumbers.h	Sat Feb 04 01:27:29 2017 +0000
@@ -0,0 +1,36 @@
+// http://www.nxp.com/documents/user_manual/UM10462.pdf Page 407-408
+#define LPC11U12FHN33_201   { 0x09, 0x5C, 0x80, 0x2B }
+#define LPC11U12FHN33_201   { 0x29, 0x5C, 0x80, 0x2B }
+#define LPC11U12FBD48_201   { 0x09, 0x5C, 0x80, 0x2B }
+#define LPC11U12FBD48_201   { 0x29, 0x5C, 0x80, 0x2B }
+#define LPC11U13FBD48_201   { 0x09, 0x7A, 0x80, 0x2B }
+#define LPC11U13FBD48_201   { 0x29, 0x7A, 0x80, 0x2B }
+#define LPC11U14FHN33_201   { 0x09, 0x98, 0x80, 0x2B }
+#define LPC11U14FHN33_201   { 0x29, 0x98, 0x80, 0x2B }
+#define LPC11U14FHI33_201   { 0x29, 0x98, 0x80, 0x2B }
+#define LPC11U14FBD48_201   { 0x09, 0x98, 0x80, 0x2B }
+#define LPC11U14FBD48_201   { 0x29, 0x98, 0x80, 0x2B }
+#define LPC11U14FET48_201   { 0x09, 0x98, 0x80, 0x2B }
+#define LPC11U14FET48_201   { 0x29, 0x98, 0x80, 0x2B }
+#define LPC11U22FBD48_301   { 0x29, 0x54, 0x40, 0x2B }
+#define LPC11U23FBD48_301   { 0x29, 0x72, 0x40, 0x2B }
+#define LPC11U24FHI33_301   { 0x29, 0x88, 0x40, 0x2B }
+#define LPC11U24FBD48_301   { 0x29, 0x88, 0x40, 0x2B }
+#define LPC11U24FET48_301   { 0x29, 0x88, 0x40, 0x2B }
+#define LPC11U24FHN33_401   { 0x29, 0x80, 0x00, 0x2B }
+#define LPC11U24FBD48_401   { 0x29, 0x80, 0x00, 0x2B }
+#define LPC11U24FBD64_401   { 0x29, 0x80, 0x00, 0x2B }
+#define LPC11U34FHN33_311   { 0x00, 0x03, 0xD4, 0x40 }
+#define LPC11U34FBD48_311   { 0x00, 0x03, 0xD4, 0x40 }
+#define LPC11U34FHN33_421   { 0x00, 0x01, 0xCC, 0x40 }
+#define LPC11U34FBD48_421   { 0x00, 0x01, 0xCC, 0x40 }
+#define LPC11U35FHN33_401   { 0x00, 0x01, 0xBC, 0x40 }
+#define LPC11U35FBD48_401   { 0x00, 0x01, 0xBC, 0x40 }
+#define LPC11U35FBD64_401   { 0x00, 0x01, 0xBC, 0x40 }
+#define LPC11U35FHI33_501   { 0x00, 0x00, 0xBC, 0x40 }
+#define LPC11U35FET48_501   { 0x00, 0x00, 0xBC, 0x40 }
+#define LPC11U36FBD48_401   { 0x00, 0x01, 0x9C, 0x40 }
+#define LPC11U36FBD64_401   { 0x00, 0x01, 0x9C, 0x40 }
+#define LPC11U37FBD48_401   { 0x00, 0x01, 0x7C, 0x40 }
+#define LPC11U37HFBD64_401  { 0x00, 0x00, 0x7C, 0x44 }
+#define LPC11U37FBD64_501   { 0x00, 0x00, 0x7C, 0x40 }
\ No newline at end of file