Library for the ADJD-S371, Avago Colour Sensor
ADJDColourSensor.cpp@0:47465be3223d, 2010-10-01 (annotated)
- Committer:
- MichaelW
- Date:
- Fri Oct 01 13:39:51 2010 +0000
- Revision:
- 0:47465be3223d
Supports reading from the sensors and writing to the configuration registers. Doesn\t have built in optimisation yet
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MichaelW | 0:47465be3223d | 1 | /** |
MichaelW | 0:47465be3223d | 2 | * @section LICENSE |
MichaelW | 0:47465be3223d | 3 | *Copyright (c) 2010 ARM Ltd. |
MichaelW | 0:47465be3223d | 4 | * |
MichaelW | 0:47465be3223d | 5 | *Permission is hereby granted, free of charge, to any person obtaining a copy |
MichaelW | 0:47465be3223d | 6 | *of this software and associated documentation files (the "Software"), to deal |
MichaelW | 0:47465be3223d | 7 | *in the Software without restriction, including without limitation the rights |
MichaelW | 0:47465be3223d | 8 | *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
MichaelW | 0:47465be3223d | 9 | *copies of the Software, and to permit persons to whom the Software is |
MichaelW | 0:47465be3223d | 10 | *furnished to do so, subject to the following conditions: |
MichaelW | 0:47465be3223d | 11 | * |
MichaelW | 0:47465be3223d | 12 | *The above copyright notice and this permission notice shall be included in |
MichaelW | 0:47465be3223d | 13 | *all copies or substantial portions of the Software. |
MichaelW | 0:47465be3223d | 14 | * |
MichaelW | 0:47465be3223d | 15 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
MichaelW | 0:47465be3223d | 16 | *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
MichaelW | 0:47465be3223d | 17 | *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
MichaelW | 0:47465be3223d | 18 | *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
MichaelW | 0:47465be3223d | 19 | *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
MichaelW | 0:47465be3223d | 20 | *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
MichaelW | 0:47465be3223d | 21 | *THE SOFTWARE. |
MichaelW | 0:47465be3223d | 22 | * |
MichaelW | 0:47465be3223d | 23 | * |
MichaelW | 0:47465be3223d | 24 | * @section DESCRIPTION |
MichaelW | 0:47465be3223d | 25 | * |
MichaelW | 0:47465be3223d | 26 | * |
MichaelW | 0:47465be3223d | 27 | */ |
MichaelW | 0:47465be3223d | 28 | |
MichaelW | 0:47465be3223d | 29 | #include "ADJDColourSensor.h" |
MichaelW | 0:47465be3223d | 30 | |
MichaelW | 0:47465be3223d | 31 | ADJDColourSensor::ADJDColourSensor(PinName sda, PinName scl, PinName LED): |
MichaelW | 0:47465be3223d | 32 | _sensor(sda, scl), |
MichaelW | 0:47465be3223d | 33 | _LED(LED) |
MichaelW | 0:47465be3223d | 34 | { |
MichaelW | 0:47465be3223d | 35 | _address = 0x74 << 1; |
MichaelW | 0:47465be3223d | 36 | char cmd[2]; |
MichaelW | 0:47465be3223d | 37 | cmd[0] = 1; //Config reg |
MichaelW | 0:47465be3223d | 38 | cmd[1] = 0x01; //setup |
MichaelW | 0:47465be3223d | 39 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 40 | |
MichaelW | 0:47465be3223d | 41 | setCapacitors(0x0E,0x0E,0x0E,0x0E); |
MichaelW | 0:47465be3223d | 42 | //Good for 500 under office light |
MichaelW | 0:47465be3223d | 43 | setIntegrationTimeSlot(900,1000,1800,600); |
MichaelW | 0:47465be3223d | 44 | //1000, 1000, 1700, 600 |
MichaelW | 0:47465be3223d | 45 | |
MichaelW | 0:47465be3223d | 46 | |
MichaelW | 0:47465be3223d | 47 | setIntegrationTimeSlot(1300,1400,2200,1000); |
MichaelW | 0:47465be3223d | 48 | |
MichaelW | 0:47465be3223d | 49 | } |
MichaelW | 0:47465be3223d | 50 | |
MichaelW | 0:47465be3223d | 51 | void ADJDColourSensor::setCapacitors(int redCap, int greenCap, int blueCap, int clearCap){ |
MichaelW | 0:47465be3223d | 52 | //Values from 00H to 0FH |
MichaelW | 0:47465be3223d | 53 | char cmd[2]; |
MichaelW | 0:47465be3223d | 54 | //Red |
MichaelW | 0:47465be3223d | 55 | cmd[0] = 0x06; //Cap Red |
MichaelW | 0:47465be3223d | 56 | cmd[1] = redCap; // |
MichaelW | 0:47465be3223d | 57 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 58 | |
MichaelW | 0:47465be3223d | 59 | //Green |
MichaelW | 0:47465be3223d | 60 | cmd[0] = 0x07; //Cap Green |
MichaelW | 0:47465be3223d | 61 | cmd[1] = greenCap; // |
MichaelW | 0:47465be3223d | 62 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 63 | |
MichaelW | 0:47465be3223d | 64 | //Blue |
MichaelW | 0:47465be3223d | 65 | cmd[0] = 0x08; //Cap Blue |
MichaelW | 0:47465be3223d | 66 | cmd[1] = blueCap; // |
MichaelW | 0:47465be3223d | 67 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 68 | |
MichaelW | 0:47465be3223d | 69 | //Clear |
MichaelW | 0:47465be3223d | 70 | cmd[0] = 0x09; //Cap clear |
MichaelW | 0:47465be3223d | 71 | cmd[1] = clearCap; // |
MichaelW | 0:47465be3223d | 72 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 73 | } |
MichaelW | 0:47465be3223d | 74 | void ADJDColourSensor::setIntegrationTimeSlot(int redInt, int greenInt, int blueInt, int clearInt){ |
MichaelW | 0:47465be3223d | 75 | //values should be 0 to 4095 |
MichaelW | 0:47465be3223d | 76 | char cmd[2]; |
MichaelW | 0:47465be3223d | 77 | //Red |
MichaelW | 0:47465be3223d | 78 | cmd[0] = 0x0A; //int red low |
MichaelW | 0:47465be3223d | 79 | cmd[1] = redInt & 0xFF; //redInt low |
MichaelW | 0:47465be3223d | 80 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 81 | |
MichaelW | 0:47465be3223d | 82 | cmd[0] = 0x0B; //int red high |
MichaelW | 0:47465be3223d | 83 | cmd[1] = (redInt >> 8) & 0x0F; //redInt high |
MichaelW | 0:47465be3223d | 84 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 85 | |
MichaelW | 0:47465be3223d | 86 | //Green |
MichaelW | 0:47465be3223d | 87 | cmd[0] = 0x0C; //int green low |
MichaelW | 0:47465be3223d | 88 | cmd[1] = greenInt & 0xFF; //greenInt low |
MichaelW | 0:47465be3223d | 89 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 90 | |
MichaelW | 0:47465be3223d | 91 | cmd[0] = 0x0D; //int green high |
MichaelW | 0:47465be3223d | 92 | cmd[1] = (greenInt >> 8) & 0x0F; //greenInt high |
MichaelW | 0:47465be3223d | 93 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 94 | |
MichaelW | 0:47465be3223d | 95 | //Blue |
MichaelW | 0:47465be3223d | 96 | cmd[0] = 0x0E; //int blue low |
MichaelW | 0:47465be3223d | 97 | cmd[1] = blueInt & 0xFF; //blueInt low |
MichaelW | 0:47465be3223d | 98 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 99 | |
MichaelW | 0:47465be3223d | 100 | cmd[0] = 0x0F; //int blue high |
MichaelW | 0:47465be3223d | 101 | cmd[1] = (blueInt >> 8) & 0x0F; //blueInt high |
MichaelW | 0:47465be3223d | 102 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 103 | |
MichaelW | 0:47465be3223d | 104 | //Clear |
MichaelW | 0:47465be3223d | 105 | cmd[0] = 0x10; //int clear low |
MichaelW | 0:47465be3223d | 106 | cmd[1] = clearInt & 0xFF; //clearInt low |
MichaelW | 0:47465be3223d | 107 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 108 | |
MichaelW | 0:47465be3223d | 109 | cmd[0] = 0x11; //int clear high |
MichaelW | 0:47465be3223d | 110 | cmd[1] = (clearInt >> 8) & 0x0F; //clearInt high |
MichaelW | 0:47465be3223d | 111 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 112 | } |
MichaelW | 0:47465be3223d | 113 | float ADJDColourSensor::read(){ |
MichaelW | 0:47465be3223d | 114 | |
MichaelW | 0:47465be3223d | 115 | _LED = 1; |
MichaelW | 0:47465be3223d | 116 | |
MichaelW | 0:47465be3223d | 117 | char cmd[2]; |
MichaelW | 0:47465be3223d | 118 | char cmd2[2]; |
MichaelW | 0:47465be3223d | 119 | char Result[2]; |
MichaelW | 0:47465be3223d | 120 | cmd[0] = 0x00; //CTRL reg |
MichaelW | 0:47465be3223d | 121 | cmd[1] = 0x01; //Get sensor |
MichaelW | 0:47465be3223d | 122 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 123 | wait(0.1); |
MichaelW | 0:47465be3223d | 124 | |
MichaelW | 0:47465be3223d | 125 | do{ |
MichaelW | 0:47465be3223d | 126 | wait(0.1); |
MichaelW | 0:47465be3223d | 127 | cmd[0] = 0; |
MichaelW | 0:47465be3223d | 128 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 129 | _sensor.read(_address, cmd2, 1); |
MichaelW | 0:47465be3223d | 130 | //printf("sensing %i\n", int(cmd2[0])); |
MichaelW | 0:47465be3223d | 131 | }while(cmd2[0] != 0); //Wait for CTRl register to be clear |
MichaelW | 0:47465be3223d | 132 | |
MichaelW | 0:47465be3223d | 133 | |
MichaelW | 0:47465be3223d | 134 | //red |
MichaelW | 0:47465be3223d | 135 | cmd[0] = 0x40; |
MichaelW | 0:47465be3223d | 136 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 137 | _sensor.read(_address, Result, 1); |
MichaelW | 0:47465be3223d | 138 | cmd[0] = 0x41; |
MichaelW | 0:47465be3223d | 139 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 140 | _sensor.read(_address, cmd2, 1); |
MichaelW | 0:47465be3223d | 141 | _red = Result[0] | ((cmd2[0] & 0x03) << 8); |
MichaelW | 0:47465be3223d | 142 | |
MichaelW | 0:47465be3223d | 143 | |
MichaelW | 0:47465be3223d | 144 | //Green |
MichaelW | 0:47465be3223d | 145 | cmd[0] = 0x42; |
MichaelW | 0:47465be3223d | 146 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 147 | _sensor.read(_address, Result, 1); |
MichaelW | 0:47465be3223d | 148 | cmd[0] = 0x43; |
MichaelW | 0:47465be3223d | 149 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 150 | _sensor.read(_address, cmd2, 1); |
MichaelW | 0:47465be3223d | 151 | _green = Result[0] | ((cmd2[0] & 0x03) << 8); |
MichaelW | 0:47465be3223d | 152 | |
MichaelW | 0:47465be3223d | 153 | //Blue |
MichaelW | 0:47465be3223d | 154 | cmd[0] = 0x44; |
MichaelW | 0:47465be3223d | 155 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 156 | _sensor.read(_address, Result, 1); |
MichaelW | 0:47465be3223d | 157 | cmd[0] = 0x45; |
MichaelW | 0:47465be3223d | 158 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 159 | _sensor.read(_address, cmd2, 1); |
MichaelW | 0:47465be3223d | 160 | _blue = Result[0] | ((cmd2[0] & 0x03) << 8); |
MichaelW | 0:47465be3223d | 161 | _LED = 0; |
MichaelW | 0:47465be3223d | 162 | |
MichaelW | 0:47465be3223d | 163 | //Clear |
MichaelW | 0:47465be3223d | 164 | float clear; |
MichaelW | 0:47465be3223d | 165 | cmd[0] = 0x46; |
MichaelW | 0:47465be3223d | 166 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 167 | _sensor.read(_address, Result, 1); |
MichaelW | 0:47465be3223d | 168 | cmd[0] = 0x47; |
MichaelW | 0:47465be3223d | 169 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 170 | _sensor.read(_address, cmd2, 1); |
MichaelW | 0:47465be3223d | 171 | _clear = Result[0] | ((cmd2[0] & 0x03) << 8); |
MichaelW | 0:47465be3223d | 172 | |
MichaelW | 0:47465be3223d | 173 | |
MichaelW | 0:47465be3223d | 174 | //Convert the private int values into the output float values |
MichaelW | 0:47465be3223d | 175 | red = (float)_red; |
MichaelW | 0:47465be3223d | 176 | green = (float)_green; |
MichaelW | 0:47465be3223d | 177 | blue = (float)_blue; |
MichaelW | 0:47465be3223d | 178 | clear = (float)_clear; |
MichaelW | 0:47465be3223d | 179 | |
MichaelW | 0:47465be3223d | 180 | return(clear); |
MichaelW | 0:47465be3223d | 181 | } |
MichaelW | 0:47465be3223d | 182 | |
MichaelW | 0:47465be3223d | 183 | int ADJDColourSensor::readOffset(){ |
MichaelW | 0:47465be3223d | 184 | _LED = 1; |
MichaelW | 0:47465be3223d | 185 | char cmd[2]; |
MichaelW | 0:47465be3223d | 186 | cmd[0] = 0; //CTRL reg |
MichaelW | 0:47465be3223d | 187 | cmd[1] = 2; //Get sensor |
MichaelW | 0:47465be3223d | 188 | _sensor.write(_address, cmd, 2); |
MichaelW | 0:47465be3223d | 189 | |
MichaelW | 0:47465be3223d | 190 | wait(0.1); //Or wait till bit cleared |
MichaelW | 0:47465be3223d | 191 | |
MichaelW | 0:47465be3223d | 192 | //Red |
MichaelW | 0:47465be3223d | 193 | cmd[0] = 0x48; |
MichaelW | 0:47465be3223d | 194 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 195 | _sensor.read(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 196 | redOffset = cmd[0]; |
MichaelW | 0:47465be3223d | 197 | |
MichaelW | 0:47465be3223d | 198 | //Green |
MichaelW | 0:47465be3223d | 199 | cmd[0] = 0x49; |
MichaelW | 0:47465be3223d | 200 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 201 | _sensor.read(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 202 | greenOffset = cmd[0]; |
MichaelW | 0:47465be3223d | 203 | |
MichaelW | 0:47465be3223d | 204 | //Blue |
MichaelW | 0:47465be3223d | 205 | cmd[0] = 0x4A; |
MichaelW | 0:47465be3223d | 206 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 207 | _sensor.read(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 208 | blueOffset = cmd[0]; |
MichaelW | 0:47465be3223d | 209 | |
MichaelW | 0:47465be3223d | 210 | //Clear |
MichaelW | 0:47465be3223d | 211 | cmd[0] = 0x4B; |
MichaelW | 0:47465be3223d | 212 | _sensor.write(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 213 | _sensor.read(_address, cmd, 1); |
MichaelW | 0:47465be3223d | 214 | clearOffset = cmd[0]; |
MichaelW | 0:47465be3223d | 215 | |
MichaelW | 0:47465be3223d | 216 | _LED = 0; |
MichaelW | 0:47465be3223d | 217 | |
MichaelW | 0:47465be3223d | 218 | return(clearOffset); |
MichaelW | 0:47465be3223d | 219 | |
MichaelW | 0:47465be3223d | 220 | } |
MichaelW | 0:47465be3223d | 221 | void ADJDColourSensor::optimise(){ |
MichaelW | 0:47465be3223d | 222 | optimise(500,500,500,500); |
MichaelW | 0:47465be3223d | 223 | } |
MichaelW | 0:47465be3223d | 224 | void ADJDColourSensor::optimise(int optimum){ |
MichaelW | 0:47465be3223d | 225 | optimise(optimum,optimum,optimum,optimum); |
MichaelW | 0:47465be3223d | 226 | } |
MichaelW | 0:47465be3223d | 227 | void ADJDColourSensor::optimise(int redTarget, int blueTarget, int greenTarget ,int clearTarget){ |
MichaelW | 0:47465be3223d | 228 | //use capacitor as they are to begin with |
MichaelW | 0:47465be3223d | 229 | |
MichaelW | 0:47465be3223d | 230 | //Optimise all at once as reading |
MichaelW | 0:47465be3223d | 231 | int redInt = 1000; |
MichaelW | 0:47465be3223d | 232 | int greenInt = 1000; |
MichaelW | 0:47465be3223d | 233 | int blueInt = 1000; |
MichaelW | 0:47465be3223d | 234 | int clearInt = 1000; |
MichaelW | 0:47465be3223d | 235 | int range = 20; |
MichaelW | 0:47465be3223d | 236 | bool Optimised = false; |
MichaelW | 0:47465be3223d | 237 | read(); |
MichaelW | 0:47465be3223d | 238 | while(!Optimised){ |
MichaelW | 0:47465be3223d | 239 | |
MichaelW | 0:47465be3223d | 240 | |
MichaelW | 0:47465be3223d | 241 | //Optimise red |
MichaelW | 0:47465be3223d | 242 | if(_red > (redTarget + range)){ |
MichaelW | 0:47465be3223d | 243 | //too big so decreae redInt |
MichaelW | 0:47465be3223d | 244 | redInt = redInt - 50; |
MichaelW | 0:47465be3223d | 245 | }else{ |
MichaelW | 0:47465be3223d | 246 | if(_red < (redTarget - range)){ |
MichaelW | 0:47465be3223d | 247 | //too low so increase redInt |
MichaelW | 0:47465be3223d | 248 | redInt = redInt + 50; |
MichaelW | 0:47465be3223d | 249 | } |
MichaelW | 0:47465be3223d | 250 | } |
MichaelW | 0:47465be3223d | 251 | //optimise blue |
MichaelW | 0:47465be3223d | 252 | if(_blue > (blueTarget + range)){ |
MichaelW | 0:47465be3223d | 253 | blueInt = blueInt - 50; |
MichaelW | 0:47465be3223d | 254 | }else{ |
MichaelW | 0:47465be3223d | 255 | if(_blue < (blueTarget - range)){ |
MichaelW | 0:47465be3223d | 256 | blueInt = blueInt + 50; |
MichaelW | 0:47465be3223d | 257 | } |
MichaelW | 0:47465be3223d | 258 | } |
MichaelW | 0:47465be3223d | 259 | |
MichaelW | 0:47465be3223d | 260 | //optimise green |
MichaelW | 0:47465be3223d | 261 | if(_green > (greenTarget + range)){ |
MichaelW | 0:47465be3223d | 262 | greenInt = greenInt - 50; |
MichaelW | 0:47465be3223d | 263 | }else{ |
MichaelW | 0:47465be3223d | 264 | if(_green < (greenTarget - range)){ |
MichaelW | 0:47465be3223d | 265 | greenInt = greenInt + 50; |
MichaelW | 0:47465be3223d | 266 | } |
MichaelW | 0:47465be3223d | 267 | } |
MichaelW | 0:47465be3223d | 268 | |
MichaelW | 0:47465be3223d | 269 | //Optimise Clear |
MichaelW | 0:47465be3223d | 270 | if(_clear > (clearTarget + range)){ |
MichaelW | 0:47465be3223d | 271 | clearInt = clearInt - 50; |
MichaelW | 0:47465be3223d | 272 | }else{ |
MichaelW | 0:47465be3223d | 273 | if(_clear < (clearTarget - range)){ |
MichaelW | 0:47465be3223d | 274 | clearInt = clearInt + 50; |
MichaelW | 0:47465be3223d | 275 | } |
MichaelW | 0:47465be3223d | 276 | } |
MichaelW | 0:47465be3223d | 277 | |
MichaelW | 0:47465be3223d | 278 | //Check if any of the integration values have exceeded the max limits (0 to 4095) and if so try changing the capacitors |
MichaelW | 0:47465be3223d | 279 | if((redInt > 4095 || greenInt > 4095 || blueInt > 4095 || clearInt > 4095) || (redInt <= 0 || greenInt <= 0 || blueInt <= 0 || clearInt <= 0)){ |
MichaelW | 0:47465be3223d | 280 | printf("Also need to change the capacitor values\n"); |
MichaelW | 0:47465be3223d | 281 | } |
MichaelW | 0:47465be3223d | 282 | //Send the new optimisation |
MichaelW | 0:47465be3223d | 283 | setIntegrationTimeSlot(redInt, greenInt, blueInt, clearInt); |
MichaelW | 0:47465be3223d | 284 | |
MichaelW | 0:47465be3223d | 285 | //get new values |
MichaelW | 0:47465be3223d | 286 | _clear = read(); |
MichaelW | 0:47465be3223d | 287 | |
MichaelW | 0:47465be3223d | 288 | //Check if optimised |
MichaelW | 0:47465be3223d | 289 | if((_red < (redTarget + range) && (_red > redTarget - range)) && (_green < (greenTarget + range) && (_green > greenTarget - range)) && (_blue < (blueTarget + range) && (_blue > blueTarget - range)) && (_clear < (clearTarget + range) && (_clear > clearTarget - range)))Optimised = true; |
MichaelW | 0:47465be3223d | 290 | |
MichaelW | 0:47465be3223d | 291 | } |
MichaelW | 0:47465be3223d | 292 | |
MichaelW | 0:47465be3223d | 293 | |
MichaelW | 0:47465be3223d | 294 | //Should check max condition (Outputs do not exceed 1000) - or is the above optimising for max condition |
MichaelW | 0:47465be3223d | 295 | |
MichaelW | 0:47465be3223d | 296 | } |