Library files for using Seeed Studio TFT Touch Shield for Arduino (ST7781R controller) together with ELMICRO TestBed for mbed. Featuring a short example program of how to calibrate the touch screen. Some basic drawing functions are also included (circle, rectangle, lines, text).
2d_draw.c@0:db0d63650413, 2012-06-28 (annotated)
- Committer:
- elmicro
- Date:
- Thu Jun 28 10:12:07 2012 +0000
- Revision:
- 0:db0d63650413
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
elmicro | 0:db0d63650413 | 1 | #include "2d_draw.h" |
elmicro | 0:db0d63650413 | 2 | #include "TFT.h" |
elmicro | 0:db0d63650413 | 3 | #include "touch.h" |
elmicro | 0:db0d63650413 | 4 | |
elmicro | 0:db0d63650413 | 5 | //unsigned char DispDir; |
elmicro | 0:db0d63650413 | 6 | |
elmicro | 0:db0d63650413 | 7 | /* =================================================================== |
elmicro | 0:db0d63650413 | 8 | routine: DrawCircle |
elmicro | 0:db0d63650413 | 9 | purpose: Guess what?! |
elmicro | 0:db0d63650413 | 10 | parameters: <posX, posY> Middlepoint of circle (pixel-aligned) |
elmicro | 0:db0d63650413 | 11 | <radius> radius of circle (in pixels) |
elmicro | 0:db0d63650413 | 12 | <color> |
elmicro | 0:db0d63650413 | 13 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 14 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 15 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 16 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 17 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 18 | void DrawCircle(unsigned int posX, unsigned int posY, unsigned int radius, unsigned int color) |
elmicro | 0:db0d63650413 | 19 | { |
elmicro | 0:db0d63650413 | 20 | int x = -radius, y = 0, err = 2 - 2 * radius, e2; |
elmicro | 0:db0d63650413 | 21 | do { |
elmicro | 0:db0d63650413 | 22 | SetPixel(posX - x, posY + y, color); |
elmicro | 0:db0d63650413 | 23 | SetPixel(posX + x, posY + y, color); |
elmicro | 0:db0d63650413 | 24 | SetPixel(posX + x, posY - y, color); |
elmicro | 0:db0d63650413 | 25 | SetPixel(posX - x, posY - y, color); |
elmicro | 0:db0d63650413 | 26 | e2 = err; |
elmicro | 0:db0d63650413 | 27 | if (e2 <= y) { |
elmicro | 0:db0d63650413 | 28 | err += ++y*2+1; |
elmicro | 0:db0d63650413 | 29 | if (-x == y && e2 <= x) e2 = 0; |
elmicro | 0:db0d63650413 | 30 | } |
elmicro | 0:db0d63650413 | 31 | if (e2 > x) err += ++x*2+1; |
elmicro | 0:db0d63650413 | 32 | } while (x <= 0); |
elmicro | 0:db0d63650413 | 33 | } |
elmicro | 0:db0d63650413 | 34 | |
elmicro | 0:db0d63650413 | 35 | /* =================================================================== |
elmicro | 0:db0d63650413 | 36 | routine: DrawHorizontalLine |
elmicro | 0:db0d63650413 | 37 | parameters: <posX, posY> starting point (pixel-aligned) |
elmicro | 0:db0d63650413 | 38 | <length> length of line (in pixels) |
elmicro | 0:db0d63650413 | 39 | <color> |
elmicro | 0:db0d63650413 | 40 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 41 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 42 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 43 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 44 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 45 | void DrawHorizontalLine(unsigned int posX, unsigned int posY,unsigned int length,unsigned int color) |
elmicro | 0:db0d63650413 | 46 | { |
elmicro | 0:db0d63650413 | 47 | SetXY(posX, posY); |
elmicro | 0:db0d63650413 | 48 | SetOrientation(0); |
elmicro | 0:db0d63650413 | 49 | if(length + posX > TFTData.XRes) |
elmicro | 0:db0d63650413 | 50 | { |
elmicro | 0:db0d63650413 | 51 | length = TFTData.XRes - posX; |
elmicro | 0:db0d63650413 | 52 | } |
elmicro | 0:db0d63650413 | 53 | for(unsigned int i=0; i<length; i++) |
elmicro | 0:db0d63650413 | 54 | { |
elmicro | 0:db0d63650413 | 55 | SendData(color); |
elmicro | 0:db0d63650413 | 56 | } |
elmicro | 0:db0d63650413 | 57 | } |
elmicro | 0:db0d63650413 | 58 | |
elmicro | 0:db0d63650413 | 59 | |
elmicro | 0:db0d63650413 | 60 | /* =================================================================== |
elmicro | 0:db0d63650413 | 61 | routine: DrawVerticalLine |
elmicro | 0:db0d63650413 | 62 | parameters: <posX, posY> starting point (pixel-aligned) |
elmicro | 0:db0d63650413 | 63 | <length> length of line (in pixels) |
elmicro | 0:db0d63650413 | 64 | <color> |
elmicro | 0:db0d63650413 | 65 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 66 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 67 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 68 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 69 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 70 | void DrawVerticalLine(unsigned int posX, unsigned int posY,unsigned int length,unsigned int color) |
elmicro | 0:db0d63650413 | 71 | { |
elmicro | 0:db0d63650413 | 72 | SetXY(posX,posY); |
elmicro | 0:db0d63650413 | 73 | SetOrientation(1); |
elmicro | 0:db0d63650413 | 74 | if(length + posY > TFTData.YRes) |
elmicro | 0:db0d63650413 | 75 | { |
elmicro | 0:db0d63650413 | 76 | length = TFTData.YRes - posY; |
elmicro | 0:db0d63650413 | 77 | } |
elmicro | 0:db0d63650413 | 78 | |
elmicro | 0:db0d63650413 | 79 | for(unsigned int i=0; i<length; i++) |
elmicro | 0:db0d63650413 | 80 | { |
elmicro | 0:db0d63650413 | 81 | SendData(color); |
elmicro | 0:db0d63650413 | 82 | } |
elmicro | 0:db0d63650413 | 83 | } |
elmicro | 0:db0d63650413 | 84 | |
elmicro | 0:db0d63650413 | 85 | |
elmicro | 0:db0d63650413 | 86 | /* =================================================================== |
elmicro | 0:db0d63650413 | 87 | routine: DrawLine |
elmicro | 0:db0d63650413 | 88 | purpose: Connects two points by a line with width of 1 pixel |
elmicro | 0:db0d63650413 | 89 | parameters: <xstart, xend> starting point (pixel-aligned) |
elmicro | 0:db0d63650413 | 90 | <xstart, xend> ending point (pixel-aligned) |
elmicro | 0:db0d63650413 | 91 | <iColor> |
elmicro | 0:db0d63650413 | 92 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 93 | note: Based on the Bresenham-Algorithm for rasterizing |
elmicro | 0:db0d63650413 | 94 | vector elements |
elmicro | 0:db0d63650413 | 95 | author: (C)2006 Stefan Kleinwort (mikrocontroller.net) |
elmicro | 0:db0d63650413 | 96 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 97 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 98 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 99 | |
elmicro | 0:db0d63650413 | 100 | void DrawLine(int xstart, int ystart, int xend ,int yend, int iColor) |
elmicro | 0:db0d63650413 | 101 | { |
elmicro | 0:db0d63650413 | 102 | int x, y, t, dist, xerr, yerr, dx, dy, incx, incy; |
elmicro | 0:db0d63650413 | 103 | |
elmicro | 0:db0d63650413 | 104 | /* calculate distances of both directions */ |
elmicro | 0:db0d63650413 | 105 | dx = xend - xstart; |
elmicro | 0:db0d63650413 | 106 | dy = yend - ystart; |
elmicro | 0:db0d63650413 | 107 | |
elmicro | 0:db0d63650413 | 108 | /* calculate polarity */ |
elmicro | 0:db0d63650413 | 109 | if(dx<0) |
elmicro | 0:db0d63650413 | 110 | { |
elmicro | 0:db0d63650413 | 111 | incx = -1; |
elmicro | 0:db0d63650413 | 112 | dx = -dx; |
elmicro | 0:db0d63650413 | 113 | } |
elmicro | 0:db0d63650413 | 114 | else |
elmicro | 0:db0d63650413 | 115 | incx = dx ? 1 : 0; |
elmicro | 0:db0d63650413 | 116 | |
elmicro | 0:db0d63650413 | 117 | if(dy < 0) |
elmicro | 0:db0d63650413 | 118 | { |
elmicro | 0:db0d63650413 | 119 | incy = -1; |
elmicro | 0:db0d63650413 | 120 | dy = -dy; |
elmicro | 0:db0d63650413 | 121 | } |
elmicro | 0:db0d63650413 | 122 | else |
elmicro | 0:db0d63650413 | 123 | incy = dy ? 1 : 0; |
elmicro | 0:db0d63650413 | 124 | |
elmicro | 0:db0d63650413 | 125 | /* determine larger distance */ |
elmicro | 0:db0d63650413 | 126 | dist = (dx > dy) ? dx : dy; |
elmicro | 0:db0d63650413 | 127 | |
elmicro | 0:db0d63650413 | 128 | /* loop init */ |
elmicro | 0:db0d63650413 | 129 | x = xstart; |
elmicro | 0:db0d63650413 | 130 | y = ystart; |
elmicro | 0:db0d63650413 | 131 | xerr = yerr = (dist) >> 1; //dx; |
elmicro | 0:db0d63650413 | 132 | |
elmicro | 0:db0d63650413 | 133 | /* Calculate pixel */ |
elmicro | 0:db0d63650413 | 134 | for(t = 0; t < dist; ++t) |
elmicro | 0:db0d63650413 | 135 | { |
elmicro | 0:db0d63650413 | 136 | SetPixel(x,y,iColor); |
elmicro | 0:db0d63650413 | 137 | xerr += dx; |
elmicro | 0:db0d63650413 | 138 | yerr += dy; |
elmicro | 0:db0d63650413 | 139 | if(xerr >= dist) |
elmicro | 0:db0d63650413 | 140 | { |
elmicro | 0:db0d63650413 | 141 | xerr -= dist; |
elmicro | 0:db0d63650413 | 142 | x += incx; |
elmicro | 0:db0d63650413 | 143 | } |
elmicro | 0:db0d63650413 | 144 | |
elmicro | 0:db0d63650413 | 145 | if(yerr >= dist) |
elmicro | 0:db0d63650413 | 146 | { |
elmicro | 0:db0d63650413 | 147 | yerr -= dist; |
elmicro | 0:db0d63650413 | 148 | y += incy; |
elmicro | 0:db0d63650413 | 149 | } |
elmicro | 0:db0d63650413 | 150 | } |
elmicro | 0:db0d63650413 | 151 | SetPixel(x, y, iColor); |
elmicro | 0:db0d63650413 | 152 | } |
elmicro | 0:db0d63650413 | 153 | |
elmicro | 0:db0d63650413 | 154 | |
elmicro | 0:db0d63650413 | 155 | /* =================================================================== |
elmicro | 0:db0d63650413 | 156 | routine: DrawRectangle |
elmicro | 0:db0d63650413 | 157 | purpose: Draws outlined rectangle with width of 1 pixel |
elmicro | 0:db0d63650413 | 158 | parameters: <posX, posY> starting point (pixel-aligned) |
elmicro | 0:db0d63650413 | 159 | <length> length of rectangle (in pixels) |
elmicro | 0:db0d63650413 | 160 | <height> height of rectangle (in pixels) |
elmicro | 0:db0d63650413 | 161 | <color> |
elmicro | 0:db0d63650413 | 162 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 163 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 164 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 165 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 166 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 167 | void DrawRectangle(unsigned int posX, unsigned int posY, unsigned int length, unsigned int height, unsigned int color) |
elmicro | 0:db0d63650413 | 168 | { |
elmicro | 0:db0d63650413 | 169 | DrawHorizontalLine(posX, posY, length, color); |
elmicro | 0:db0d63650413 | 170 | DrawHorizontalLine(posX, posY+height, length, color); |
elmicro | 0:db0d63650413 | 171 | DrawVerticalLine (posX, posY, height, color); |
elmicro | 0:db0d63650413 | 172 | DrawVerticalLine (posX + length, posY, height, color); |
elmicro | 0:db0d63650413 | 173 | } |
elmicro | 0:db0d63650413 | 174 | |
elmicro | 0:db0d63650413 | 175 | |
elmicro | 0:db0d63650413 | 176 | /* =================================================================== |
elmicro | 0:db0d63650413 | 177 | routine: FillRectangle |
elmicro | 0:db0d63650413 | 178 | purpose: Draws solid rectangle |
elmicro | 0:db0d63650413 | 179 | parameters: <posX, posY> starting point (pixel-aligned) |
elmicro | 0:db0d63650413 | 180 | <length> length of rectangle (in pixels) |
elmicro | 0:db0d63650413 | 181 | <height> height of rectangle (in pixels) |
elmicro | 0:db0d63650413 | 182 | <color> |
elmicro | 0:db0d63650413 | 183 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 184 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 185 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 186 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 187 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 188 | void FillRectangle(unsigned int posX, unsigned int posY, unsigned int length, unsigned int width, unsigned int color) |
elmicro | 0:db0d63650413 | 189 | { |
elmicro | 0:db0d63650413 | 190 | for(unsigned int i=0; i<width; i++) |
elmicro | 0:db0d63650413 | 191 | { |
elmicro | 0:db0d63650413 | 192 | switch(DispDir) |
elmicro | 0:db0d63650413 | 193 | { |
elmicro | 0:db0d63650413 | 194 | case DOWN2UP: |
elmicro | 0:db0d63650413 | 195 | DrawHorizontalLine(posX, posY-i, length, color); |
elmicro | 0:db0d63650413 | 196 | break; |
elmicro | 0:db0d63650413 | 197 | case RIGHT2LEFT: |
elmicro | 0:db0d63650413 | 198 | DrawHorizontalLine(posX, posY-i, length, color); |
elmicro | 0:db0d63650413 | 199 | break; |
elmicro | 0:db0d63650413 | 200 | case UP2DOWN: |
elmicro | 0:db0d63650413 | 201 | DrawHorizontalLine(posX, posY+i, length, color); |
elmicro | 0:db0d63650413 | 202 | break; |
elmicro | 0:db0d63650413 | 203 | case LEFT2RIGHT: |
elmicro | 0:db0d63650413 | 204 | default: |
elmicro | 0:db0d63650413 | 205 | DrawHorizontalLine(posX, posY+i, length, color); |
elmicro | 0:db0d63650413 | 206 | } |
elmicro | 0:db0d63650413 | 207 | } |
elmicro | 0:db0d63650413 | 208 | } |
elmicro | 0:db0d63650413 | 209 | |
elmicro | 0:db0d63650413 | 210 | /* =================================================================== |
elmicro | 0:db0d63650413 | 211 | routine: DrawAscii |
elmicro | 0:db0d63650413 | 212 | purpose: Displays single character |
elmicro | 0:db0d63650413 | 213 | parameters: <ascii> character to display |
elmicro | 0:db0d63650413 | 214 | <posX, posY> pixel-aligned starting point |
elmicro | 0:db0d63650413 | 215 | <size> scaling factor of character |
elmicro | 0:db0d63650413 | 216 | (size=1 means no scaling, 2 doubles the size) |
elmicro | 0:db0d63650413 | 217 | <fgcolor> |
elmicro | 0:db0d63650413 | 218 | note: Needs a rastered font definition table with 8 |
elmicro | 0:db0d63650413 | 219 | bytes per character (const unsigned char simpleFont[][8]) |
elmicro | 0:db0d63650413 | 220 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 221 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 222 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 223 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 224 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 225 | void DrawAscii(unsigned char ascii,unsigned int posX, unsigned int posY,unsigned int size, unsigned int fgcolor) |
elmicro | 0:db0d63650413 | 226 | { |
elmicro | 0:db0d63650413 | 227 | SetXY(posX, posY); |
elmicro | 0:db0d63650413 | 228 | |
elmicro | 0:db0d63650413 | 229 | if( (ascii < 0x20) || (ascii > 0x7e) ) //check for valid ASCII char |
elmicro | 0:db0d63650413 | 230 | { |
elmicro | 0:db0d63650413 | 231 | ascii = '?'; //char not supported |
elmicro | 0:db0d63650413 | 232 | } |
elmicro | 0:db0d63650413 | 233 | for(unsigned char i=0; i<8; i++) |
elmicro | 0:db0d63650413 | 234 | { |
elmicro | 0:db0d63650413 | 235 | unsigned char temp = simpleFont[ascii - 0x20][i]; |
elmicro | 0:db0d63650413 | 236 | for(unsigned char f=0; f<8; f++) |
elmicro | 0:db0d63650413 | 237 | { |
elmicro | 0:db0d63650413 | 238 | if( (temp>>f) & 0x01 ) |
elmicro | 0:db0d63650413 | 239 | { |
elmicro | 0:db0d63650413 | 240 | switch(DispDir) |
elmicro | 0:db0d63650413 | 241 | { |
elmicro | 0:db0d63650413 | 242 | case DOWN2UP: |
elmicro | 0:db0d63650413 | 243 | FillRectangle(posX+f*size, posY-i*size, size, size, fgcolor); |
elmicro | 0:db0d63650413 | 244 | break; |
elmicro | 0:db0d63650413 | 245 | case RIGHT2LEFT: |
elmicro | 0:db0d63650413 | 246 | FillRectangle(posX-i*size, posY-f*size, size, size, fgcolor); |
elmicro | 0:db0d63650413 | 247 | break; |
elmicro | 0:db0d63650413 | 248 | case UP2DOWN: |
elmicro | 0:db0d63650413 | 249 | FillRectangle(posX-f*size, posY+i*size, size, size, fgcolor); |
elmicro | 0:db0d63650413 | 250 | break; |
elmicro | 0:db0d63650413 | 251 | case LEFT2RIGHT: |
elmicro | 0:db0d63650413 | 252 | default: |
elmicro | 0:db0d63650413 | 253 | FillRectangle(posX+i*size, posY+f*size, size, size, fgcolor); |
elmicro | 0:db0d63650413 | 254 | } |
elmicro | 0:db0d63650413 | 255 | } |
elmicro | 0:db0d63650413 | 256 | } |
elmicro | 0:db0d63650413 | 257 | } |
elmicro | 0:db0d63650413 | 258 | } |
elmicro | 0:db0d63650413 | 259 | |
elmicro | 0:db0d63650413 | 260 | /* =================================================================== |
elmicro | 0:db0d63650413 | 261 | routine: DrawString |
elmicro | 0:db0d63650413 | 262 | purpose: Displays string of characters |
elmicro | 0:db0d63650413 | 263 | parameters: <*string> pointer to null-terminated (!) character |
elmicro | 0:db0d63650413 | 264 | array |
elmicro | 0:db0d63650413 | 265 | <posX, posY> pixel-aligned starting point |
elmicro | 0:db0d63650413 | 266 | <size> scaling factor of characters (see DrawAscii) |
elmicro | 0:db0d63650413 | 267 | <fgcolor> |
elmicro | 0:db0d63650413 | 268 | note: based on DrawAscii function |
elmicro | 0:db0d63650413 | 269 | date: 2012-06-27 |
elmicro | 0:db0d63650413 | 270 | author: Seeed Studio |
elmicro | 0:db0d63650413 | 271 | co-author: Stefan Guenther |
elmicro | 0:db0d63650413 | 272 | Elektronikladen | ELMICRO |
elmicro | 0:db0d63650413 | 273 | -------------------------------------------------------------------*/ |
elmicro | 0:db0d63650413 | 274 | void DrawString(char *string,unsigned int posX, unsigned int posY,unsigned int size,unsigned int fgcolor) |
elmicro | 0:db0d63650413 | 275 | { |
elmicro | 0:db0d63650413 | 276 | while(*string) |
elmicro | 0:db0d63650413 | 277 | { |
elmicro | 0:db0d63650413 | 278 | DrawAscii(*string, posX, posY, size, fgcolor); |
elmicro | 0:db0d63650413 | 279 | *string++; |
elmicro | 0:db0d63650413 | 280 | switch(DispDir) |
elmicro | 0:db0d63650413 | 281 | { |
elmicro | 0:db0d63650413 | 282 | case DOWN2UP: |
elmicro | 0:db0d63650413 | 283 | if(posY > 0) posY-=8*size; //Change position to next char |
elmicro | 0:db0d63650413 | 284 | break; |
elmicro | 0:db0d63650413 | 285 | case RIGHT2LEFT: |
elmicro | 0:db0d63650413 | 286 | if(posX > 0) posX-=8*size; |
elmicro | 0:db0d63650413 | 287 | break; |
elmicro | 0:db0d63650413 | 288 | case UP2DOWN: |
elmicro | 0:db0d63650413 | 289 | if(posY < TFTData.YRes) posY+=8*size; |
elmicro | 0:db0d63650413 | 290 | break; |
elmicro | 0:db0d63650413 | 291 | case LEFT2RIGHT: |
elmicro | 0:db0d63650413 | 292 | default: |
elmicro | 0:db0d63650413 | 293 | if(posX < TFTData.XRes) posX+=8*size; |
elmicro | 0:db0d63650413 | 294 | } |
elmicro | 0:db0d63650413 | 295 | } |
elmicro | 0:db0d63650413 | 296 | } |
elmicro | 0:db0d63650413 | 297 | |
elmicro | 0:db0d63650413 | 298 | |
elmicro | 0:db0d63650413 | 299 | void DispPolygon2D(int *pIn, int iCorners, int iColor) |
elmicro | 0:db0d63650413 | 300 | { |
elmicro | 0:db0d63650413 | 301 | int x, x1,y1; |
elmicro | 0:db0d63650413 | 302 | x1=*pIn; |
elmicro | 0:db0d63650413 | 303 | y1=*(pIn+1); |
elmicro | 0:db0d63650413 | 304 | for(x=2; x<=iCorners; x++) |
elmicro | 0:db0d63650413 | 305 | { |
elmicro | 0:db0d63650413 | 306 | DrawLine(*pIn, *(pIn+1), *(pIn+2), *(pIn+3), iColor); |
elmicro | 0:db0d63650413 | 307 | pIn+=2; |
elmicro | 0:db0d63650413 | 308 | } |
elmicro | 0:db0d63650413 | 309 | DrawLine(*pIn, *(pIn+1), x1, y1, iColor); |
elmicro | 0:db0d63650413 | 310 | } |