Grzegorz Kaczmarek
/
Max7221
Fix to have load pin working with SPI1.
Fork of Max7221 by
Max7221.cpp@3:5abc4047af8d, 2013-08-07 (annotated)
- Committer:
- jakowisp
- Date:
- Wed Aug 07 02:34:59 2013 +0000
- Revision:
- 3:5abc4047af8d
- Parent:
- MAX7221/Max7221.cpp@2:828c62cc1861
- Child:
- 5:1f3dbf38d027
Fix Library file locations
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jakowisp | 2:828c62cc1861 | 1 | /** |
jakowisp | 2:828c62cc1861 | 2 | * @file Max7221.cpp |
jakowisp | 2:828c62cc1861 | 3 | * @brief This file defines the Max7221 class methods and the default values for static variables |
jakowisp | 2:828c62cc1861 | 4 | * |
jakowisp | 2:828c62cc1861 | 5 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 6 | * |
jakowisp | 2:828c62cc1861 | 7 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 8 | */ |
jakowisp | 1:d8589d1f368c | 9 | #include "mbed.h" |
jakowisp | 1:d8589d1f368c | 10 | #include "Max7221.h" |
jakowisp | 1:d8589d1f368c | 11 | |
jakowisp | 2:828c62cc1861 | 12 | ///Intialize the Class static members |
jakowisp | 2:828c62cc1861 | 13 | ///Devices used per SPI bus are set to ZERO |
jakowisp | 1:d8589d1f368c | 14 | int Max7221::maxInUseSPI1 = 0; |
jakowisp | 1:d8589d1f368c | 15 | int Max7221::maxInUseSPI2 = 0; |
jakowisp | 2:828c62cc1861 | 16 | ///Set the static pointers to the SPI busses to NULL |
jakowisp | 1:d8589d1f368c | 17 | SPI *Max7221::spi1=NULL; |
jakowisp | 1:d8589d1f368c | 18 | SPI *Max7221::spi2=NULL; |
jakowisp | 2:828c62cc1861 | 19 | ///Set the static pointers to the load signals to NULL |
jakowisp | 1:d8589d1f368c | 20 | DigitalOut *Max7221::load1=NULL; |
jakowisp | 1:d8589d1f368c | 21 | DigitalOut *Max7221::load2=NULL; |
jakowisp | 1:d8589d1f368c | 22 | |
jakowisp | 2:828c62cc1861 | 23 | /** |
jakowisp | 2:828c62cc1861 | 24 | * Constructor. This is the default constructor |
jakowisp | 2:828c62cc1861 | 25 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 26 | * @param msoi The SPI pin used as input to the device. Valid values for LPC1768 are p5 or p11 |
jakowisp | 2:828c62cc1861 | 27 | * @param mclk The SPI pin used as clock for the device. Valid values for LPC1768 are p7 or p13 |
jakowisp | 2:828c62cc1861 | 28 | * @param load The pin used to control load for the device. Any pin capable for DigitalOut can be used, but the same load pin must be used for |
jakowisp | 2:828c62cc1861 | 29 | * device that share the same msoi and mclk pins |
jakowisp | 2:828c62cc1861 | 30 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 31 | */ |
jakowisp | 1:d8589d1f368c | 32 | Max7221::Max7221(PinName msoi, PinName mclk, PinName load){ |
jakowisp | 2:828c62cc1861 | 33 | ///Determine which bus we are connecting the device to based on the MSOI pin name |
jakowisp | 1:d8589d1f368c | 34 | switch (msoi) { |
jakowisp | 2:828c62cc1861 | 35 | ///If using SPI bus #1 |
jakowisp | 1:d8589d1f368c | 36 | case p5: maxInUseSPI1++; |
jakowisp | 2:828c62cc1861 | 37 | ///Set this insctance to pointers to the correct static pointers |
jakowisp | 1:d8589d1f368c | 38 | this->id=maxInUseSPI1; |
jakowisp | 1:d8589d1f368c | 39 | this->maxInUse=&maxInUseSPI1; |
jakowisp | 2:828c62cc1861 | 40 | ///If no devices have been assigned to the SPI bus it must be initialized |
jakowisp | 1:d8589d1f368c | 41 | if (spi1 ==NULL) { |
jakowisp | 1:d8589d1f368c | 42 | spi1 = new SPI(msoi, NC, mclk); |
jakowisp | 1:d8589d1f368c | 43 | load1 = new DigitalOut(load); |
jakowisp | 1:d8589d1f368c | 44 | } else { |
jakowisp | 2:828c62cc1861 | 45 | ///TODO: Check that load pin is the same for all SP2 |
jakowisp | 1:d8589d1f368c | 46 | } |
jakowisp | 1:d8589d1f368c | 47 | this->max72_spi=spi1; |
jakowisp | 1:d8589d1f368c | 48 | this->load = load2; |
jakowisp | 1:d8589d1f368c | 49 | break; |
jakowisp | 2:828c62cc1861 | 50 | ///If using SPI bus #2 |
jakowisp | 1:d8589d1f368c | 51 | case p11: maxInUseSPI2++; |
jakowisp | 2:828c62cc1861 | 52 | ///Set this insctance to pointers to the correct static pointers |
jakowisp | 1:d8589d1f368c | 53 | this->id=maxInUseSPI2; |
jakowisp | 1:d8589d1f368c | 54 | this->maxInUse=&maxInUseSPI2; |
jakowisp | 2:828c62cc1861 | 55 | ///If no devices have been assigned to the SPI bus it must be initialized |
jakowisp | 1:d8589d1f368c | 56 | if (spi2 ==NULL) { |
jakowisp | 1:d8589d1f368c | 57 | spi2 = new SPI(msoi, NC, mclk); |
jakowisp | 1:d8589d1f368c | 58 | load2 = new DigitalOut(load); |
jakowisp | 1:d8589d1f368c | 59 | } else { |
jakowisp | 2:828c62cc1861 | 60 | ///TODO: Check that load pin is the same for all SP2 |
jakowisp | 1:d8589d1f368c | 61 | } |
jakowisp | 1:d8589d1f368c | 62 | this->max72_spi=spi2; |
jakowisp | 1:d8589d1f368c | 63 | this->load = load2; |
jakowisp | 1:d8589d1f368c | 64 | break; |
jakowisp | 2:828c62cc1861 | 65 | ///If a pin not belonging to a SPI bus is used, Throw error |
jakowisp | 1:d8589d1f368c | 66 | default: error("Not a SPI port"); |
jakowisp | 1:d8589d1f368c | 67 | } |
jakowisp | 1:d8589d1f368c | 68 | |
jakowisp | 1:d8589d1f368c | 69 | } |
jakowisp | 1:d8589d1f368c | 70 | |
jakowisp | 2:828c62cc1861 | 71 | /** |
jakowisp | 2:828c62cc1861 | 72 | * This method is used to write a byte of data to a specified register for only the device defined in this class instance |
jakowisp | 2:828c62cc1861 | 73 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 74 | * @param reg The register to write to. |
jakowisp | 2:828c62cc1861 | 75 | * @param data The value to be written. |
jakowisp | 2:828c62cc1861 | 76 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 77 | *//** |
jakowisp | 2:828c62cc1861 | 78 | * This method is used to write a byte of data to a specified register for only the device defined in this class instance |
jakowisp | 2:828c62cc1861 | 79 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 80 | * @param reg The register to write to. |
jakowisp | 2:828c62cc1861 | 81 | * @param data The value to be written. |
jakowisp | 2:828c62cc1861 | 82 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 83 | */ |
jakowisp | 2:828c62cc1861 | 84 | void Max7221::Write( unsigned int reg, unsigned int data) { |
jakowisp | 1:d8589d1f368c | 85 | int c = 0; |
jakowisp | 1:d8589d1f368c | 86 | *load = LOW; |
jakowisp | 1:d8589d1f368c | 87 | |
jakowisp | 2:828c62cc1861 | 88 | ///if there are multiple devices sharing the SPI buss and they preceed the current device in the cascade Write a NOOP to them |
jakowisp | 1:d8589d1f368c | 89 | for ( c = *maxInUse; c > this->id; c--) { |
jakowisp | 1:d8589d1f368c | 90 | max72_spi->write(0); // no-op |
jakowisp | 1:d8589d1f368c | 91 | max72_spi->write(0); // no-op |
jakowisp | 1:d8589d1f368c | 92 | } |
jakowisp | 2:828c62cc1861 | 93 | ///Write to this device registers |
jakowisp | 1:d8589d1f368c | 94 | max72_spi->write(reg); // specify register |
jakowisp | 2:828c62cc1861 | 95 | max72_spi->write(data); // put data |
jakowisp | 1:d8589d1f368c | 96 | |
jakowisp | 2:828c62cc1861 | 97 | ///if there are multiple devices sharing the SPI buss and they follow the current device in the cascade Write a NOOP to them |
jakowisp | 1:d8589d1f368c | 98 | for ( c=this->id-1; c >= 1; c--) { |
jakowisp | 1:d8589d1f368c | 99 | max72_spi->write(0); // no-op |
jakowisp | 1:d8589d1f368c | 100 | max72_spi->write(0); // no-op |
jakowisp | 1:d8589d1f368c | 101 | } |
jakowisp | 1:d8589d1f368c | 102 | *load = HIGH; |
jakowisp | 1:d8589d1f368c | 103 | } |
jakowisp | 1:d8589d1f368c | 104 | |
jakowisp | 2:828c62cc1861 | 105 | /** |
jakowisp | 2:828c62cc1861 | 106 | * This method is used to write an intial set off values to the device to prepare it for use. |
jakowisp | 2:828c62cc1861 | 107 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 108 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 109 | */ |
jakowisp | 1:d8589d1f368c | 110 | void Max7221::Setup () { |
jakowisp | 2:828c62cc1861 | 111 | // initiation of the max 7221 |
jakowisp | 1:d8589d1f368c | 112 | // SPI setup: 8 bits, mode 0 |
jakowisp | 1:d8589d1f368c | 113 | max72_spi->format(8, 0); |
jakowisp | 1:d8589d1f368c | 114 | |
jakowisp | 1:d8589d1f368c | 115 | // going by the datasheet, min clk is 100ns so theoretically 10MHz should work... |
jakowisp | 1:d8589d1f368c | 116 | max72_spi->frequency(10*MHZ); |
jakowisp | 1:d8589d1f368c | 117 | |
jakowisp | 2:828c62cc1861 | 118 | Write(max7219_reg_scanLimit, 0x07); ///ENABLE all 8 digits |
jakowisp | 2:828c62cc1861 | 119 | Write(max7219_reg_decodeMode, 0xff); // Turn on Code B font decode for all digits |
jakowisp | 2:828c62cc1861 | 120 | Write(max7219_reg_shutdown, 0x01); // Disable shutdown mode |
jakowisp | 2:828c62cc1861 | 121 | Write(max7219_reg_displayTest, 0x00); // Disable display test |
jakowisp | 2:828c62cc1861 | 122 | for (int e=1; e<=8; e++) { // Write blank to all digits |
jakowisp | 1:d8589d1f368c | 123 | Write(e,0xf); |
jakowisp | 1:d8589d1f368c | 124 | } |
jakowisp | 2:828c62cc1861 | 125 | Write(max7219_reg_intensity, 0x01 ); // Set the display intensity to a low level. |
jakowisp | 1:d8589d1f368c | 126 | // range: 0x00 to 0x0f |
jakowisp | 1:d8589d1f368c | 127 | } |
jakowisp | 1:d8589d1f368c | 128 | |
jakowisp | 2:828c62cc1861 | 129 | /** |
jakowisp | 2:828c62cc1861 | 130 | * This method is used to write a byte of data to a specified register for all the devices instantiated. |
jakowisp | 2:828c62cc1861 | 131 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 132 | * @param reg The register to write to. |
jakowisp | 2:828c62cc1861 | 133 | * @param data The value to be written. |
jakowisp | 2:828c62cc1861 | 134 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 135 | */ |
jakowisp | 2:828c62cc1861 | 136 | void Max7221::WriteAll (unsigned int reg, unsigned int data) { |
jakowisp | 2:828c62cc1861 | 137 | ///Write to all the devices on SPI Bus #1 first |
jakowisp | 1:d8589d1f368c | 138 | if(load1 !=NULL) { |
jakowisp | 1:d8589d1f368c | 139 | *load1 = LOW; // begin |
jakowisp | 1:d8589d1f368c | 140 | for ( int c=1; c<= maxInUseSPI1; c++) { |
jakowisp | 1:d8589d1f368c | 141 | spi1->write(reg); // specify register |
jakowisp | 2:828c62cc1861 | 142 | spi1->write(data); // put data |
jakowisp | 1:d8589d1f368c | 143 | } |
jakowisp | 1:d8589d1f368c | 144 | *load1 = HIGH; |
jakowisp | 1:d8589d1f368c | 145 | } |
jakowisp | 2:828c62cc1861 | 146 | ///Write to all the devices on SPI Bus #2 |
jakowisp | 1:d8589d1f368c | 147 | if(load2 !=NULL) { |
jakowisp | 1:d8589d1f368c | 148 | *load2 = LOW; |
jakowisp | 1:d8589d1f368c | 149 | for ( int c=1; c<= maxInUseSPI2; c++) { |
jakowisp | 1:d8589d1f368c | 150 | spi2->write(reg); // specify register |
jakowisp | 2:828c62cc1861 | 151 | spi2->write(data); // put data |
jakowisp | 1:d8589d1f368c | 152 | } |
jakowisp | 1:d8589d1f368c | 153 | *load2 = HIGH; |
jakowisp | 1:d8589d1f368c | 154 | } |
jakowisp | 1:d8589d1f368c | 155 | } |
jakowisp | 2:828c62cc1861 | 156 | /** |
jakowisp | 2:828c62cc1861 | 157 | * This method is used to display an integer to the specified device instance. Underflow and overflow result in '-' written to all digits |
jakowisp | 2:828c62cc1861 | 158 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 159 | * @param value An integer value to display |
jakowisp | 2:828c62cc1861 | 160 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 161 | */ |
jakowisp | 1:d8589d1f368c | 162 | void Max7221::WriteInt( int value ){ |
jakowisp | 1:d8589d1f368c | 163 | char buffer[16]; |
jakowisp | 1:d8589d1f368c | 164 | |
jakowisp | 2:828c62cc1861 | 165 | ///TODO:SET UPPERBOUND AND LOWERBOUND based on NUMDIGITS |
jakowisp | 2:828c62cc1861 | 166 | ///Check the the INT value can be displayed and convert to a string. |
jakowisp | 1:d8589d1f368c | 167 | if (value <= UPPERBOUND && value >= LOWERBOUND) { |
jakowisp | 1:d8589d1f368c | 168 | sprintf(buffer,"%8d",value); |
jakowisp | 1:d8589d1f368c | 169 | } else { |
jakowisp | 1:d8589d1f368c | 170 | sprintf(buffer,"--------"); |
jakowisp | 1:d8589d1f368c | 171 | } |
jakowisp | 2:828c62cc1861 | 172 | ///In case a program changed the decode mode, set it again. |
jakowisp | 1:d8589d1f368c | 173 | Write(max7219_reg_decodeMode, 0xff); |
jakowisp | 1:d8589d1f368c | 174 | for (int i=0;i<NUMDIGITS;i++) { |
jakowisp | 2:828c62cc1861 | 175 | ///For each character of the string, convert the ASCII to the datacode needed by the device |
jakowisp | 1:d8589d1f368c | 176 | switch(buffer[i]){ |
jakowisp | 1:d8589d1f368c | 177 | case 0x2d: buffer[i]=0xa; break; |
jakowisp | 1:d8589d1f368c | 178 | case 0x20: buffer[i]=0xf; break; |
jakowisp | 1:d8589d1f368c | 179 | default: buffer[i]= buffer[i] & 0x0f; |
jakowisp | 1:d8589d1f368c | 180 | } |
jakowisp | 2:828c62cc1861 | 181 | ///Call function to write the data for each character of the srting. |
jakowisp | 1:d8589d1f368c | 182 | Write(NUMDIGITS-i,buffer[i]); |
jakowisp | 1:d8589d1f368c | 183 | } |
jakowisp | 1:d8589d1f368c | 184 | } |
jakowisp | 1:d8589d1f368c | 185 | |
jakowisp | 2:828c62cc1861 | 186 | /** |
jakowisp | 2:828c62cc1861 | 187 | * This method is used to display a floating point number to the specified device instance. |
jakowisp | 2:828c62cc1861 | 188 | * Underflow and overflow result in '-' written to all digits. The digits after the decimal |
jakowisp | 2:828c62cc1861 | 189 | * point are truncated to fit the display. |
jakowisp | 2:828c62cc1861 | 190 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 191 | * @param value A float value to display |
jakowisp | 2:828c62cc1861 | 192 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 193 | */ |
jakowisp | 1:d8589d1f368c | 194 | void Max7221::WriteFloat( float value ){ |
jakowisp | 1:d8589d1f368c | 195 | char buffer[32]; |
jakowisp | 1:d8589d1f368c | 196 | int ptr=-1,len; |
jakowisp | 1:d8589d1f368c | 197 | int i; |
jakowisp | 1:d8589d1f368c | 198 | |
jakowisp | 1:d8589d1f368c | 199 | sprintf(buffer,"%f",value); |
jakowisp | 1:d8589d1f368c | 200 | len=strlen(buffer); |
jakowisp | 1:d8589d1f368c | 201 | i=len-1; |
jakowisp | 1:d8589d1f368c | 202 | while(buffer[i]==0x30) { |
jakowisp | 1:d8589d1f368c | 203 | buffer[i]='\0'; |
jakowisp | 1:d8589d1f368c | 204 | i--; |
jakowisp | 1:d8589d1f368c | 205 | len--; |
jakowisp | 1:d8589d1f368c | 206 | } |
jakowisp | 1:d8589d1f368c | 207 | for( i =0; i<=len; i++) { |
jakowisp | 1:d8589d1f368c | 208 | switch(buffer[i]){ |
jakowisp | 1:d8589d1f368c | 209 | case 0x2d: buffer[i]=0xa; break; |
jakowisp | 1:d8589d1f368c | 210 | case 0x20: buffer[i]=0xf; break; |
jakowisp | 1:d8589d1f368c | 211 | case 0x2e: buffer[i]=buffer[i-1] | 0x80; |
jakowisp | 1:d8589d1f368c | 212 | ptr = i-1; |
jakowisp | 1:d8589d1f368c | 213 | break; |
jakowisp | 1:d8589d1f368c | 214 | default: buffer[i]= buffer[i]; |
jakowisp | 1:d8589d1f368c | 215 | } |
jakowisp | 1:d8589d1f368c | 216 | if (ptr != -1) { |
jakowisp | 1:d8589d1f368c | 217 | buffer[i-1]=buffer[i]; |
jakowisp | 1:d8589d1f368c | 218 | } |
jakowisp | 1:d8589d1f368c | 219 | } |
jakowisp | 1:d8589d1f368c | 220 | |
jakowisp | 1:d8589d1f368c | 221 | len=strlen(buffer); |
jakowisp | 1:d8589d1f368c | 222 | Write(max7219_reg_decodeMode, 0xff); |
jakowisp | 1:d8589d1f368c | 223 | |
jakowisp | 1:d8589d1f368c | 224 | // If too large for display set to '-' |
jakowisp | 1:d8589d1f368c | 225 | if(len > NUMDIGITS && (ptr==-1 || ptr>NUMDIGITS)) |
jakowisp | 1:d8589d1f368c | 226 | for (int i=0;i<NUMDIGITS;i++) { |
jakowisp | 1:d8589d1f368c | 227 | buffer[i]=0x0a; |
jakowisp | 1:d8589d1f368c | 228 | } |
jakowisp | 1:d8589d1f368c | 229 | //if number is smaller than display, fill with ' ' |
jakowisp | 1:d8589d1f368c | 230 | if (len<=NUMDIGITS) { |
jakowisp | 1:d8589d1f368c | 231 | for (int i=1;i<=NUMDIGITS;i++) { |
jakowisp | 1:d8589d1f368c | 232 | if(len-i>=0) { |
jakowisp | 1:d8589d1f368c | 233 | Write(i,buffer[len-i]); |
jakowisp | 1:d8589d1f368c | 234 | } else { |
jakowisp | 1:d8589d1f368c | 235 | Write(i,0xf); |
jakowisp | 1:d8589d1f368c | 236 | } |
jakowisp | 1:d8589d1f368c | 237 | } |
jakowisp | 1:d8589d1f368c | 238 | } else { |
jakowisp | 1:d8589d1f368c | 239 | //Write out the buffer, truncating the decimal digits if larger than display |
jakowisp | 1:d8589d1f368c | 240 | for (int i=0;i<NUMDIGITS;i++) { |
jakowisp | 1:d8589d1f368c | 241 | Write(NUMDIGITS-i,buffer[i]); |
jakowisp | 1:d8589d1f368c | 242 | } |
jakowisp | 1:d8589d1f368c | 243 | } |
jakowisp | 1:d8589d1f368c | 244 | } |
jakowisp | 1:d8589d1f368c | 245 | |
jakowisp | 2:828c62cc1861 | 246 | /** |
jakowisp | 2:828c62cc1861 | 247 | * This method is used to write an intial set off values to ALL device to prepare them for use. |
jakowisp | 2:828c62cc1861 | 248 | * @author Dwayne S. Dilbeck |
jakowisp | 2:828c62cc1861 | 249 | * @date 8/6/2013 |
jakowisp | 2:828c62cc1861 | 250 | */ |
jakowisp | 1:d8589d1f368c | 251 | void Max7221::SetupAll () { |
jakowisp | 1:d8589d1f368c | 252 | // initiation of the max 7219 |
jakowisp | 1:d8589d1f368c | 253 | // SPI setup: 8 bits, mode 0 |
jakowisp | 1:d8589d1f368c | 254 | if(spi1!=NULL) { |
jakowisp | 1:d8589d1f368c | 255 | spi1->format(8, 0); |
jakowisp | 1:d8589d1f368c | 256 | spi1->frequency(10*MHZ); |
jakowisp | 1:d8589d1f368c | 257 | } |
jakowisp | 1:d8589d1f368c | 258 | if(spi2!=NULL) { |
jakowisp | 1:d8589d1f368c | 259 | spi2->format(8, 0); |
jakowisp | 1:d8589d1f368c | 260 | spi2->frequency(10*MHZ); |
jakowisp | 1:d8589d1f368c | 261 | } |
jakowisp | 1:d8589d1f368c | 262 | WriteAll(max7219_reg_scanLimit, 0x07); |
jakowisp | 1:d8589d1f368c | 263 | WriteAll(max7219_reg_decodeMode, 0xff); // using an led matrix (not digits) |
jakowisp | 1:d8589d1f368c | 264 | WriteAll(max7219_reg_shutdown, 0x01); // not in shutdown mode |
jakowisp | 1:d8589d1f368c | 265 | WriteAll(max7219_reg_displayTest, 0x00); // no display test |
jakowisp | 1:d8589d1f368c | 266 | for (int e=1; e<=8; e++) { // empty registers, turn all LEDs off |
jakowisp | 1:d8589d1f368c | 267 | WriteAll(e,0xf); |
jakowisp | 1:d8589d1f368c | 268 | } |
jakowisp | 1:d8589d1f368c | 269 | WriteAll(max7219_reg_intensity, 0x01 & 0x0f); // the first 0x0f is the value you can set |
jakowisp | 1:d8589d1f368c | 270 | // range: 0x00 to 0x0f |
jakowisp | 1:d8589d1f368c | 271 | } |
jakowisp | 2:828c62cc1861 | 272 |