Last active
August 29, 2015 14:09
-
-
Save D3f0/294caf0860231e8b17f8 to your computer and use it in GitHub Desktop.
Mara para Arduino
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "metadata": { | |
| "author": "Nahuel Defoss\u00e9", | |
| "name": "", | |
| "signature": "sha256:0e596bf855e85768efc0a387d0d9b12a21899d5a0bf935acbc171174cff0d802" | |
| }, | |
| "nbformat": 3, | |
| "nbformat_minor": 0, | |
| "worksheets": [ | |
| { | |
| "cells": [ | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "%load_ext hierarchymagic" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 1 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Protocolo de Mara\n", | |
| "\n", | |
| "<img src=\"http://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Gro%C3%9Fer_Mara_0505273.jpg/250px-Gro%C3%9Fer_Mara_0505273.jpg\">\n", | |
| "\n", | |
| "# Estructura de una trama Mara\n", | |
| "<table class=\"protocol\" style=\"text-align: center\">\n", | |
| " <tr>\n", | |
| " <td>Nombre</td>\n", | |
| " <th>SOF</th><th>QTY</th><th>DST</th><th>SRC</th><th>SEQ</th><th>CMD</th><th>[PAYLOAD]</th><th>BCC H</th><th>BCC L</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <td>Significado</td>\n", | |
| " <td>Inicio de trama</td>\n", | |
| " <td>Longitud del trama</td>\n", | |
| " <td>Direcci\u00f3n de destino</td>\n", | |
| " <td>Direcci\u00f3n de origen</td>\n", | |
| " <td>N\u00famero de secuencia</td>\n", | |
| " <td>Comando</td>\n", | |
| " <td>Carga \u00fatil</td>\n", | |
| " <td>Suma de coprobaci\u00f3n byte alto</td>\n", | |
| " <td>Suma de comprobaci\u00f3n byte bajo</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <td>Ejemplo</td>\n", | |
| " <td>FE</td><td>08</td><td>01</td><td>40</td><td>80</td><td>10</td><td></td><td>80</td><td>A7</td>\n", | |
| " </tr>\n", | |
| "</table>\n", | |
| "\n", | |
| "## SOF\n", | |
| "Comienzo de trama\n", | |
| "\n", | |
| "## QTY\n", | |
| "Longitud total de la trama, en bytes, incluyendo el BCC H y L\n", | |
| "\n", | |
| "## DST\n", | |
| "Direcci\u00f3n destino, en general `0xFF` es una direcci\u00f3 de broadcast.\n", | |
| "\n", | |
| "## SRC\n", | |
| "Direcci\u00f3n de origen, generalmente no cambia y es la del ``master`` en la comunicaci\u00f3n.\n", | |
| "\n", | |
| "## SEQ\n", | |
| "N\u00famero de secuencia, comienza en ``0x00`` y llega hasta ``0xAA``\n", | |
| "\n", | |
| "## CMD\n", | |
| "N\u00famero de comando. Los comandos pueden ser con o sin respuesta. Los comandos que sean enviados con ``DST == 0xFF`` nunca tienen respuesta.\n", | |
| "\n", | |
| "### Nota\n", | |
| "\n", | |
| "Cuando hablemos de n\u00fameros hexadecimales utilizaremos la notaci\u00f3n de C/C++, que consiste en anteponer un ``0x`` al n\u00famero, adem\u00e1s se rellenar\u00e1 con un 0 si el nibble alto es 0. Por ejemplo, el n\u00famero 10 se escribe ``0x0A``." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "%%dot -f svg\n", | |
| "digraph G {\n", | |
| " WAIT_SOF -> WAIT_QTY [label=\"Rx byte == SOF\"];\n", | |
| " WAIT_SOF -> WAIT_SOF [label=\"Rx byte != SOF\"];\n", | |
| " WAIT_QTY -> WAIT_SOF [label=\"Rx byte < 5\"];\n", | |
| " WAIT_QTY -> WAIT_FRAME_QTY [label=\"*\"];\n", | |
| " WAIT_FRAME_QTY -> WAIT_SOF [label=\"received == QTY\"];\n", | |
| " WAIT_FRAME_QTY -> WAIT_FRAME_QTY [label=\"received < QTY\"];\n", | |
| "\n", | |
| "\n", | |
| "}" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "metadata": {}, | |
| "output_type": "display_data", | |
| "svg": [ | |
| "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", | |
| "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", | |
| " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", | |
| "<!-- Generated by graphviz version 2.38.0 (20140413.2041)\n", | |
| " -->\n", | |
| "<!-- Title: G Pages: 1 -->\n", | |
| "<svg width=\"396pt\" height=\"218pt\"\n", | |
| " viewBox=\"0.00 0.00 396.10 218.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", | |
| "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 214)\">\n", | |
| "<title>G</title>\n", | |
| "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-214 392.105,-214 392.105,4 -4,4\"/>\n", | |
| "<!-- WAIT_SOF -->\n", | |
| "<g id=\"node1\" class=\"node\"><title>WAIT_SOF</title>\n", | |
| "<ellipse fill=\"none\" stroke=\"black\" cx=\"123.913\" cy=\"-192\" rx=\"56.59\" ry=\"18\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"123.913\" y=\"-188.3\" font-family=\"Times,serif\" font-size=\"14.00\">WAIT_SOF</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_SOF->WAIT_SOF -->\n", | |
| "<g id=\"edge2\" class=\"edge\"><title>WAIT_SOF->WAIT_SOF</title>\n", | |
| "<path fill=\"none\" stroke=\"black\" d=\"M175.13,-199.794C188.43,-199.315 198.458,-196.717 198.458,-192 198.458,-188.573 193.164,-186.264 185.168,-185.074\"/>\n", | |
| "<polygon fill=\"black\" stroke=\"black\" points=\"185.394,-181.581 175.13,-184.206 184.791,-188.555 185.394,-181.581\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"245.458\" y=\"-188.3\" font-family=\"Times,serif\" font-size=\"14.00\">Rx byte != SOF</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_QTY -->\n", | |
| "<g id=\"node2\" class=\"node\"><title>WAIT_QTY</title>\n", | |
| "<ellipse fill=\"none\" stroke=\"black\" cx=\"114.913\" cy=\"-105\" rx=\"58.4896\" ry=\"18\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"114.913\" y=\"-101.3\" font-family=\"Times,serif\" font-size=\"14.00\">WAIT_QTY</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_SOF->WAIT_QTY -->\n", | |
| "<g id=\"edge1\" class=\"edge\"><title>WAIT_SOF->WAIT_QTY</title>\n", | |
| "<path fill=\"none\" stroke=\"black\" d=\"M68.2661,-188.784C44.8276,-184.747 19.6209,-175.656 4.91329,-156 -11.6582,-133.853 18.0248,-121.255 50.7096,-114.246\"/>\n", | |
| "<polygon fill=\"black\" stroke=\"black\" points=\"51.7629,-117.606 60.9016,-112.245 50.4147,-110.737 51.7629,-117.606\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"53.4133\" y=\"-144.8\" font-family=\"Times,serif\" font-size=\"14.00\">Rx byte == SOF</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_QTY->WAIT_SOF -->\n", | |
| "<g id=\"edge3\" class=\"edge\"><title>WAIT_QTY->WAIT_SOF</title>\n", | |
| "<path fill=\"none\" stroke=\"black\" d=\"M116.732,-123.175C117.963,-134.806 119.617,-150.419 121.026,-163.734\"/>\n", | |
| "<polygon fill=\"black\" stroke=\"black\" points=\"117.558,-164.223 122.092,-173.799 124.52,-163.486 117.558,-164.223\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"154.913\" y=\"-144.8\" font-family=\"Times,serif\" font-size=\"14.00\">Rx byte < 5</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_FRAME_QTY -->\n", | |
| "<g id=\"node3\" class=\"node\"><title>WAIT_FRAME_QTY</title>\n", | |
| "<ellipse fill=\"none\" stroke=\"black\" cx=\"179.913\" cy=\"-18\" rx=\"96.3833\" ry=\"18\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"179.913\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">WAIT_FRAME_QTY</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_QTY->WAIT_FRAME_QTY -->\n", | |
| "<g id=\"edge4\" class=\"edge\"><title>WAIT_QTY->WAIT_FRAME_QTY</title>\n", | |
| "<path fill=\"none\" stroke=\"black\" d=\"M127.755,-87.2067C137.131,-74.9464 150.002,-58.1143 160.613,-44.2391\"/>\n", | |
| "<polygon fill=\"black\" stroke=\"black\" points=\"163.581,-46.119 166.876,-36.0493 158.021,-41.8668 163.581,-46.119\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"154.913\" y=\"-57.8\" font-family=\"Times,serif\" font-size=\"14.00\">*</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_FRAME_QTY->WAIT_SOF -->\n", | |
| "<g id=\"edge5\" class=\"edge\"><title>WAIT_FRAME_QTY->WAIT_SOF</title>\n", | |
| "<path fill=\"none\" stroke=\"black\" d=\"M187.913,-36.0863C199.5,-63.5841 217.167,-118.375 193.913,-156 189.035,-163.894 181.777,-170.067 173.757,-174.875\"/>\n", | |
| "<polygon fill=\"black\" stroke=\"black\" points=\"172.049,-171.819 164.831,-179.574 175.31,-178.013 172.049,-171.819\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"255.913\" y=\"-101.3\" font-family=\"Times,serif\" font-size=\"14.00\">received == QTY</text>\n", | |
| "</g>\n", | |
| "<!-- WAIT_FRAME_QTY->WAIT_FRAME_QTY -->\n", | |
| "<g id=\"edge6\" class=\"edge\"><title>WAIT_FRAME_QTY->WAIT_FRAME_QTY</title>\n", | |
| "<path fill=\"none\" stroke=\"black\" d=\"M268.01,-25.3828C283.399,-24.3984 294.105,-21.9375 294.105,-18 294.105,-14.9854 287.829,-12.8362 277.981,-11.5527\"/>\n", | |
| "<polygon fill=\"black\" stroke=\"black\" points=\"278.293,-8.06666 268.01,-10.6172 277.64,-15.0361 278.293,-8.06666\"/>\n", | |
| "<text text-anchor=\"middle\" x=\"341.105\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">received < QTY</text>\n", | |
| "</g>\n", | |
| "</g>\n", | |
| "</svg>\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 11 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Esto conforma un aut\u00f3mata finito con transiciones lambda, por lo tanto no determinista.\n", | |
| "A\u00fan as\u00ed es implementable. \n", | |
| "Cabe aclarar que lo que se recive entre el estado WAIT_QTY y las iteraciones en WAIT_FRAME_QTY es el [PDU](http://es.wikipedia.org/wiki/Unidad_de_datos_de_protocolo) con el checksum (BCC)." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "A partir de este aut\u00f3mata y vali\u00e9ndonos de que Arduino utiliza un compilador de C++, podemos generar una clase que se encarge de recibir los paquetes del protocolo." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "! mkdir -p src" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 12 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "%%file src/mara.cpp\n", | |
| "// Algunas definiciones\n", | |
| "\n", | |
| "#ifndef __AVR_ATmega328P__\n", | |
| "// Para emular un puerto serial de arduino compilando sobre x86\n", | |
| "// creamos la siguente clase\n", | |
| "class Serial {\n", | |
| " public:\n", | |
| " static int write(int) {\n", | |
| "\n", | |
| " }\n", | |
| " static int \n", | |
| "\n", | |
| "}\n", | |
| "#endif\n", | |
| "\n", | |
| "#define SOF 0xF0\n", | |
| "#define MIN_QTY 8\n", | |
| "#define MAX_PKG_LEN 256\n", | |
| "#define MAX_CMD_OP 128\n", | |
| "\n", | |
| "#define GET_CMD( arr ) (arr[5])\n", | |
| "\n", | |
| "class MaraServer {\n", | |
| " private:\n", | |
| " char _buffer[MAX_PKG_LEN];\n", | |
| " char _index; // Indice en el buffer\n", | |
| " bool (*_cmdCallbacks[MAX_CMD_OP])(char, char*);\n", | |
| " char _remainingQty; // Longitud que queda de lectura de trama luego de encontrar QTY\n", | |
| " public:\n", | |
| " /**\n", | |
| " * Estado del aut\u00f3mata de entrada\n", | |
| " */\n", | |
| " enum MaraInputState {\n", | |
| " WAIT_SOF,\n", | |
| " WAIT_QTY,\n", | |
| " WAIT_FRAME_QTY\n", | |
| " } _state;\n", | |
| " // Constructor \n", | |
| " MaraServer() {\n", | |
| " _state = WAIT_SOF;\n", | |
| " _index = 0;\n", | |
| " _remainingQty = 0;\n", | |
| " // Inicializaci\u00f3n en 0 del arreglo\n", | |
| " for (int i=0; i<MAX_CMD_OP; i++) {\n", | |
| " _cmdCallbacks[i] = (bool (*)(char, char*))0;\n", | |
| " }\n", | |
| " }\n", | |
| " // Acepta un byte\n", | |
| " void receiveByte(char byte) {\n", | |
| " switch (_state) {\n", | |
| " case WAIT_SOF:\n", | |
| " if (byte == SOF) {\n", | |
| " _state = WAIT_QTY;\n", | |
| " _buffer[_index++] = byte;\n", | |
| " }\n", | |
| " break;\n", | |
| " case WAIT_QTY:\n", | |
| " if (byte >= MIN_QTY && byte <= MAX_PKG_LEN) {\n", | |
| " _state = WAIT_FRAME_QTY;\n", | |
| " _buffer[_index++] = byte;\n", | |
| " _remainingQty = byte - 2; // Para control m\u00e1s tarde\n", | |
| " }\n", | |
| " break;\n", | |
| " case WAIT_FRAME_QTY:\n", | |
| " _buffer[_index++] = byte;\n", | |
| " _remainingQty--;\n", | |
| " if (_remainingQty == 0) {\n", | |
| " executeCommand();\n", | |
| " _state = WAIT_SOF;\n", | |
| " }\n", | |
| " break;\n", | |
| " \n", | |
| " }\n", | |
| " \n", | |
| " }\n", | |
| " // Realiza la operaci\u00f3n registrada para el comando\n", | |
| " void executeCommand(void) {\n", | |
| " // Hay handler registrado?\n", | |
| "\n", | |
| " }\n", | |
| " // Registra una funci\u00f3n que atiende un comando\n", | |
| " void onCommand(char command, bool (*funptr)(char, char *)) {\n", | |
| " _cmdCallbacks[command] = funptr;\n", | |
| " }\n", | |
| " \n", | |
| "};\n", | |
| "\n", | |
| "int main(void) {\n", | |
| " MaraServer server;\n", | |
| " //server.receiveByte();\n", | |
| "}" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "Overwriting src/mara.cpp\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 62 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "!gcc src/mara.cpp -o mara" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [], | |
| "prompt_number": 63 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "!gist -d \"Mara para Arduino\" \"Mara para Arduino.ipynb\"" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "https://gist.github.com/294caf0860231e8b17f8\r\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 67 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [ | |
| "!gist -u https://gist.github.com/294caf0860231e8b17f8 \"Mara para Arduino.ipynb\"" | |
| ], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "stream": "stdout", | |
| "text": [ | |
| "https://gist.github.com/294caf0860231e8b17f8\r\n" | |
| ] | |
| } | |
| ], | |
| "prompt_number": 69 | |
| }, | |
| { | |
| "cell_type": "code", | |
| "collapsed": false, | |
| "input": [], | |
| "language": "python", | |
| "metadata": {}, | |
| "outputs": [] | |
| } | |
| ], | |
| "metadata": {} | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment