The MBED firmware used on the Chipin sorter, developed over 12 weeks for a 3rd year university systems project. Chipin is a token sorter, it sorts tokens by colours and dispenses them to order through an online booking system and card reader. This program interfaces with an FPGA, PC and LCD screen to control the sorter. The sorter has an operation mode where it can process orders when a card is entered into the machine. There is also a maintenance mode where the device responds to maintenance instructions such as 'dispense all'. More information at http://www.ionsystems.uk/

Dependencies:   MCP23017 TCS3472_I2C WattBob_TextLCD mbed-rtos mbed

Committer:
IonSystems
Date:
Wed Dec 03 17:49:41 2014 +0000
Revision:
24:8868101d01d0
Parent:
23:f9e7e64784be
Child:
25:7f5d764d8e34
Commented the .h files from top to bottom, got half way through FPGAcomms

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IonSystems 6:e64796f1f384 1 #include "mbed.h"
IonSystems 11:06f6e82b40a8 2 #include "colourProcessing.h"
IonSystems 24:8868101d01d0 3 ////////////////////////////
IonSystems 24:8868101d01d0 4 // START OF I/O DEFINITIONS
IonSystems 24:8868101d01d0 5 ////////////////////////////
IonSystems 6:e64796f1f384 6 //Setup pins to FPGA
IonSystems 6:e64796f1f384 7 DigitalOut startSort(p5); //A positive edge tells the FPGA to start sorting.
IonSystems 24:8868101d01d0 8 DigitalIn sortComplete(p16); //FPGA sets to 1 once complete until another signal is recieved.
IonSystems 6:e64796f1f384 9 /*
IonSystems 24:8868101d01d0 10 The command codes for the three sort select bits(ColourBit1,ColourBit2,ColourBit3)
IonSystems 24:8868101d01d0 11 See datasheet for furter information.
IonSystems 6:e64796f1f384 12 000 Sort red chip
IonSystems 6:e64796f1f384 13 001 Sort green chip
IonSystems 6:e64796f1f384 14 010 Sort blue chip
IonSystems 6:e64796f1f384 15 011 Bin the chip
IonSystems 6:e64796f1f384 16 100 Recycle the chip
IonSystems 6:e64796f1f384 17 101 Nothing
IonSystems 6:e64796f1f384 18 110 Nothing
IonSystems 6:e64796f1f384 19 111 Nothing
IonSystems 6:e64796f1f384 20 */
IonSystems 6:e64796f1f384 21
IonSystems 6:e64796f1f384 22 DigitalOut colourBit1(p6); //The 3 bits below are select bits for the sorter.
IonSystems 6:e64796f1f384 23 DigitalOut colourBit2(p7);
IonSystems 6:e64796f1f384 24 DigitalOut colourBit3(p8);
IonSystems 24:8868101d01d0 25 DigitalOut startDispense(p18); //A positive edge tells the FPGA to start dispensing.
IonSystems 6:e64796f1f384 26 /*
IonSystems 6:e64796f1f384 27 00 Dispense red chip
IonSystems 6:e64796f1f384 28 01 Dispense green chip
IonSystems 6:e64796f1f384 29 10 Dispense blue chip
IonSystems 6:e64796f1f384 30 11 Nothing
IonSystems 6:e64796f1f384 31 */
IonSystems 6:e64796f1f384 32
IonSystems 24:8868101d01d0 33 DigitalOut dispenseBit1(p19); //The 2 bits below are select bits for the dispenser.
IonSystems 24:8868101d01d0 34 DigitalOut dispenseBit2(p20);
IonSystems 8:b7771391adc9 35
IonSystems 12:814a8fdbb6f7 36 DigitalIn dispenseComplete(p11); //FPGA sets to 1 once complete until another signal is recieved.
IonSystems 10:8c0696b99692 37 DigitalOut select(p15); //0 for control, 1 for maintenance.
IonSystems 10:8c0696b99692 38
IonSystems 24:8868101d01d0 39 ////////////////////////////
IonSystems 24:8868101d01d0 40 // END OF I/O DEFINITIONS
IonSystems 24:8868101d01d0 41 ////////////////////////////
IonSystems 12:814a8fdbb6f7 42
IonSystems 24:8868101d01d0 43 /* Set the select lines for when the FPGA is in maintenance mode.
IonSystems 24:8868101d01d0 44 * The same pins have different functions in operation mode and maintenance mode on the FPGA.
IonSystems 24:8868101d01d0 45 */
IonSystems 19:78d4b78fa736 46 void setMaintenanceSelect(bool bit6, bool bit5, bool bit4, bool bit3, bool bit2, bool bit1)
IonSystems 19:78d4b78fa736 47 {
IonSystems 12:814a8fdbb6f7 48 startSort = bit1;
IonSystems 12:814a8fdbb6f7 49 colourBit1 = bit2;
IonSystems 12:814a8fdbb6f7 50 colourBit2 = bit3;
IonSystems 12:814a8fdbb6f7 51 colourBit3 = bit4;
IonSystems 12:814a8fdbb6f7 52 startDispense = bit5;
IonSystems 12:814a8fdbb6f7 53 dispenseBit1 = bit6;
IonSystems 19:78d4b78fa736 54 }
IonSystems 19:78d4b78fa736 55
IonSystems 24:8868101d01d0 56 //Set the maintenance start bit.
IonSystems 19:78d4b78fa736 57 void setMaintenanceStart(bool value)
IonSystems 19:78d4b78fa736 58 {
IonSystems 12:814a8fdbb6f7 59 dispenseBit2 = value;
IonSystems 19:78d4b78fa736 60 }
IonSystems 24:8868101d01d0 61
IonSystems 24:8868101d01d0 62 //Wait for the FPGA to complete a maintenance operation and return a complete signal.
IonSystems 19:78d4b78fa736 63 void waitForMaintenanceComplete()
IonSystems 19:78d4b78fa736 64 {
IonSystems 19:78d4b78fa736 65 while(!sortComplete) {
IonSystems 23:f9e7e64784be 66
IonSystems 19:78d4b78fa736 67 }
IonSystems 23:f9e7e64784be 68
IonSystems 19:78d4b78fa736 69 }
IonSystems 19:78d4b78fa736 70
IonSystems 24:8868101d01d0 71 //Set the select lines for a dispense operation for when the FPGA is in operation mode.
IonSystems 19:78d4b78fa736 72 void setDispenseSelect(bool dBit1, bool dBit2)
IonSystems 19:78d4b78fa736 73 {
IonSystems 19:78d4b78fa736 74 dispenseBit1 = dBit1;
IonSystems 19:78d4b78fa736 75 dispenseBit2 = dBit2;
IonSystems 12:814a8fdbb6f7 76 }
IonSystems 19:78d4b78fa736 77
IonSystems 24:8868101d01d0 78 //Set the select lines for a sorting operation for when the FPGA is in operation mode.
IonSystems 19:78d4b78fa736 79 void setSortSelect(bool sBit1, bool sBit2, bool sBit3)
IonSystems 19:78d4b78fa736 80 {
IonSystems 19:78d4b78fa736 81 colourBit1 = sBit1;
IonSystems 19:78d4b78fa736 82 colourBit2 = sBit2;
IonSystems 19:78d4b78fa736 83 colourBit3 = sBit3;
IonSystems 19:78d4b78fa736 84 }
IonSystems 19:78d4b78fa736 85
IonSystems 24:8868101d01d0 86 /* maintain(StateMachine statemachine)
IonSystems 24:8868101d01d0 87 * Carries out a maintenance operation depending on the value of the StateMachine input parameter.
IonSystems 24:8868101d01d0 88 */
IonSystems 19:78d4b78fa736 89 void maintain(StateMachine maintainState)
IonSystems 19:78d4b78fa736 90 {
IonSystems 12:814a8fdbb6f7 91 select = 1; //setting FPGA to maintenance mode.
IonSystems 24:8868101d01d0 92
IonSystems 24:8868101d01d0 93 /* Reset select pins to ensure FPGA carries out one operation.
IonSystems 24:8868101d01d0 94 * The FPGA triggers whenever the select lines change.
IonSystems 24:8868101d01d0 95 * Setting all bits high ensure a 'do nothing' state on the FPGA,
IonSystems 24:8868101d01d0 96 * so it won't do anything.
IonSystems 24:8868101d01d0 97 */
IonSystems 19:78d4b78fa736 98 setMaintenanceSelect(true,true,true,true,true,true);
IonSystems 24:8868101d01d0 99 switch(maintainState) { //Set the maintenanc select values depending on value of maintainState.
IonSystems 12:814a8fdbb6f7 100 case RB_LEFT:
IonSystems 12:814a8fdbb6f7 101 setMaintenanceSelect(false,false,false,true,false,true);
IonSystems 19:78d4b78fa736 102 break;
IonSystems 12:814a8fdbb6f7 103 case RB_CENTRE:
IonSystems 12:814a8fdbb6f7 104 setMaintenanceSelect(false,false,false,true,true,false);
IonSystems 19:78d4b78fa736 105 break;
IonSystems 12:814a8fdbb6f7 106 case RB_RIGHT:
IonSystems 12:814a8fdbb6f7 107 setMaintenanceSelect(false,false,false,true,true,true);
IonSystems 19:78d4b78fa736 108 break;
IonSystems 12:814a8fdbb6f7 109 case GO_UP:
IonSystems 12:814a8fdbb6f7 110 setMaintenanceSelect(false,false,true,false,false,false);
IonSystems 19:78d4b78fa736 111 break;
IonSystems 12:814a8fdbb6f7 112 case GO_CENTRE:
IonSystems 12:814a8fdbb6f7 113 setMaintenanceSelect(false,false,true,false,false,true);
IonSystems 19:78d4b78fa736 114 break;
IonSystems 12:814a8fdbb6f7 115 case GO_DOWN:
IonSystems 12:814a8fdbb6f7 116 setMaintenanceSelect(false,false,true,false,true,false);
IonSystems 19:78d4b78fa736 117 break;
IonSystems 12:814a8fdbb6f7 118 case BR_LEFT:
IonSystems 12:814a8fdbb6f7 119 setMaintenanceSelect(false,false,true,false,true,true);
IonSystems 19:78d4b78fa736 120 break;
IonSystems 12:814a8fdbb6f7 121 case BR_RIGHT:
IonSystems 12:814a8fdbb6f7 122 setMaintenanceSelect(false,false,true,true,false,false);
IonSystems 19:78d4b78fa736 123 break;
IonSystems 12:814a8fdbb6f7 124 case R_PUSH:
IonSystems 12:814a8fdbb6f7 125 setMaintenanceSelect(false,false,true,true,false,true);
IonSystems 19:78d4b78fa736 126 break;
IonSystems 22:8f11d1c178ab 127 case R_HOME:
IonSystems 22:8f11d1c178ab 128 setMaintenanceSelect(false,false,true,true,true,false);
IonSystems 22:8f11d1c178ab 129 break;
IonSystems 22:8f11d1c178ab 130 case GB_LEFT:
IonSystems 22:8f11d1c178ab 131 setMaintenanceSelect(false,false,true,true,true,true);
IonSystems 22:8f11d1c178ab 132 break;
IonSystems 22:8f11d1c178ab 133 case GB_CENTRE:
IonSystems 22:8f11d1c178ab 134 setMaintenanceSelect(false,true,false,false,false,false);
IonSystems 22:8f11d1c178ab 135 break;
IonSystems 22:8f11d1c178ab 136 case GB_RIGHT:
IonSystems 22:8f11d1c178ab 137 setMaintenanceSelect(false,true,false,false,false,true);
IonSystems 22:8f11d1c178ab 138 break;
IonSystems 22:8f11d1c178ab 139 case maintenanceEND:
IonSystems 22:8f11d1c178ab 140 setMaintenanceSelect(false,true,false,false,true,false);
IonSystems 23:f9e7e64784be 141 break;
IonSystems 14:31ba3e56c788 142 default:
IonSystems 19:78d4b78fa736 143 break;
IonSystems 19:78d4b78fa736 144 }
IonSystems 24:8868101d01d0 145 setMaintenanceStart(true); //Tell the FPGA to start the maintenance operation
IonSystems 24:8868101d01d0 146 waitForMaintenanceComplete(); //Wait for the FPGA to complete the maintenance operation.
IonSystems 24:8868101d01d0 147 setMaintenanceStart(false); //Set the start bit low.
IonSystems 24:8868101d01d0 148 setMaintenanceSelect(true,false,true,true,true,false); //Set select bits back to 'do nothing' state.
IonSystems 19:78d4b78fa736 149 }
IonSystems 19:78d4b78fa736 150
IonSystems 24:8868101d01d0 151 //Wait for the FPGA to complete a dispense operation and send a complete signal.
IonSystems 19:78d4b78fa736 152 void waitForDispenseComplete()
IonSystems 19:78d4b78fa736 153 {
IonSystems 23:f9e7e64784be 154 while(!dispenseComplete) {
IonSystems 12:814a8fdbb6f7 155 }
IonSystems 23:f9e7e64784be 156
IonSystems 19:78d4b78fa736 157 }
IonSystems 19:78d4b78fa736 158
IonSystems 24:8868101d01d0 159 /* dispense(Colour colour)
IonSystems 24:8868101d01d0 160 * Carries out a dispense operation for the colour defined by 'colour' which is a Colour.
IonSystems 24:8868101d01d0 161 */
IonSystems 19:78d4b78fa736 162 void dispense(Colour colour)
IonSystems 19:78d4b78fa736 163 {
IonSystems 24:8868101d01d0 164 startDispense = false; //Set start dispense to false, it should be false already.
IonSystems 24:8868101d01d0 165 bool validDispense = false; //Set up a boolean to record whether the dispense is valid or not.
IonSystems 24:8868101d01d0 166 select = 0; //Set the FPGA to operation mode.
IonSystems 24:8868101d01d0 167 setDispenseSelect(true,true); //Set the dispense selcect bits to 'no nothing' state.
IonSystems 23:f9e7e64784be 168 // A dispense operation can only take place if there are chips
IonSystems 23:f9e7e64784be 169
IonSystems 24:8868101d01d0 170 switch(colour) { //Carry out a dispense operation for the colour defined by 'colour'.
IonSystems 19:78d4b78fa736 171 case RED:
IonSystems 24:8868101d01d0 172
IonSystems 24:8868101d01d0 173 if(redAmount > 0 || operationMode == false) { //Ensure dispense is valid
IonSystems 24:8868101d01d0 174 setDispenseSelect(false,false); //Set select lines for RED dispense
IonSystems 24:8868101d01d0 175 if(operationMode)redAmount--; //Decrement tube amount if in operation mode
IonSystems 24:8868101d01d0 176 validDispense = true;
IonSystems 19:78d4b78fa736 177 }
IonSystems 10:8c0696b99692 178 break;
IonSystems 19:78d4b78fa736 179 case GREEN:
IonSystems 24:8868101d01d0 180 if(greenAmount > 0 || operationMode == false) { //Ensure dispense is valid
IonSystems 24:8868101d01d0 181 setDispenseSelect(true,false); //Set select lines for GREEN dispense
IonSystems 24:8868101d01d0 182 if(operationMode)greenAmount--; //Decrement tube amount if in operation mode
IonSystems 19:78d4b78fa736 183 validDispense = true;
IonSystems 19:78d4b78fa736 184 }
IonSystems 10:8c0696b99692 185 break;
IonSystems 19:78d4b78fa736 186 case BLUE:
IonSystems 24:8868101d01d0 187 if(blueAmount > 0 || operationMode == false) { //Ensure dispense is valid
IonSystems 24:8868101d01d0 188 setDispenseSelect(false,true); //Set select lines for BLUE dispense
IonSystems 24:8868101d01d0 189 if(operationMode)blueAmount--; //Decrement tube amount if in operation mode
IonSystems 12:814a8fdbb6f7 190 validDispense = true;
IonSystems 19:78d4b78fa736 191 }
IonSystems 10:8c0696b99692 192 break;
IonSystems 19:78d4b78fa736 193 }
IonSystems 23:f9e7e64784be 194
IonSystems 24:8868101d01d0 195 if(operationMode)writeFile(redAmount,greenAmount,blueAmount,recycleAmount); //Store new tube values if in operation mode.
IonSystems 24:8868101d01d0 196 /* If this is a valid dispense (enough chips in storage tubes) then
IonSystems 24:8868101d01d0 197 * set the start bit, wait for complete signal, then reset start bit,
IonSystems 24:8868101d01d0 198 * and select lines.
IonSystems 24:8868101d01d0 199 */
IonSystems 24:8868101d01d0 200 if(validDispense || operationMode == false) {
IonSystems 10:8c0696b99692 201 startDispense = true; //set the startDispense line high.
IonSystems 24:8868101d01d0 202 waitForDispenseComplete();
IonSystems 10:8c0696b99692 203 startDispense = false;
IonSystems 19:78d4b78fa736 204 setDispenseSelect(true,true);
IonSystems 10:8c0696b99692 205 }
IonSystems 19:78d4b78fa736 206 }
IonSystems 24:8868101d01d0 207
IonSystems 24:8868101d01d0 208 /*
IonSystems 24:8868101d01d0 209 *
IonSystems 24:8868101d01d0 210 */
IonSystems 19:78d4b78fa736 211 void dispenseOrder(int r, int g, int b)
IonSystems 19:78d4b78fa736 212 {
IonSystems 23:f9e7e64784be 213 //TODO: Check if there are enough chips of each colour to dispense the order.
IonSystems 24:8868101d01d0 214 //operationMode = false;
IonSystems 24:8868101d01d0 215 for(int i = r; i > 0; i--) {
IonSystems 14:31ba3e56c788 216 dispense(RED);
IonSystems 24:8868101d01d0 217 wait(0.2);
IonSystems 24:8868101d01d0 218 Thread::wait(200);
IonSystems 19:78d4b78fa736 219 }
IonSystems 23:f9e7e64784be 220 for(int i = g; i > 0; i--) {
IonSystems 15:0c5f20e15b6a 221 dispense(GREEN);
IonSystems 19:78d4b78fa736 222 }
IonSystems 23:f9e7e64784be 223 for(int i = b; i > 0; i--) {
IonSystems 15:0c5f20e15b6a 224 dispense(BLUE);
IonSystems 17:6a0bb0ad5bb4 225 }
IonSystems 24:8868101d01d0 226 //operationMode = true;
IonSystems 19:78d4b78fa736 227 }
IonSystems 19:78d4b78fa736 228
IonSystems 20:6de191ac7ff3 229 void waitForSortComplete()
IonSystems 20:6de191ac7ff3 230 {
IonSystems 23:f9e7e64784be 231 while(!sortComplete) {}
IonSystems 20:6de191ac7ff3 232 }
IonSystems 20:6de191ac7ff3 233
IonSystems 20:6de191ac7ff3 234 void lift()
IonSystems 20:6de191ac7ff3 235 {
IonSystems 20:6de191ac7ff3 236 select = 0; //Setting to operation mode just in case it has not been set.
IonSystems 20:6de191ac7ff3 237 setSortSelect(true,true,true);
IonSystems 20:6de191ac7ff3 238 setSortSelect(true,false,true);
IonSystems 20:6de191ac7ff3 239 startSort = true; //set the startDispense line high.
IonSystems 23:f9e7e64784be 240 waitForSortComplete();
IonSystems 23:f9e7e64784be 241 startSort = false;
IonSystems 23:f9e7e64784be 242 setSortSelect(true,true,true);
IonSystems 23:f9e7e64784be 243 }
IonSystems 20:6de191ac7ff3 244
IonSystems 20:6de191ac7ff3 245
IonSystems 20:6de191ac7ff3 246
IonSystems 19:78d4b78fa736 247 void recycle()
IonSystems 19:78d4b78fa736 248 {
IonSystems 24:8868101d01d0 249 if(redAmount >= tubeSize && greenAmount >= tubeSize && blueAmount >= tubeSize && operationMode){
IonSystems 24:8868101d01d0 250 return;
IonSystems 24:8868101d01d0 251 }
IonSystems 19:78d4b78fa736 252 select = 0; //Setting to operation mode just in case it has not been set.
IonSystems 19:78d4b78fa736 253 setSortSelect(true,true,true);
IonSystems 19:78d4b78fa736 254 setSortSelect(false,false,true);
IonSystems 24:8868101d01d0 255 if(operationMode)recycleAmount++;
IonSystems 19:78d4b78fa736 256 startSort = true; //set the startDispense line high.
IonSystems 20:6de191ac7ff3 257 waitForSortComplete();
IonSystems 19:78d4b78fa736 258 startSort = false;
IonSystems 19:78d4b78fa736 259 setSortSelect(true,true,true);
IonSystems 23:f9e7e64784be 260 if(recycleAmount >= 5) {
IonSystems 24:8868101d01d0 261 Thread::wait(1000);
IonSystems 23:f9e7e64784be 262 lift();
IonSystems 24:8868101d01d0 263 Thread::wait(1000);
IonSystems 23:f9e7e64784be 264 recycleAmount = 0;
IonSystems 23:f9e7e64784be 265 }
IonSystems 19:78d4b78fa736 266 }
IonSystems 19:78d4b78fa736 267
IonSystems 19:78d4b78fa736 268
IonSystems 19:78d4b78fa736 269
IonSystems 19:78d4b78fa736 270 void sort(Colour colour)
IonSystems 19:78d4b78fa736 271 {
IonSystems 19:78d4b78fa736 272 if(colour == NONE) {
IonSystems 19:78d4b78fa736 273 return;
IonSystems 19:78d4b78fa736 274 } else {
IonSystems 23:f9e7e64784be 275 startSort = false;
IonSystems 10:8c0696b99692 276 select = 0; //Setting to operation mode just in case it has not been set.
IonSystems 19:78d4b78fa736 277 setSortSelect(true,true,true);
IonSystems 19:78d4b78fa736 278 switch(colour) {
IonSystems 24:8868101d01d0 279 case RED:
IonSystems 24:8868101d01d0 280 if(redAmount >= tubeSize && operationMode) {
IonSystems 17:6a0bb0ad5bb4 281 recycle();
IonSystems 17:6a0bb0ad5bb4 282 return;
IonSystems 19:78d4b78fa736 283 }
IonSystems 19:78d4b78fa736 284 setSortSelect(false,false,false);
IonSystems 24:8868101d01d0 285 if(operationMode) redAmount++;
IonSystems 19:78d4b78fa736 286 break;
IonSystems 10:8c0696b99692 287 case GREEN:
IonSystems 24:8868101d01d0 288 if(greenAmount >= tubeSize && operationMode) {
IonSystems 17:6a0bb0ad5bb4 289 recycle();
IonSystems 17:6a0bb0ad5bb4 290 return;
IonSystems 19:78d4b78fa736 291 }
IonSystems 19:78d4b78fa736 292 setSortSelect(true,false,false);
IonSystems 24:8868101d01d0 293 if(operationMode) greenAmount++;
IonSystems 19:78d4b78fa736 294 break;
IonSystems 10:8c0696b99692 295 case BLUE:
IonSystems 24:8868101d01d0 296 if(blueAmount >= tubeSize && operationMode) {
IonSystems 17:6a0bb0ad5bb4 297 recycle();
IonSystems 17:6a0bb0ad5bb4 298 return;
IonSystems 19:78d4b78fa736 299 }
IonSystems 19:78d4b78fa736 300 setSortSelect(false,true,false);
IonSystems 24:8868101d01d0 301 if(operationMode) blueAmount++;
IonSystems 19:78d4b78fa736 302 break;
IonSystems 11:06f6e82b40a8 303 case BIN:
IonSystems 19:78d4b78fa736 304 setSortSelect(true,true,false);
IonSystems 19:78d4b78fa736 305 break;
IonSystems 10:8c0696b99692 306 }
IonSystems 23:f9e7e64784be 307 startSort = true;
IonSystems 19:78d4b78fa736 308 waitForSortComplete();
IonSystems 19:78d4b78fa736 309 startSort = false;
IonSystems 19:78d4b78fa736 310 setSortSelect(true,true,true);
IonSystems 24:8868101d01d0 311 if(operationMode) writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
IonSystems 24:8868101d01d0 312
IonSystems 19:78d4b78fa736 313 }
IonSystems 12:814a8fdbb6f7 314 }
IonSystems 12:814a8fdbb6f7 315
IonSystems 19:78d4b78fa736 316
IonSystems 19:78d4b78fa736 317
IonSystems 19:78d4b78fa736 318 void dispenseAll()
IonSystems 19:78d4b78fa736 319 {
IonSystems 23:f9e7e64784be 320 dispenseOrder(redAmount,greenAmount,blueAmount);
IonSystems 24:8868101d01d0 321 redAmount = 0; greenAmount = 0; blueAmount = 0;
IonSystems 23:f9e7e64784be 322 writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
IonSystems 19:78d4b78fa736 323 }