Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed FastIO FastPWM USBDevice
Plunger/tsl14xxSensor.h@87:8d35c74403af, 2017-05-09 (annotated)
- Committer:
- mjr
- Date:
- Tue May 09 05:48:37 2017 +0000
- Revision:
- 87:8d35c74403af
- Parent:
- 86:e30a1f60f783
- Child:
- 100:1ff35c07217c
AEDR-8300, VL6180X, TLC59116; new plunger firing detection
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| mjr | 82:4f6209cb5c33 | 1 | // Base class for TSL14xx-based plunger sensors. | 
| mjr | 82:4f6209cb5c33 | 2 | // | 
| mjr | 82:4f6209cb5c33 | 3 | // This provides a common base class for plunger sensors based on | 
| mjr | 82:4f6209cb5c33 | 4 | // AMS/TAOS TSL14xx sensors (TSL1410R, TSL1412S, TSL1401CL). The sensors | 
| mjr | 82:4f6209cb5c33 | 5 | // in this series all work the same way, differing mostly in the number | 
| mjr | 82:4f6209cb5c33 | 6 | // of pixels. However, we have two fundamentally different ways of using | 
| mjr | 82:4f6209cb5c33 | 7 | // these image sensors to detect position: sensing the position of the | 
| mjr | 82:4f6209cb5c33 | 8 | // shadow cast by the plunger on the sensor, and optically reading a bar | 
| mjr | 82:4f6209cb5c33 | 9 | // code telling us the location of the sensor along a scale. This class | 
| mjr | 82:4f6209cb5c33 | 10 | // provides the low-level pixel-sensor interface; subclasses provide the | 
| mjr | 82:4f6209cb5c33 | 11 | // image analysis that figures the position from the captured image. | 
| mjr | 82:4f6209cb5c33 | 12 | |
| mjr | 82:4f6209cb5c33 | 13 | |
| mjr | 82:4f6209cb5c33 | 14 | #ifndef _TSL14XXSENSOR_H_ | 
| mjr | 82:4f6209cb5c33 | 15 | #define _TSL14XXSENSOR_H_ | 
| mjr | 82:4f6209cb5c33 | 16 | |
| mjr | 82:4f6209cb5c33 | 17 | #include "plunger.h" | 
| mjr | 87:8d35c74403af | 18 | #include "edgeSensor.h" | 
| mjr | 87:8d35c74403af | 19 | #include "barCodeSensor.h" | 
| mjr | 82:4f6209cb5c33 | 20 | #include "TSL14xx.h" | 
| mjr | 82:4f6209cb5c33 | 21 | |
| mjr | 87:8d35c74403af | 22 | class PlungerSensorImageInterfaceTSL14xx: public PlungerSensorImageInterface | 
| mjr | 82:4f6209cb5c33 | 23 | { | 
| mjr | 82:4f6209cb5c33 | 24 | public: | 
| mjr | 87:8d35c74403af | 25 | PlungerSensorImageInterfaceTSL14xx(int nativePix, PinName si, PinName clock, PinName ao) | 
| mjr | 87:8d35c74403af | 26 | : PlungerSensorImageInterface(nativePix), sensor(nativePix, si, clock, ao) | 
| mjr | 82:4f6209cb5c33 | 27 | { | 
| mjr | 82:4f6209cb5c33 | 28 | } | 
| mjr | 82:4f6209cb5c33 | 29 | |
| mjr | 82:4f6209cb5c33 | 30 | // is the sensor ready? | 
| mjr | 82:4f6209cb5c33 | 31 | virtual bool ready() { return sensor.ready(); } | 
| mjr | 82:4f6209cb5c33 | 32 | |
| mjr | 87:8d35c74403af | 33 | // is a DMA transfer in progress? | 
| mjr | 87:8d35c74403af | 34 | virtual bool dmaBusy() { return sensor.dmaBusy(); } | 
| mjr | 87:8d35c74403af | 35 | |
| mjr | 82:4f6209cb5c33 | 36 | virtual void init() | 
| mjr | 82:4f6209cb5c33 | 37 | { | 
| mjr | 82:4f6209cb5c33 | 38 | sensor.clear(); | 
| mjr | 82:4f6209cb5c33 | 39 | } | 
| mjr | 82:4f6209cb5c33 | 40 | |
| mjr | 87:8d35c74403af | 41 | // get the average sensor scan time | 
| mjr | 87:8d35c74403af | 42 | virtual uint32_t getAvgScanTime() { return sensor.getAvgScanTime(); } | 
| mjr | 87:8d35c74403af | 43 | |
| mjr | 87:8d35c74403af | 44 | protected: | 
| mjr | 87:8d35c74403af | 45 | virtual void getStatusReportPixels( | 
| mjr | 87:8d35c74403af | 46 | uint8_t* &pix, uint32_t &t, int axcTime, int extraTime) | 
| mjr | 82:4f6209cb5c33 | 47 | { | 
| mjr | 86:e30a1f60f783 | 48 | // The sensor's internal buffering scheme makes it a little tricky | 
| mjr | 86:e30a1f60f783 | 49 | // to get the requested timing, and our own double-buffering adds a | 
| mjr | 86:e30a1f60f783 | 50 | // little complexity as well. To get the exact timing requested, we | 
| mjr | 86:e30a1f60f783 | 51 | // have to work with the buffering pipeline like so: | 
| mjr | 82:4f6209cb5c33 | 52 | // | 
| mjr | 86:e30a1f60f783 | 53 | // 1. Call startCapture(). This waits for any in-progress pixel | 
| mjr | 86:e30a1f60f783 | 54 | // transfer from the sensor to finish, then executes a HOLD/SI pulse | 
| mjr | 86:e30a1f60f783 | 55 | // on the sensor. The HOLD/SI takes a snapshot of the current live | 
| mjr | 86:e30a1f60f783 | 56 | // photo receptors to the sensor shift register. These pixels have | 
| mjr | 86:e30a1f60f783 | 57 | // been integrating starting from before we were called; call this | 
| mjr | 86:e30a1f60f783 | 58 | // integration period A. So the shift register contains period A. | 
| mjr | 86:e30a1f60f783 | 59 | // The HOLD/SI then grounds the photo receptors, clearing their | 
| mjr | 86:e30a1f60f783 | 60 | // charge, thus starting a new integration period B. After sending | 
| mjr | 86:e30a1f60f783 | 61 | // the HOLD/SI pulse, startCapture() begins a DMA transfer of the | 
| mjr | 86:e30a1f60f783 | 62 | // shift register pixels (period A) to one of our two buffers (call | 
| mjr | 86:e30a1f60f783 | 63 | // it the EVEN buffer). | 
| mjr | 82:4f6209cb5c33 | 64 | // | 
| mjr | 86:e30a1f60f783 | 65 | // 2. Wait for the current transfer (period A to the EVEN buffer) | 
| mjr | 86:e30a1f60f783 | 66 | // to finish. The minimum integration time is the time of one | 
| mjr | 86:e30a1f60f783 | 67 | // transfer cycle, so this brings us to the minimum time for | 
| mjr | 86:e30a1f60f783 | 68 | // period B. | 
| mjr | 86:e30a1f60f783 | 69 | // | 
| mjr | 86:e30a1f60f783 | 70 | // 3. Now pause for the reqeusted extra delay time. Period B is | 
| mjr | 86:e30a1f60f783 | 71 | // still running at this point (it keeps going until we start a | 
| mjr | 86:e30a1f60f783 | 72 | // new capture), so this pause adds the requested extra time to | 
| mjr | 86:e30a1f60f783 | 73 | // period B's total integration time. This brings period B to | 
| mjr | 86:e30a1f60f783 | 74 | // exactly the requested total time. | 
| mjr | 82:4f6209cb5c33 | 75 | // | 
| mjr | 86:e30a1f60f783 | 76 | // 4. Call startCapture() to end period B, move period B's pixels | 
| mjr | 86:e30a1f60f783 | 77 | // to the sensor's shift register, and begin period C. This | 
| mjr | 86:e30a1f60f783 | 78 | // switches DMA buffers, so the EVEN buffer (with period A) is now | 
| mjr | 86:e30a1f60f783 | 79 | // available, and the ODD buffer becomes the DMA target for the | 
| mjr | 86:e30a1f60f783 | 80 | // period B pixels. | 
| mjr | 82:4f6209cb5c33 | 81 | // | 
| mjr | 86:e30a1f60f783 | 82 | // 5. Wait for the period B pixels to become available, via | 
| mjr | 86:e30a1f60f783 | 83 | // waitPix(). This waits for the DMA transfer to complete and | 
| mjr | 86:e30a1f60f783 | 84 | // hands us the latest (ODD) transfer buffer. | 
| mjr | 86:e30a1f60f783 | 85 | // | 
| mjr | 86:e30a1f60f783 | 86 | sensor.startCapture(axcTime); // begin transfer of pixels from incoming period A, begin integration period B | 
| mjr | 82:4f6209cb5c33 | 87 | sensor.wait(); // wait for scan of A to complete, as minimum integration B time | 
| mjr | 82:4f6209cb5c33 | 88 | wait_us(long(extraTime) * 100); // add extraTime (0.1ms == 100us increments) to integration B time | 
| mjr | 86:e30a1f60f783 | 89 | sensor.startCapture(axcTime); // begin transfer of pixels from integration period B, begin period C; period A pixels now available | 
| mjr | 82:4f6209cb5c33 | 90 | |
| mjr | 86:e30a1f60f783 | 91 | // wait for the DMA transfer of period B to finish, and get the | 
| mjr | 86:e30a1f60f783 | 92 | // period B pixels | 
| mjr | 86:e30a1f60f783 | 93 | sensor.waitPix(pix, t); | 
| mjr | 87:8d35c74403af | 94 | } | 
| mjr | 87:8d35c74403af | 95 | |
| mjr | 87:8d35c74403af | 96 | // reset after a status report | 
| mjr | 87:8d35c74403af | 97 | virtual void resetAfterStatusReport(int axcTime) | 
| mjr | 87:8d35c74403af | 98 | { | 
| mjr | 82:4f6209cb5c33 | 99 | // It takes us a while to send all of the pixels, since we have | 
| mjr | 82:4f6209cb5c33 | 100 | // to break them up into many USB reports. This delay means that | 
| mjr | 82:4f6209cb5c33 | 101 | // the sensor has been sitting there integrating for much longer | 
| mjr | 82:4f6209cb5c33 | 102 | // than usual, so the next frame read will be overexposed. To | 
| mjr | 82:4f6209cb5c33 | 103 | // mitigate this, make sure we don't have a capture running, | 
| mjr | 82:4f6209cb5c33 | 104 | // then clear the sensor and start a new capture. | 
| mjr | 82:4f6209cb5c33 | 105 | sensor.wait(); | 
| mjr | 82:4f6209cb5c33 | 106 | sensor.clear(); | 
| mjr | 82:4f6209cb5c33 | 107 | sensor.startCapture(axcTime); | 
| mjr | 82:4f6209cb5c33 | 108 | } | 
| mjr | 87:8d35c74403af | 109 | |
| mjr | 82:4f6209cb5c33 | 110 | // the low-level interface to the TSL14xx sensor | 
| mjr | 82:4f6209cb5c33 | 111 | TSL14xx sensor; | 
| mjr | 82:4f6209cb5c33 | 112 | }; | 
| mjr | 82:4f6209cb5c33 | 113 | |
| mjr | 86:e30a1f60f783 | 114 | // --------------------------------------------------------------------- | 
| mjr | 86:e30a1f60f783 | 115 | // | 
| mjr | 86:e30a1f60f783 | 116 | // Subclass for the large sensors, such as TSL1410R (1280 pixels) | 
| mjr | 86:e30a1f60f783 | 117 | // and TSL1412S (1536 pixels). | 
| mjr | 86:e30a1f60f783 | 118 | // | 
| mjr | 86:e30a1f60f783 | 119 | // For the large sensors, pixel transfers take a long time: about | 
| mjr | 86:e30a1f60f783 | 120 | // 2.5ms on the 1410R and 1412S. This is much longer than our main | 
| mjr | 86:e30a1f60f783 | 121 | // loop time, so we don't want to block other work to do a transfer. | 
| mjr | 86:e30a1f60f783 | 122 | // Instead, we want to do our transfers asynchronously, so that the | 
| mjr | 86:e30a1f60f783 | 123 | // main loop can keep going while a transfer proceeds. This is | 
| mjr | 86:e30a1f60f783 | 124 | // possible via our DMA double buffering. | 
| mjr | 86:e30a1f60f783 | 125 | // | 
| mjr | 86:e30a1f60f783 | 126 | // This scheme gives us three images in our pipeline at any given time: | 
| mjr | 86:e30a1f60f783 | 127 | // | 
| mjr | 86:e30a1f60f783 | 128 | // - a live image integrating light on the photo receptors on the sensor | 
| mjr | 86:e30a1f60f783 | 129 | // - the prior image being held in the sensor's shift register and being | 
| mjr | 86:e30a1f60f783 | 130 | // transferred via DMA into one of our buffers | 
| mjr | 86:e30a1f60f783 | 131 | // - the image before that in our other buffer | 
| mjr | 86:e30a1f60f783 | 132 | // | 
| mjr | 86:e30a1f60f783 | 133 | // Integration of a live image starts when we begin the transfer of the | 
| mjr | 86:e30a1f60f783 | 134 | // prior image. Integration ends when we start the next transfer after | 
| mjr | 86:e30a1f60f783 | 135 | // that. So the total integration time, which is to say the exposure | 
| mjr | 86:e30a1f60f783 | 136 | // time, is the time between consecutive transfer starts. It's important | 
| mjr | 86:e30a1f60f783 | 137 | // for this time to be consistent from image to image, because that | 
| mjr | 86:e30a1f60f783 | 138 | // determines the exposure level. We use polling from the main loop | 
| mjr | 86:e30a1f60f783 | 139 | // to initiate new transfers, so the main loop is responsible for | 
| mjr | 86:e30a1f60f783 | 140 | // polling frequently during the 2.5ms transfer period. It would be | 
| mjr | 86:e30a1f60f783 | 141 | // more consistent if we did this in an interrupt handler instead, | 
| mjr | 86:e30a1f60f783 | 142 | // but that would complicate things considerably since our image | 
| mjr | 86:e30a1f60f783 | 143 | // analysis is too time-consuming to do in interrupt context. | 
| mjr | 86:e30a1f60f783 | 144 | // | 
| mjr | 87:8d35c74403af | 145 | class PlungerSensorTSL14xxLarge: public PlungerSensorImageInterfaceTSL14xx | 
| mjr | 86:e30a1f60f783 | 146 | { | 
| mjr | 86:e30a1f60f783 | 147 | public: | 
| mjr | 87:8d35c74403af | 148 | PlungerSensorTSL14xxLarge(int nativePix, PinName si, PinName clock, PinName ao) | 
| mjr | 87:8d35c74403af | 149 | : PlungerSensorImageInterfaceTSL14xx(nativePix, si, clock, ao) | 
| mjr | 86:e30a1f60f783 | 150 | { | 
| mjr | 86:e30a1f60f783 | 151 | } | 
| mjr | 86:e30a1f60f783 | 152 | |
| mjr | 87:8d35c74403af | 153 | virtual void readPix(uint8_t* &pix, uint32_t &t, int axcTime) | 
| mjr | 87:8d35c74403af | 154 | { | 
| mjr | 86:e30a1f60f783 | 155 | // start reading the next pixel array (this waits for any DMA | 
| mjr | 86:e30a1f60f783 | 156 | // transfer in progress to finish, ensuring a stable pixel buffer) | 
| mjr | 86:e30a1f60f783 | 157 | sensor.startCapture(axcTime); | 
| mjr | 86:e30a1f60f783 | 158 | |
| mjr | 86:e30a1f60f783 | 159 | // get the image array from the last capture | 
| mjr | 87:8d35c74403af | 160 | sensor.getPix(pix, t); | 
| mjr | 86:e30a1f60f783 | 161 | |
| mjr | 86:e30a1f60f783 | 162 | } | 
| mjr | 86:e30a1f60f783 | 163 | }; | 
| mjr | 86:e30a1f60f783 | 164 | |
| mjr | 86:e30a1f60f783 | 165 | // --------------------------------------------------------------------- | 
| mjr | 86:e30a1f60f783 | 166 | // | 
| mjr | 86:e30a1f60f783 | 167 | // Subclass for the small sensors, such as TSL1401CL (128 pixels). | 
| mjr | 86:e30a1f60f783 | 168 | // | 
| mjr | 86:e30a1f60f783 | 169 | // For the small sensors, we can't use the asynchronous transfer | 
| mjr | 86:e30a1f60f783 | 170 | // scheme we use for the large sensors, because the transfer times | 
| mjr | 86:e30a1f60f783 | 171 | // are so short that the main loop can't poll frequently enough to | 
| mjr | 86:e30a1f60f783 | 172 | // maintain consistent exposure times. With the short transfer | 
| mjr | 86:e30a1f60f783 | 173 | // times, though, we don't need to do them asynchronously. | 
| mjr | 86:e30a1f60f783 | 174 | // | 
| mjr | 86:e30a1f60f783 | 175 | // Instead, each time we want to read the sensor, we do the whole | 
| mjr | 86:e30a1f60f783 | 176 | // integration and transfer synchronously, so that we can precisly | 
| mjr | 86:e30a1f60f783 | 177 | // control the total time. This requires two transfers. First, | 
| mjr | 86:e30a1f60f783 | 178 | // we start a transfer in order to set the exact starting time of | 
| mjr | 86:e30a1f60f783 | 179 | // an integration period: call it period A. We wait for the | 
| mjr | 86:e30a1f60f783 | 180 | // transfer to complete, which fills a buffer with the prior | 
| mjr | 86:e30a1f60f783 | 181 | // integration period's pixels. We don't want those pixels, | 
| mjr | 86:e30a1f60f783 | 182 | // because they started before we got here and thus we can't | 
| mjr | 86:e30a1f60f783 | 183 | // control how long they were integrating. So we discard that | 
| mjr | 86:e30a1f60f783 | 184 | // buffer and start a new transfer. This starts period B while | 
| mjr | 86:e30a1f60f783 | 185 | // transferring period A's pixels into a DMA buffer. We want | 
| mjr | 86:e30a1f60f783 | 186 | // those period A pixels, so we wait for this transfer to finish. | 
| mjr | 86:e30a1f60f783 | 187 | // | 
| mjr | 87:8d35c74403af | 188 | class PlungerSensorTSL14xxSmall: public PlungerSensorImageInterfaceTSL14xx | 
| mjr | 86:e30a1f60f783 | 189 | { | 
| mjr | 86:e30a1f60f783 | 190 | public: | 
| mjr | 87:8d35c74403af | 191 | PlungerSensorTSL14xxSmall(int nativePix, PinName si, PinName clock, PinName ao) | 
| mjr | 87:8d35c74403af | 192 | : PlungerSensorImageInterfaceTSL14xx(nativePix, si, clock, ao) | 
| mjr | 86:e30a1f60f783 | 193 | { | 
| mjr | 86:e30a1f60f783 | 194 | } | 
| mjr | 86:e30a1f60f783 | 195 | |
| mjr | 87:8d35c74403af | 196 | // read the image | 
| mjr | 87:8d35c74403af | 197 | virtual void readPix(uint8_t* &pix, uint32_t &t, int axcTime) | 
| mjr | 86:e30a1f60f783 | 198 | { | 
| mjr | 86:e30a1f60f783 | 199 | // Clear the sensor. This sends a HOLD/SI pulse to the sensor, | 
| mjr | 86:e30a1f60f783 | 200 | // which ends the current integration period, starts a new one | 
| mjr | 86:e30a1f60f783 | 201 | // (call the new one period A) right now, and clocks out all | 
| mjr | 86:e30a1f60f783 | 202 | // of the pixels from the old cycle. We want to discard these | 
| mjr | 86:e30a1f60f783 | 203 | // pixels because they've been integrating from some time in | 
| mjr | 86:e30a1f60f783 | 204 | // the past, so we can't control the exact timing of that cycle. | 
| mjr | 86:e30a1f60f783 | 205 | // Clearing the sensor clocks the pixels out without waiting to | 
| mjr | 86:e30a1f60f783 | 206 | // read them on DMA, so it's much faster than a regular transfer | 
| mjr | 86:e30a1f60f783 | 207 | // and thus gives us the shortest possible base integration time | 
| mjr | 86:e30a1f60f783 | 208 | // for period A. | 
| mjr | 86:e30a1f60f783 | 209 | sensor.clear(); | 
| mjr | 86:e30a1f60f783 | 210 | |
| mjr | 86:e30a1f60f783 | 211 | // Start a real transfer. This ends integration period A (the | 
| mjr | 86:e30a1f60f783 | 212 | // one we just started), starts a new integration period B, and | 
| mjr | 86:e30a1f60f783 | 213 | // begins transferring period A's pixels to memory via DMA. We | 
| mjr | 86:e30a1f60f783 | 214 | // use the auto-exposure time to get the optimal exposure. | 
| mjr | 86:e30a1f60f783 | 215 | sensor.startCapture(axcTime); | 
| mjr | 86:e30a1f60f783 | 216 | |
| mjr | 86:e30a1f60f783 | 217 | // wait for the period A pixel transfer to finish, and grab | 
| mjr | 86:e30a1f60f783 | 218 | // its pixels | 
| mjr | 87:8d35c74403af | 219 | sensor.waitPix(pix, t); | 
| mjr | 86:e30a1f60f783 | 220 | } | 
| mjr | 86:e30a1f60f783 | 221 | }; | 
| mjr | 86:e30a1f60f783 | 222 | |
| mjr | 86:e30a1f60f783 | 223 | |
| mjr | 87:8d35c74403af | 224 | // ------------------------------------------------------------------------- | 
| mjr | 87:8d35c74403af | 225 | // | 
| mjr | 87:8d35c74403af | 226 | // Concrete TSL14xx sensor types | 
| mjr | 87:8d35c74403af | 227 | // | 
| mjr | 87:8d35c74403af | 228 | |
| mjr | 87:8d35c74403af | 229 | |
| mjr | 87:8d35c74403af | 230 | // TSL1410R sensor - edge detection sensor | 
| mjr | 87:8d35c74403af | 231 | class PlungerSensorTSL1410R: public PlungerSensorEdgePos | 
| mjr | 87:8d35c74403af | 232 | { | 
| mjr | 87:8d35c74403af | 233 | public: | 
| mjr | 87:8d35c74403af | 234 | PlungerSensorTSL1410R(PinName si, PinName clock, PinName ao) | 
| mjr | 87:8d35c74403af | 235 | : PlungerSensorEdgePos(sensor, 1280), sensor(1280, si, clock, ao) | 
| mjr | 87:8d35c74403af | 236 | { | 
| mjr | 87:8d35c74403af | 237 | } | 
| mjr | 87:8d35c74403af | 238 | |
| mjr | 87:8d35c74403af | 239 | protected: | 
| mjr | 87:8d35c74403af | 240 | PlungerSensorTSL14xxLarge sensor; | 
| mjr | 87:8d35c74403af | 241 | }; | 
| mjr | 87:8d35c74403af | 242 | |
| mjr | 87:8d35c74403af | 243 | // TSL1412R - edge detection sensor | 
| mjr | 87:8d35c74403af | 244 | class PlungerSensorTSL1412R: public PlungerSensorEdgePos | 
| mjr | 87:8d35c74403af | 245 | { | 
| mjr | 87:8d35c74403af | 246 | public: | 
| mjr | 87:8d35c74403af | 247 | PlungerSensorTSL1412R(PinName si, PinName clock, PinName ao) | 
| mjr | 87:8d35c74403af | 248 | : PlungerSensorEdgePos(sensor, 1536), sensor(1536, si, clock, ao) | 
| mjr | 87:8d35c74403af | 249 | { | 
| mjr | 87:8d35c74403af | 250 | } | 
| mjr | 87:8d35c74403af | 251 | |
| mjr | 87:8d35c74403af | 252 | protected: | 
| mjr | 87:8d35c74403af | 253 | PlungerSensorTSL14xxLarge sensor; | 
| mjr | 87:8d35c74403af | 254 | }; | 
| mjr | 87:8d35c74403af | 255 | |
| mjr | 87:8d35c74403af | 256 | // TSL1401CL - bar code sensor | 
| mjr | 87:8d35c74403af | 257 | class PlungerSensorTSL1401CL: public PlungerSensorBarCode<7, 0, 1, 16> | 
| mjr | 87:8d35c74403af | 258 | { | 
| mjr | 87:8d35c74403af | 259 | public: | 
| mjr | 87:8d35c74403af | 260 | PlungerSensorTSL1401CL(PinName si, PinName clock, PinName ao) | 
| mjr | 87:8d35c74403af | 261 | : PlungerSensorBarCode(sensor, 128), sensor(128, si, clock, ao) | 
| mjr | 87:8d35c74403af | 262 | { | 
| mjr | 87:8d35c74403af | 263 | } | 
| mjr | 87:8d35c74403af | 264 | |
| mjr | 87:8d35c74403af | 265 | protected: | 
| mjr | 87:8d35c74403af | 266 | PlungerSensorTSL14xxSmall sensor; | 
| mjr | 87:8d35c74403af | 267 | }; | 
| mjr | 87:8d35c74403af | 268 | |
| mjr | 87:8d35c74403af | 269 | |
| mjr | 82:4f6209cb5c33 | 270 | #endif |