PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

PokittoLib

Library for programming Pokitto hardware

How to Use

  1. Import this library to online compiler (see button "import" on the right hand side
  2. DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
  3. Change My_settings.h according to your project
  4. Start coding!
Committer:
Pokitto
Date:
Fri Dec 29 05:17:10 2017 +0000
Revision:
23:f88837b8f914
Parent:
6:72f87b7c7400
PokittoLib mbed and Github are back in sync with all contributions from Hanski and Spinal included

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pokitto 6:72f87b7c7400 1 /**************************************************************************/
Pokitto 6:72f87b7c7400 2 /*!
Pokitto 6:72f87b7c7400 3 @file PokittoConsole.cpp
Pokitto 6:72f87b7c7400 4 @author Jonne Valola
Pokitto 6:72f87b7c7400 5
Pokitto 6:72f87b7c7400 6 @section LICENSE
Pokitto 6:72f87b7c7400 7
Pokitto 6:72f87b7c7400 8 Software License Agreement (BSD License)
Pokitto 6:72f87b7c7400 9
Pokitto 6:72f87b7c7400 10 Copyright (c) 2016, Jonne Valola
Pokitto 6:72f87b7c7400 11 All rights reserved.
Pokitto 6:72f87b7c7400 12
Pokitto 6:72f87b7c7400 13 Redistribution and use in source and binary forms, with or without
Pokitto 6:72f87b7c7400 14 modification, are permitted provided that the following conditions are met:
Pokitto 6:72f87b7c7400 15 1. Redistributions of source code must retain the above copyright
Pokitto 6:72f87b7c7400 16 notice, this list of conditions and the following disclaimer.
Pokitto 6:72f87b7c7400 17 2. Redistributions in binary form must reproduce the above copyright
Pokitto 6:72f87b7c7400 18 notice, this list of conditions and the following disclaimer in the
Pokitto 6:72f87b7c7400 19 documentation and/or other materials provided with the distribution.
Pokitto 6:72f87b7c7400 20 3. Neither the name of the copyright holders nor the
Pokitto 6:72f87b7c7400 21 names of its contributors may be used to endorse or promote products
Pokitto 6:72f87b7c7400 22 derived from this software without specific prior written permission.
Pokitto 6:72f87b7c7400 23
Pokitto 6:72f87b7c7400 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
Pokitto 6:72f87b7c7400 25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Pokitto 6:72f87b7c7400 26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Pokitto 6:72f87b7c7400 27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
Pokitto 6:72f87b7c7400 28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Pokitto 6:72f87b7c7400 29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Pokitto 6:72f87b7c7400 30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Pokitto 6:72f87b7c7400 31 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Pokitto 6:72f87b7c7400 32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Pokitto 6:72f87b7c7400 33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Pokitto 6:72f87b7c7400 34 */
Pokitto 6:72f87b7c7400 35 /**************************************************************************/
Pokitto 6:72f87b7c7400 36
Pokitto 6:72f87b7c7400 37 #include "PokittoGlobs.h"
Pokitto 6:72f87b7c7400 38 #include "PokittoConsole.h"
Pokitto 6:72f87b7c7400 39 #include "PokittoFonts.h"
Pokitto 6:72f87b7c7400 40 #include "PokittoDisplay.h"
Pokitto 6:72f87b7c7400 41
Pokitto 6:72f87b7c7400 42 Pokitto::Console pConsole;
Pokitto 6:72f87b7c7400 43
Pokitto 6:72f87b7c7400 44 using namespace Pokitto;
Pokitto 6:72f87b7c7400 45
Pokitto 6:72f87b7c7400 46 consmsg Console::msgbuf[CONSOLEBUFSIZE];
Pokitto 6:72f87b7c7400 47 uint8_t Console::conslast;
Pokitto 6:72f87b7c7400 48 uint8_t Console::consfirst;
Pokitto 6:72f87b7c7400 49 uint8_t Console::conspointer;
Pokitto 6:72f87b7c7400 50 uint16_t Console::conscounter;
Pokitto 6:72f87b7c7400 51 uint16_t Console::color;
Pokitto 6:72f87b7c7400 52 Display* Console::_display;
Pokitto 6:72f87b7c7400 53 uint8_t Console::mode;
Pokitto 6:72f87b7c7400 54 uint8_t Console::visible;
Pokitto 6:72f87b7c7400 55 unsigned char* Console::font;
Pokitto 6:72f87b7c7400 56
Pokitto 6:72f87b7c7400 57 Console::Console() {
Pokitto 6:72f87b7c7400 58 conslast=consfirst=conspointer=conscounter=0;
Pokitto 6:72f87b7c7400 59 color=0xFFFF;
Pokitto 6:72f87b7c7400 60 font=(unsigned char*)fontMini;
Pokitto 6:72f87b7c7400 61 #if POK_CONSOLE_VISIBLE_AT_STARTUP > 0
Pokitto 6:72f87b7c7400 62 mode=CONS_OVERLAY|CONS_VISIBLE;
Pokitto 6:72f87b7c7400 63 #else
Pokitto 6:72f87b7c7400 64 mode=CONS_OVERLAY;//|CONS_VISIBLE;
Pokitto 6:72f87b7c7400 65 #endif
Pokitto 6:72f87b7c7400 66 }
Pokitto 6:72f87b7c7400 67
Pokitto 6:72f87b7c7400 68 void Console::Toggle() {
Pokitto 6:72f87b7c7400 69 if (!conscounter) // conscounter is a debounce feature for console toggle
Pokitto 6:72f87b7c7400 70 {
Pokitto 6:72f87b7c7400 71 mode ^= CONS_VISIBLE;
Pokitto 6:72f87b7c7400 72 conscounter = CONS_TIMEOUT;
Pokitto 6:72f87b7c7400 73 }
Pokitto 6:72f87b7c7400 74 }
Pokitto 6:72f87b7c7400 75
Pokitto 6:72f87b7c7400 76
Pokitto 6:72f87b7c7400 77 void Console::AddMessage(uint8_t source, uint8_t msgtype) {
Pokitto 6:72f87b7c7400 78 AddMessage(source,msgtype, V_NONE,0);
Pokitto 6:72f87b7c7400 79 }
Pokitto 6:72f87b7c7400 80
Pokitto 6:72f87b7c7400 81
Pokitto 6:72f87b7c7400 82 void Console::AddMessage(uint8_t type, char* stringptr) {
Pokitto 6:72f87b7c7400 83 AddMessage(MSOURCE_USER,type,V_STRING, (uint32_t) stringptr);
Pokitto 6:72f87b7c7400 84 }
Pokitto 6:72f87b7c7400 85
Pokitto 6:72f87b7c7400 86
Pokitto 6:72f87b7c7400 87 void Console::AddMessage(uint8_t msgtype, uint8_t valtype, uint32_t val) {
Pokitto 6:72f87b7c7400 88 AddMessage(MSOURCE_USER,msgtype,valtype,val);
Pokitto 6:72f87b7c7400 89 }
Pokitto 6:72f87b7c7400 90
Pokitto 6:72f87b7c7400 91 void Console::AddMessage(uint8_t source, uint8_t msgtype, uint8_t valtype, uint32_t val) {
Pokitto 6:72f87b7c7400 92 consmsg c;
Pokitto 6:72f87b7c7400 93 c.msgsource = source;
Pokitto 6:72f87b7c7400 94 c.msgtype = msgtype;
Pokitto 6:72f87b7c7400 95 c.valtype = valtype;
Pokitto 6:72f87b7c7400 96 c.val = val;
Pokitto 6:72f87b7c7400 97 msgbuf[conslast] = c;
Pokitto 6:72f87b7c7400 98 conslast++;
Pokitto 6:72f87b7c7400 99 if (conslast==CONSOLEBUFSIZE) conslast = 0; // wrap around the buffer
Pokitto 6:72f87b7c7400 100 consfirst = conslast + 1;
Pokitto 6:72f87b7c7400 101 if (consfirst == CONSOLEBUFSIZE) consfirst = 0;
Pokitto 6:72f87b7c7400 102 }
Pokitto 6:72f87b7c7400 103
Pokitto 6:72f87b7c7400 104 void Console::Last() {
Pokitto 6:72f87b7c7400 105 conspointer = conslast;
Pokitto 6:72f87b7c7400 106 }
Pokitto 6:72f87b7c7400 107
Pokitto 6:72f87b7c7400 108 void Console::RemoveLast() {
Pokitto 6:72f87b7c7400 109 Last();
Pokitto 6:72f87b7c7400 110 Previous();
Pokitto 6:72f87b7c7400 111 msgbuf[conspointer].msgsource = MSOURCE_USER;
Pokitto 6:72f87b7c7400 112 msgbuf[conspointer].msgtype = MSG_OK;
Pokitto 6:72f87b7c7400 113 msgbuf[conspointer].val = 0;
Pokitto 6:72f87b7c7400 114 msgbuf[conspointer].valtype = 0;
Pokitto 6:72f87b7c7400 115 conslast = conspointer;
Pokitto 6:72f87b7c7400 116 }
Pokitto 6:72f87b7c7400 117
Pokitto 6:72f87b7c7400 118 void Console::First() {
Pokitto 6:72f87b7c7400 119 consmsg c;
Pokitto 6:72f87b7c7400 120 uint16_t outofbounds=0;
Pokitto 6:72f87b7c7400 121 conspointer = consfirst;
Pokitto 6:72f87b7c7400 122 c=GetMessage();
Pokitto 6:72f87b7c7400 123 while (!c.msgsource) {
Pokitto 6:72f87b7c7400 124 Next();
Pokitto 6:72f87b7c7400 125 c=GetMessage();
Pokitto 6:72f87b7c7400 126 outofbounds++;
Pokitto 6:72f87b7c7400 127 if (outofbounds==CONSOLEBUFSIZE) {
Pokitto 6:72f87b7c7400 128 conspointer = consfirst;
Pokitto 6:72f87b7c7400 129 break;
Pokitto 6:72f87b7c7400 130 }
Pokitto 6:72f87b7c7400 131 }
Pokitto 6:72f87b7c7400 132 }
Pokitto 6:72f87b7c7400 133
Pokitto 6:72f87b7c7400 134 void Console::Previous() {
Pokitto 6:72f87b7c7400 135 if (conspointer==0) conspointer = CONSOLEBUFSIZE-1;
Pokitto 6:72f87b7c7400 136 else conspointer--;
Pokitto 6:72f87b7c7400 137 }
Pokitto 6:72f87b7c7400 138
Pokitto 6:72f87b7c7400 139 void Console::Next() {
Pokitto 6:72f87b7c7400 140 if (conspointer==CONSOLEBUFSIZE-1) conspointer = 0;
Pokitto 6:72f87b7c7400 141 else conspointer++;
Pokitto 6:72f87b7c7400 142 }
Pokitto 6:72f87b7c7400 143
Pokitto 6:72f87b7c7400 144 consmsg Console::GetMessage() {
Pokitto 6:72f87b7c7400 145 return msgbuf[conspointer];
Pokitto 6:72f87b7c7400 146 }
Pokitto 6:72f87b7c7400 147
Pokitto 6:72f87b7c7400 148 void Console::PrintMessage() {
Pokitto 6:72f87b7c7400 149 consmsg c = msgbuf[conspointer];
Pokitto 6:72f87b7c7400 150 switch (c.msgsource) {
Pokitto 6:72f87b7c7400 151 case MSOURCE_APP:
Pokitto 6:72f87b7c7400 152 _display->print("App:");break;
Pokitto 6:72f87b7c7400 153 case MSOURCE_BATT:
Pokitto 6:72f87b7c7400 154 _display->print("Batt:");break;
Pokitto 6:72f87b7c7400 155 case MSOURCE_BTNA:
Pokitto 6:72f87b7c7400 156 _display->print("A:");break;
Pokitto 6:72f87b7c7400 157 case MSOURCE_BTNB:
Pokitto 6:72f87b7c7400 158 _display->print("B:");break;
Pokitto 6:72f87b7c7400 159 case MSOURCE_BTNC:
Pokitto 6:72f87b7c7400 160 _display->print("C:");break;
Pokitto 6:72f87b7c7400 161 case MSOURCE_BTNU:
Pokitto 6:72f87b7c7400 162 _display->print("Up:");break;
Pokitto 6:72f87b7c7400 163 case MSOURCE_BTND:
Pokitto 6:72f87b7c7400 164 _display->print("Down:");break;
Pokitto 6:72f87b7c7400 165 case MSOURCE_BTNL:
Pokitto 6:72f87b7c7400 166 _display->print("Left:");break;
Pokitto 6:72f87b7c7400 167 case MSOURCE_BTNR:
Pokitto 6:72f87b7c7400 168 _display->print("Right:");break;
Pokitto 6:72f87b7c7400 169 case MSOURCE_LCD:
Pokitto 6:72f87b7c7400 170 _display->print("LCD:");break;
Pokitto 6:72f87b7c7400 171 case MSOURCE_SD:
Pokitto 6:72f87b7c7400 172 _display->print("SD:");break;
Pokitto 6:72f87b7c7400 173 case MSOURCE_SOUND:
Pokitto 6:72f87b7c7400 174 _display->print("Sound:");break;
Pokitto 6:72f87b7c7400 175 case MSOURCE_TIMER:
Pokitto 6:72f87b7c7400 176 _display->print("Timer:");break;
Pokitto 6:72f87b7c7400 177 case MSOURCE_USER:
Pokitto 6:72f87b7c7400 178 _display->print("User:");break;
Pokitto 6:72f87b7c7400 179 case MSOURCE_COLLISION:
Pokitto 6:72f87b7c7400 180 _display->print("Hit:");break;
Pokitto 6:72f87b7c7400 181 default:
Pokitto 6:72f87b7c7400 182 return;
Pokitto 6:72f87b7c7400 183 }
Pokitto 6:72f87b7c7400 184
Pokitto 6:72f87b7c7400 185 switch (c.msgtype) {
Pokitto 6:72f87b7c7400 186 case MSG_OK:
Pokitto 6:72f87b7c7400 187 _display->print("OK ");break;
Pokitto 6:72f87b7c7400 188 case MSG_INIT_OK:
Pokitto 6:72f87b7c7400 189 _display->print("INIT OK ");break;
Pokitto 6:72f87b7c7400 190 case MSG_INIT_FAIL:
Pokitto 6:72f87b7c7400 191 _display->print("INIT FAIL ");break;
Pokitto 6:72f87b7c7400 192 case MSG_WARNING:
Pokitto 6:72f87b7c7400 193 _display->print("WARNING ");break;
Pokitto 6:72f87b7c7400 194 case MSG_FATAL:
Pokitto 6:72f87b7c7400 195 _display->print("FATAL ");break;
Pokitto 6:72f87b7c7400 196 case MSG_GFX_MODE_CHANGE:
Pokitto 6:72f87b7c7400 197 _display->print("MODE ");break;
Pokitto 6:72f87b7c7400 198 case MSG_GFX_MODE_INVALID:
Pokitto 6:72f87b7c7400 199 _display->print("INVALID!");break;
Pokitto 6:72f87b7c7400 200 case MSG_NOT_ENOUGH_MEM:
Pokitto 6:72f87b7c7400 201 _display->print("NOT ENOUGH MEM ");break;
Pokitto 6:72f87b7c7400 202 case MSG_UP:
Pokitto 6:72f87b7c7400 203 _display->print("KEYUP");break;
Pokitto 6:72f87b7c7400 204 case MSG_DOWN:
Pokitto 6:72f87b7c7400 205 _display->print("KEYDOWN");break;
Pokitto 6:72f87b7c7400 206 case MSG_BREAK:
Pokitto 6:72f87b7c7400 207 _display->print("BREAK ");break;
Pokitto 6:72f87b7c7400 208 case MSG_YESNO:
Pokitto 6:72f87b7c7400 209 _display->print("YES(A)/NO(B)");break;
Pokitto 6:72f87b7c7400 210 case MSG_YES:
Pokitto 6:72f87b7c7400 211 _display->print("YES");break;
Pokitto 6:72f87b7c7400 212 case MSG_NO:
Pokitto 6:72f87b7c7400 213 _display->print("NO");break;
Pokitto 6:72f87b7c7400 214 case MSG_OBJECT:
Pokitto 6:72f87b7c7400 215 _display->print("OBJ1: ");break;
Pokitto 6:72f87b7c7400 216 case MSG_OBJECT2:
Pokitto 6:72f87b7c7400 217 _display->print("OBJ2: ");break;
Pokitto 6:72f87b7c7400 218 default:
Pokitto 6:72f87b7c7400 219 _display->print(" ");
Pokitto 6:72f87b7c7400 220 }
Pokitto 6:72f87b7c7400 221
Pokitto 6:72f87b7c7400 222 switch (c.valtype) {
Pokitto 6:72f87b7c7400 223 case V_NONE:
Pokitto 6:72f87b7c7400 224 _display->println();break;
Pokitto 6:72f87b7c7400 225 case V_UINT8:
Pokitto 6:72f87b7c7400 226 _display->println((uint16_t)c.val);break;
Pokitto 6:72f87b7c7400 227 case V_INT8:
Pokitto 6:72f87b7c7400 228 _display->println((int16_t)c.val);break;
Pokitto 6:72f87b7c7400 229 case V_UINT16:
Pokitto 6:72f87b7c7400 230 _display->println((uint16_t)c.val);break;
Pokitto 6:72f87b7c7400 231 case V_INT16:
Pokitto 6:72f87b7c7400 232 _display->println((int16_t)c.val);break;
Pokitto 6:72f87b7c7400 233 case V_UINT32:
Pokitto 6:72f87b7c7400 234 _display->println((uint32_t)c.val);break;
Pokitto 6:72f87b7c7400 235 case V_INT32:
Pokitto 6:72f87b7c7400 236 _display->println((int32_t)c.val);break;
Pokitto 6:72f87b7c7400 237 case V_FLOAT:
Pokitto 6:72f87b7c7400 238 _display->println((float)c.val);break;
Pokitto 6:72f87b7c7400 239 case V_STRING:
Pokitto 6:72f87b7c7400 240 _display->println((char*)c.val);break;
Pokitto 6:72f87b7c7400 241 default:
Pokitto 6:72f87b7c7400 242 _display->println();
Pokitto 6:72f87b7c7400 243 }
Pokitto 6:72f87b7c7400 244
Pokitto 6:72f87b7c7400 245 if (c.msgtype == MSG_BREAK || c.msgtype == MSG_YESNO) {
Pokitto 6:72f87b7c7400 246 #ifndef POK_SIM
Pokitto 6:72f87b7c7400 247 __disable_irq(); // Disable Interrupts
Pokitto 6:72f87b7c7400 248 #else
Pokitto 6:72f87b7c7400 249 pauseAudio(1);
Pokitto 6:72f87b7c7400 250 visible = false; // avoid loop in loop inside refreshDisplay
Pokitto 6:72f87b7c7400 251 simulator.wait_ms(300);
Pokitto 6:72f87b7c7400 252 #endif
Pokitto 6:72f87b7c7400 253 int rval=0;
Pokitto 6:72f87b7c7400 254 while(!rval) {
Pokitto 6:72f87b7c7400 255 _buttons->pollButtons();
Pokitto 6:72f87b7c7400 256 #ifdef POK_SIM
Pokitto 6:72f87b7c7400 257 simulator.refreshDisplay();
Pokitto 6:72f87b7c7400 258 #endif // POK_SIM
Pokitto 6:72f87b7c7400 259 if (_buttons->aBtn()) rval = 1;
Pokitto 6:72f87b7c7400 260 if (_buttons->bBtn()) rval = -1;
Pokitto 6:72f87b7c7400 261 }
Pokitto 6:72f87b7c7400 262 /* now remove this message to prevent it from rerunning */
Pokitto 6:72f87b7c7400 263 if (c.msgtype == MSG_YESNO) {
Pokitto 6:72f87b7c7400 264 int8_t* v;
Pokitto 6:72f87b7c7400 265 v = (int8_t*) c.val; //c.val is a pointer to the memory location that receives answer
Pokitto 6:72f87b7c7400 266 *v = rval; // return value through pointer
Pokitto 6:72f87b7c7400 267 msgbuf[conspointer].msgsource = MSOURCE_USER;
Pokitto 6:72f87b7c7400 268 if (rval==1) msgbuf[conspointer].msgtype = MSG_YES;
Pokitto 6:72f87b7c7400 269 else msgbuf[conspointer].msgtype = MSG_NO;
Pokitto 6:72f87b7c7400 270 } else msgbuf[conspointer].msgsource = MSOURCE_NULL;
Pokitto 6:72f87b7c7400 271
Pokitto 6:72f87b7c7400 272 #ifndef POK_SIM
Pokitto 6:72f87b7c7400 273 __enable_irq(); // Enable Interrupts
Pokitto 6:72f87b7c7400 274 #else
Pokitto 6:72f87b7c7400 275 pauseAudio(0);
Pokitto 6:72f87b7c7400 276 visible = true;
Pokitto 6:72f87b7c7400 277 #endif
Pokitto 6:72f87b7c7400 278 }
Pokitto 6:72f87b7c7400 279 }
Pokitto 6:72f87b7c7400 280
Pokitto 6:72f87b7c7400 281 void Console::Draw() {
Pokitto 6:72f87b7c7400 282 unsigned char* oldfont;
Pokitto 6:72f87b7c7400 283 int16_t oldx,oldy;
Pokitto 6:72f87b7c7400 284 uint16_t oldcolor;
Pokitto 6:72f87b7c7400 285 uint8_t oldsize;
Pokitto 6:72f87b7c7400 286 oldfont = (unsigned char*) _display->font;
Pokitto 6:72f87b7c7400 287 oldx = _display->cursorX;
Pokitto 6:72f87b7c7400 288 oldy = _display->cursorY;
Pokitto 6:72f87b7c7400 289 oldcolor = _display->directcolor;
Pokitto 6:72f87b7c7400 290 oldsize = _display->fontSize;
Pokitto 6:72f87b7c7400 291 if (!(mode & CONS_OVERLAY)) _display->clearLCD();
Pokitto 6:72f87b7c7400 292 _display->setFont(font5x7);
Pokitto 6:72f87b7c7400 293 _display->fontSize=1;
Pokitto 6:72f87b7c7400 294 _display->setCursor(0,0);
Pokitto 6:72f87b7c7400 295 _display->directcolor=color;
Pokitto 6:72f87b7c7400 296 First();
Pokitto 6:72f87b7c7400 297 while(conspointer!=conslast) {
Pokitto 6:72f87b7c7400 298 PrintMessage();
Pokitto 6:72f87b7c7400 299 Next();
Pokitto 6:72f87b7c7400 300 if (GetMessage().msgsource==MSOURCE_NULL) break;
Pokitto 6:72f87b7c7400 301 }
Pokitto 6:72f87b7c7400 302 _display->font = oldfont;
Pokitto 6:72f87b7c7400 303 _display->fontSize = oldsize;
Pokitto 6:72f87b7c7400 304 _display->cursorX = oldx;
Pokitto 6:72f87b7c7400 305 _display->cursorY = oldy;
Pokitto 6:72f87b7c7400 306 _display->directcolor = oldcolor;
Pokitto 6:72f87b7c7400 307 }
Pokitto 6:72f87b7c7400 308
Pokitto 6:72f87b7c7400 309
Pokitto 6:72f87b7c7400 310
Pokitto 6:72f87b7c7400 311
Pokitto 6:72f87b7c7400 312
Pokitto 6:72f87b7c7400 313
Pokitto 23:f88837b8f914 314