possibili applicazioni\ncon lista delle applicazioni e link al tiddler relativo\n\nesempio:\n\nWebServer
disegno cad per il montaggio paragonare al disegno del dip40
{{{\nInserire qui il codice C o ASM\n\nesempio\n\nif\n if\n else\nelse\n}}}
<html>\nLa scelta dell'indirizzo IP dipende dalla rete in cui si trova il dispositivo, perciò\npuò essere facilmente modificato nel file StackTsk.h, modificando le sequenti <em>define</em>:\n<pre class="code"> // esempio: 10.0.0.6\n#define MY_DEFAULT_IP_ADDR_BYTE1 (10)\n#define MY_DEFAULT_IP_ADDR_BYTE2 (0)\n#define MY_DEFAULT_IP_ADDR_BYTE3 (0)\n#define MY_DEFAULT_IP_ADDR_BYTE4 (6)</pre>\nAllo stesso modo è anche possibile cambiare l'<em>indirizzo MAC</em>:<br />\n<pre class="code"> // esempio: 00:04:A3:00:00:00\n#define MY_DEFAULT_MAC_BYTE1 (0x00)\n#define MY_DEFAULT_MAC_BYTE2 (0x04)\n#define MY_DEFAULT_MAC_BYTE3 (0xA3)\n#define MY_DEFAULT_MAC_BYTE4 (0x00)\n#define MY_DEFAULT_MAC_BYTE5 (0x00)\n#define MY_DEFAULT_MAC_BYTE6 (0x00)</pre>\nL'indirizzo IP non deve necessariamente essere statico, ma può essere assegnato automaticamente dal server DHCP. Per\nfare ciò bisogna abilitare il client DHCP scommentando la riga\n<pre class="code">//#define STACK_USE_DHCP</pre>\nsempre nel file StackTsk.h.<br />\n<br />\nNell'esempio proposto, i LED del modulo Ethernet sono utilizzati come LED generici; per\nfare ciò il bit di configurazione <em>ETHLED</em> è stato settato ad <em>OFF</em>; quindi,\nper ripristinare il normale utilizzo di tali LED, modificare la configurazione ad <em>ON</em>.\n<pre class="code">#pragma config XINST=OFF, WDT=OFF, FOSC2=ON, FOSC=HSPLL, ETHLED=ON</pre>\n<br />\nA questo punto è possibile ricompilare il firmware e caricarlo nel PIC.<br />\n</html>
[img[DIP40|DIP40Socket.jpg]]
FTPmicro\nSchemaElettrico\nPinOut
config.options.chkHttpReadOnly = true;
<html>\nAnalizziamo ora un semplice esempio per il monitoraggio in tempo reale della temperatura, sfruttando il sensore a bordo\ndi FTPMicro, e l'azionamento di due LED, tramite una pagina HTML ed una CGI.<br />\n<br />\nNell'esempio viene utilizzato <a target="_blank" href="http://www.gizax.it/articles/2005/ahah/" title="AHAH">AHAH</a> (Asynchronous HTTP And HTML), il quale\nci permette di inviare richieste HTTP in modo asincrono, ovvero senza dover ricaricare la pagina. <br />\nIl file CGI che utilizzeremo (<em>status.cgi</em>) è molto semplice; è costituito da codice html per realizzare una tabellina,\nall'interno della quale verranno scritti lo stato dei LED e la temperatura di sistema.\n<pre class="code"><table class="status_table">\n <tr><th colspan="2">Temperature</th></tr>\n <tr><td>System</td><td>%00°C</td></tr>\n <tr><th colspan="2">LED Status</th></tr>\n <tr><td>LED 1</td><td>%01</td></tr>\n <tr><td>LED 2</td><td>%02</td></tr>\n</table>\n</pre>\nCome si può notare, le variabili utilizzate sono:\n<ul>\n <li>00: la temperatura;</li>\n <li>01: il primo LED</li>\n <li>02: il secondo LED</li>\n</ul>\nQuindi questa pagina sarà richiesta periodicamente per conoscere lo stato del sistema. <br />\nOra esaminiamo la pagina principale (<em>index.htm</em>), la quale fondamentalmente conterrà due pulsanti per\nmodificare lo stato dei LED, ed ingloberà, grazie ad AHAH, la pagina CGI.\n<pre class="code"><html>\n <head>\n <title>FTPMicro: Temperature Example</title>\n <script type="text/javascript" src="/ahah.js"></script>\n <script type="text/javascript">\n function refresh() {\n if (lo) return true; // interrompe il caricamento se c'è già un altro caricamento in corso (causa pulsanti)\n noloadAHAH('/Status.cgi','tempdiv','GET'); // richiede la pagina status.cgi e la carica nel div "tempdiv"\n }\n window.setInterval("refresh()",2000);\n </script>\n <link rel="stylesheet" type="text/css" media="all" href="/style.css" />\n </head>\n <body>\n <h1>FTPMicro</h1>\n <div class="bar">\n The world smallest WebServer and FtpClient with DHCP and UDP features\n </div>\n <div id="tempdiv" class="left">\n Loading...\n </div>\n <div class="left">\n <form> \n <table class="status_table">\n <tr><th>LED Toggle</th></tr>\n <tr><td><input type="submit" value="LED 1" onclick="javascript: noloadAHAH('/Status.cgi?t=1','tempdiv','GET'); return false;"></td></tr>\n <tr><td><input type="submit" value="LED 2" onclick="javascript: noloadAHAH('/Status.cgi?t=2','tempdiv','GET'); return false;"></td></tr>\n </table>\n </form>\n </div>\n </body>\n</html>\n</pre>\nCome si può notare, la pagina è piuttosto semplice; la cosa che potrebbe risultare un po' criptica, però, è l'utilizzo di AHAH.<br />\nInnanzitutto, nell'header della pagina, si trova un breve script Javascript, che attraverso la funzione <em>setInterval</em>, ci\npermette di visualizzare lo stato ad intervalli regolari richiamando la pagina CGI. Quest'ultima verrà caricata all'interno del <em>div</em>\nche ha come id "tempdiv".<br />\nL'altra sezione di rilievo, è quella che riguarda i pulsanti. Anch'essi ricorrono ad AHAH per inviare comandi senza dover ricaricare la pagina.\nIn questo esempio, viene utilizzato il parametro "t" il cui valore corrisponde al LED su cui agire, quindi <em>/Status.cgi?t=1</em> sarà il comando\nda inviare per il primo LED, e <em>/Status.cgi?t=2</em> per il secondo. Dopo l'esecuzione del comando verrà restituita la pagina richiesta (<em>status.cgi</em>)\nche verrà sempre caricata all'interno del suo <em>div</em>.<br />\nNell'esempio viene anche utilizzato un file <em>css</em>, ma esso serve soltanto per definire lo stile della pagina.<br />\n<br />\n<div align="center"><img src="http://www.itentropy.it/images/tutorials/http_example.jpg" alt="" /></div>\nA questo punto, analizziamo l'implementazione dei metodi <em>ProcessIO</em>, <em>HTTPExecCmd</em> e <em>HTTPGetVar</em>; ecco il primo:\n<pre class="code">\nstatic char Temperature[8];\n\nstatic void ProcessIO(void)\n{\n signed long temp;\n\n // Start A/D conversion\n ADCON0bits.GO = 1;\n\n // Wait until A/D conversion is done\n while(ADCON0bits.GO);\n\n temp = (long)(*(WORD*)(&ADRESL)) * 322 - 50000; // conversione approssimativa...\n itoa(temp/1000, Temperature);\n}</pre>\nTale metodo viene invocato ciclicamente, "appena possibile", ovvero quando lo stack non sta svolgendo le sue funzioni. In questo esempio,\neffettua la lettura della tensione d'uscita del sensore di temperatura, e la successiva conversione in stringa.<br />\n<br />\n<pre class="code">#define VAR_TEMPERATURE (0x00)\n#define VAR_LED1 (0x01)\n#define VAR_LED2 (0x02)\n\n#define CMD_LED1 (0x1)\n#define CMD_LED2 (0x2)</pre>\nQueste define sono utili per identificare variabili CGI e comandi.<br />\n<pre class="code">void HTTPExecCmd(BYTE** argv, BYTE argc)\n{\n if (argv[1][0] == 't') {\n switch (argv[2][0] - '0') {\n case CMD_LED1 :\n LED1_IO = !LED1_IO;\n break;\n case CMD_LED2 :\n LED2_IO = !LED2_IO;\n break;\n }\n }\n}</pre>\nCome visto prima, i possibili comandi che inviamo sono del tipo "status.cgi?t=x" dove <em>x</em> rappresenta il led\na cui applicare il comando. Con questo comando, quando verrà invocato il metodo <em>HTTPExecCmd</em>, l'argomento argv, conterrà al primo posto\nla stringa "status.cgi" che rimarrà invariata; il secondo elemento sarà "t" (e ci assicureremo che sia così); il terzo conterrà\nil numero relativo al LED ma sottoforma di carattere ASCII, perciò dovremo convertirlo in intero, sottraendovi il carattere '0'.<br />\n<pre class="code">WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val)\n{\n switch (var) {\n case VAR_LED1 :\n *val = LED1_IO ? '1' : '0';\n break;\n \n case VAR_LED2 :\n *val = LED2_IO ? '1' : '0';\n break;\n\n case VAR_TEMPERATURE:\n *val = Temperature[(BYTE)ref];\n if(Temperature[(BYTE)ref] == '\s0')\n return HTTP_END_OF_VAR;\n else if(Temperature[(BYTE)++ref] == '\s0' )\n return HTTP_END_OF_VAR;\n return ref;\n default : break;\n }\n return HTTP_END_OF_VAR;\n}</pre>\nInfine il metodo <em>HTTPGetVar</em> restituisce lo stato corrente dei LED, oppure la stringa <em>Temperature</em>; Nel primo caso\nè sufficiente assegnare a *val il carattere corrispondente allo stato del led (0 o 1), mentre nel secondo caso, trattandosi di una stringa,\nè necessario restituire un byte alla volta facendo riferimento al valore di <em>ref</em>.<br />\n<br />\nNel codice si fa riferimento alle definizioni <em>LEDx_IO</em>, le quali si trovano nel file <em>Compiler.h</em>:\n<pre class="code"> #define LED1_IO (LATAbits.LATA0)\n #define LED1_TRIS (TRISAbits.TRISA0)\n #define LED2_IO (LATAbits.LATA1)\n #define LED2_TRIS (TRISAbits.TRISA1)</pre>\nIn questo caso vengono utilizzati i LED legati al modulo Ethernet, perchè già presenti nella scheda, ma modificando\ntali definizioni si possono impiegare due pin generici.<br />\n</html>
<<exportTiddlers inline>>
/***\n''Export Tiddlers Plugin for TiddlyWiki version 2.0''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#ExportTiddlersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nWhen many people edit copies of the same TiddlyWiki document, the ability to easily copy and share these changes so they can then be redistributed to the entire group is very important. This ability is also very useful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)\n\nExportTiddlersPlugin let you ''select and extract tiddlers from your ~TiddlyWiki documents and save them to a local file'' or a remote server (requires installation of compatible server-side scripting, still under development...). An interactive control panel lets you specify a destination, and then select which tiddlers to export. A convenient 'selection filter' helps you pick desired tiddlers by specifying a combination of modification dates, tags, or tiddler text to be matched or excluded. ''Tiddler data can be output as ~TiddlyWiki "storeArea ~DIVs" that can be imported into another ~TiddlyWiki or as ~RSS-compatible XML that can be published for RSS syndication.''\n\n!!!!!Inline interface (live)\n<<<\n<<exportTiddlers inline>>\n<<<\n!!!!!Usage\n<<<\nOptional "special tiddlers" used by this plugin:\n* SiteUrl^^\nURL for official server-published version of document being viewed\ndefault: //none//^^\n* SiteHost^^\nhost name/address for remote server (e.g., "www.server.com" or "192.168.1.27")\ndefault: //none//^^\n* SitePost^^\nremote path/filename for submitting changes (e.g., "/cgi-bin/submit.cgi")\ndefault: //none//^^\n* SiteParams^^\narguments (if any) for server-side receiving script\ndefault: //none//^^\n* SiteID^^\nusername or other authorization identifier for login-controlled access to remote server\ndefault: current TiddlyWiki username (e.g., "YourName")^^\n* SiteDate^^\nstored date/time stamp for most recent published version of document\ndefault: current document.modified value (i.e., the 'file date')^^\n<<<\n!!!!!Example\n<<<\n<<exportTiddlers>>\n<<<\n!!!!!Installation\n<<<\nImport (or copy/paste) the following tiddlers into your document:\n''ExportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < exportTiddlers > >" macro^^\n<<<\n!!!!!Revision History\n<<<\n''2006.03.29 [2.1.3]''^^\nadded calls to convertUnicodeToUTF8() for generated output, so it better handles international characters.\n''2006.02.12 [2.1.2]''^^\nadded var to unintended global 'tags' in matchTags(). Avoids FF1501 bug when filtering by tags. (based on report by TedPavlic)\n''2006.02.04 [2.1.1]''^^\nadded var to variables that were unintentionally global. Avoids FireFox 1.5.0.1 crash bug when referencing global variables\n''2006.02.02 [2.1.0]''^^\nAdded support for output of complete TiddlyWiki documents. Let's you use ExportTiddlers to generate 'starter' documents from selected tiddlers.^^\n''2006.01.21 [2.0.1]''^^\nDefer initial panel creation and only register a notification function when panel first is created\nin saveChanges 'hijack', create panel as needed. Note: if window.event is not available to identify the click location, the export panel is positioned relative to the 'tiddlerDisplay' element of the TW document.\n^^\n''2005.12.27 [2.0.0]''^^\nUpdate for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n^^\n''2005.12.24 [0.9.5]''^^\nMinor adjustments to CSS to force correct link colors regardless of TW stylesheet selection\n^^\n''2005.12.16 [0.9.4]''^^\nDynamically create/remove exportPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding.\n^^\n''2005.11.15 [0.9.2]''^^\nadded non-Ajax post function to bypass javascript security restrictions on cross-domain I/O. Moved AJAX functions to separate tiddler (no longer needed here). Generalized HTTP server to support UnaWiki servers\n^^\n+++[previous releases...]\n''2005.11.08 [0.9.1]''^^\nmoved HTML, CSS and control initialization into exportInit() function and call from macro handler instead of at load time. This allows exportPanel to be placed within the same containing element as the "export tiddlers" button, so that relative positioning can be achieved.\n^^\n''2005.10.28 [0.9.0]''^^\nadded 'select opened tiddlers' feature\nBased on a suggestion by Geoff Slocock\n^^\n''2005.10.24 [0.8.3]''^^\nCorrected hijack of 'save changes' when using http:\n^^\n''2005.10.18 [0.8.2]''^^\nadded AJAX functions\n^^\n''2005.10.18 [0.8.1]''^^\nCorrected timezone handling when filtering for date ranges.\nImproved error checking/reporting for invalid filter values and filters that don't match any tiddlers.\nExporting localfile-to-localfile is working for IE and FF\nExporting server-to-localfile works in IE (after ActiveX warnings), but has security issues in FF\nCross-domain exporting (localfile/server-to-server) is under development\nCookies to remember filter settings - coming soon\nMore style tweaks, minor text changes and some assorted layout cleanup.\n^^\n''2005.10.17 [0.8.0]''^^\nFirst pre-release.\n^^\n''2005.10.16 [0.7.0]''^^\nfilter by tags\n^^\n''2005.10.15 [0.6.0]''^^\nfilter by title/text\n^^\n''2005.10.14 [0.5.0]''^^\nexport to local file (DIV or XML)\n^^\n''2005.10.14 [0.4.0]''^^\nfilter by start/end date\n^^\n''2005.10.13 [0.3.0]''^^\npanel interaction\n^^\n''2005.10.11 [0.2.0]''^^\npanel layout\n^^\n''2005.10.10 [0.1.0]''^^\ncode framework\n^^\n''2005.10.09 [0.0.0]''^^\ndevelopment started\n^^\n===\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // +++[version]\n//{{{\nversion.extensions.exportTiddlers = {major: 2, minor: 1, revision: 3, date: new Date(2006,3,29)};\n//}}}\n// //===\n\n// // +++[macro handler]\n//{{{\nconfig.macros.exportTiddlers = {\n label: "export tiddlers",\n prompt: "Copy selected tiddlers to an export document",\n datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields\n};\n\nconfig.macros.exportTiddlers.handler = function(place,macroName,params) {\n if (params[0]!="inline")\n { createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }\n var panel=createExportPanel(place);\n panel.style.position="static";\n panel.style.display="block";\n}\n\nfunction createExportPanel(place) {\n var panel=document.getElementById("exportPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");\n panel=createTiddlyElement(place,"span","exportPanel",null,null)\n panel.innerHTML=config.macros.exportTiddlers.html;\n exportShowPanel(document.location.protocol);\n exportInitFilter();\n refreshExportList(0);\n store.addNotification(null,refreshExportList); // refresh listbox after every tiddler change\n return panel;\n}\n\nfunction onClickExportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("exportPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createExportPanel(parent);\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n// //===\n\n// // +++[Hijack saveChanges] diverts 'notFileUrlError' to display export control panel instead\n//{{{\nwindow.coreSaveChanges=window.saveChanges;\nwindow.saveChanges = function()\n{\n if (document.location.protocol=="file:") { coreSaveChanges(); return; }\n var e = window.event;\n var parent=e?resolveTarget(e).parentNode:document.body;\n var panel = document.getElementById("exportPanel");\n if (panel==undefined || panel.parentNode!=parent) panel=createExportPanel(parent);\n exportShowPanel(document.location.protocol);\n if (parent==document.body) { panel.style.left="30%"; panel.style.top="30%"; }\n panel.style.display = "block" ;\n}\n//}}}\n// //===\n\n// // +++[IE needs explicit scoping] for functions called by browser events\n//{{{\nwindow.onClickExportMenu=onClickExportMenu;\nwindow.onClickExportButton=onClickExportButton;\nwindow.exportShowPanel=exportShowPanel;\nwindow.exportShowFilterFields=exportShowFilterFields;\nwindow.refreshExportList=refreshExportList;\n//}}}\n// //===\n\n// // +++[CSS] for floating export control panel\n//{{{\nconfig.macros.exportTiddlers.css = '\s\n#exportPanel {\s\n display: none; position:absolute; z-index:12; width:35em; right:105%; top:6em;\s\n background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\s\n padding: 0.5em; margin:0em; -moz-border-radius:1em;\s\n}\s\n#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\s\n#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\s\n#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\s\n#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\s\n#exportPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\s\n#exportPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\s\n#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\s\n#exportPanel .rad { width:auto; }\s\n#exportPanel .chk { width:auto; }\s\n#exportPanel .btn { width:auto; }\s\n#exportPanel .btn1 { width:98%; }\s\n#exportPanel .btn2 { width:48%; }\s\n#exportPanel .btn3 { width:32%; }\s\n#exportPanel .btn4 { width:24%; }\s\n#exportPanel .btn5 { width:19%; }\s\n';\n//}}}\n// //===\n\n// // +++[HTML] for export control panel interface\n//{{{\nconfig.macros.exportTiddlers.html = '\s\n<!-- output target and format -->\s\n<table cellpadding="0" cellspacing="0"><tr><td width=50%>\s\n export to\s\n <select size=1 id="exportTo" onchange="exportShowPanel(this.value);">\s\n <option value="file:" SELECTED>this computer</option>\s\n <option value="http:">web server (http)</option>\s\n <option value="https:">secure web server (https)</option>\s\n <option value="ftp:">file server (ftp)</option>\s\n </select>\s\n</td><td width=50%>\s\n output format\s\n <select id="exportFormat" size=1>\s\n <option value="DIV">TiddlyWiki export file</option>\s\n <option value="TW">TiddlyWiki document</option>\s\n <option value="XML">RSS feed (XML)</option>\s\n </select>\s\n</td></tr></table>\s\n\s\n<!-- export to local file -->\s\n<div id="exportLocalPanel" style="margin-bottom:5px;margin-top:5px;">\s\nlocal path/filename<br>\s\n<input type="file" id="exportFilename" size=56 style="width:100%"><br>\s\n</div><!--panel-->\s\n\s\n<!-- export to http server -->\s\n<div id="exportHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;">\s\ndocument URL<br>\s\n<input type="text" id="exportHTTPSiteURL" onfocus="this.select()"><br>\s\nserver script / parameters<br>\s\n<input type="text" id="exportHTTPServerURL" onfocus="this.select()"><br>\s\n</div><!--panel-->\s\n\s\n<!-- export to ftp server -->\s\n<div id="exportFTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;">\s\n<table cellpadding="0" cellspacing="0" width="33%"><tr valign="top"><td>\s\n host server<br>\s\n <input type="text" id="exportFTPHost" onfocus="this.select()"><br>\s\n</td><td width="33%">\s\n username<br>\s\n <input type="text" id="exportFTPID" onfocus="this.select()"><br>\s\n</td><td width="33%">\s\n password<br>\s\n <input type="password" id="exportFTPPW" onfocus="this.select()"><br>\s\n</td></tr></table>\s\nFTP path/filename<br>\s\n<input type="text" id="exportFTPFilename" onfocus="this.select()"><br>\s\n</div><!--panel-->\s\n\s\n<!-- list of tiddlers -->\s\n<table><tr align="left"><td>\s\n select:\s\n <a href="JavaScript:;" id="exportSelectAll"\s\n onclick="onClickExportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="exportSelectChanges"\s\n onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\s\n changes </a> \s\n <a href="JavaScript:;" id="exportSelectOpened"\s\n onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\s\n opened </a> \s\n <a href="JavaScript:;" id="exportToggleFilter"\s\n onclick="onClickExportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</td><td align="right">\s\n <a href="JavaScript:;" id="exportListSmaller"\s\n onclick="onClickExportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="exportListLarger"\s\n onclick="onClickExportButton(this)" title="increase list size">\s\n + </a>\s\n</td></tr></table>\s\n<select id="exportList" multiple size="10" style="margin-bottom:5px;"\s\n onchange="refreshExportList(this.selectedIndex)">\s\n</select><br>\s\n\s\n<!-- selection filter -->\s\n<div id="exportFilterPanel" style="display:none">\s\n<table><tr align="left"><td>\s\n selection filter\s\n</td><td align="right">\s\n <a href="JavaScript:;" id="exportHideFilter"\s\n onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\s\n</td></tr></table>\s\n<div class="box">\s\n<input type="checkbox" class="chk" id="exportFilterStart" value="1"\s\n onclick="exportShowFilterFields(this)"> starting date/time<br>\s\n<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\s\n <select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\s\n <option value="0">today</option>\s\n <option value="1">yesterday</option>\s\n <option value="7">a week ago</option>\s\n <option value="30">a month ago</option>\s\n <option value="site">SiteDate</option>\s\n <option value="file">file date</option>\s\n <option value="other">other (mm/dd/yyyy hh:mm)</option>\s\n </select>\s\n</td><td width="50%">\s\n <input type="text" id="exportStartDate" onfocus="this.select()"\s\n onchange="document.getElementById(\s'exportFilterStartBy\s').value=\s'other\s';">\s\n</td></tr></table>\s\n<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\s\n onclick="exportShowFilterFields(this)"> ending date/time<br>\s\n<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\s\n <select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\s\n <option value="0">today</option>\s\n <option value="1">yesterday</option>\s\n <option value="7">a week ago</option>\s\n <option value="30">a month ago</option>\s\n <option value="site">SiteDate</option>\s\n <option value="file">file date</option>\s\n <option value="other">other (mm/dd/yyyy hh:mm)</option>\s\n </select>\s\n</td><td width="50%">\s\n <input type="text" id="exportEndDate" onfocus="this.select()"\s\n onchange="document.getElementById(\s'exportFilterEndBy\s').value=\s'other\s';">\s\n</td></tr></table>\s\n<input type="checkbox" class="chk" id=exportFilterTags value="1"\s\n onclick="exportShowFilterFields(this)"> match tags<br>\s\n<input type="text" id="exportTags" onfocus="this.select()">\s\n<input type="checkbox" class="chk" id=exportFilterText value="1"\s\n onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\s\n<input type="text" id="exportText" onfocus="this.select()">\s\n</div> <!--box-->\s\n</div> <!--panel-->\s\n\s\n<!-- action buttons -->\s\n<div style="text-align:center">\s\n<input type=button class="btn3" onclick="onClickExportButton(this)"\s\n id="exportFilter" value="apply filter">\s\n<input type=button class="btn3" onclick="onClickExportButton(this)"\s\n id="exportStart" value="export tiddlers">\s\n<input type=button class="btn3" onclick="onClickExportButton(this)"\s\n id="exportClose" value="close">\s\n</div><!--center-->\s\n';\n//}}}\n// //===\n\n// // +++[initialize interface]>\n// // +++[exportShowPanel(which)]\n//{{{\nfunction exportShowPanel(which) {\n var index=0; var panel='exportLocalPanel';\n switch (which) {\n case 'file:':\n case undefined:\n index=0; panel='exportLocalPanel'; break;\n case 'http:':\n index=1; panel='exportHTTPPanel'; break;\n case 'https:':\n index=2; panel='exportHTTPPanel'; break;\n case 'ftp:':\n index=3; panel='exportFTPPanel'; break;\n default:\n alert("Sorry, export to "+which+" is not yet available");\n break;\n }\n exportInitPanel(which);\n document.getElementById('exportTo').selectedIndex=index;\n document.getElementById('exportLocalPanel').style.display='none';\n document.getElementById('exportHTTPPanel').style.display='none';\n document.getElementById('exportFTPPanel').style.display='none';\n document.getElementById(panel).style.display='block';\n}\n//}}}\n// //===\n\n// // +++[exportInitPanel(which)]\n//{{{\nfunction exportInitPanel(which) {\n switch (which) {\n case "file:": // LOCAL EXPORT PANEL: file/path:\n // ** no init - security issues in IE **\n break;\n case "http:": // WEB EXPORT PANEL\n case "https:": // SECURE WEB EXPORT PANEL\n // url\n var siteURL=store.getTiddlerText("SiteUrl");\n if (store.tiddlerExists("unawiki_download")) {\n var theURL=store.getTiddlerText("unawiki_download");\n theURL=theURL.replace(/\s[\s[download\s|/,'').replace(/\s]\s]/,'');\n var title=(store.tiddlerExists("unawiki_host"))?"unawiki_host":"SiteHost";\n var theHost=store.getTiddlerText(title);\n if (!theHost || !theHost.length) theHost=document.location.host;\n if (!theHost || !theHost.length) theHost=title;\n siteURL=which+"//"+theHost+theURL\n }\n if (!siteURL) siteURL="SiteUrl";\n document.getElementById("exportHTTPSiteURL").value=siteURL;;\n // server script/params\n var title=(store.tiddlerExists("unawiki_host"))?"unawiki_host":"SiteHost";\n var theHost=store.getTiddlerText(title);\n if (!theHost || !theHost.length) theHost=document.location.host;\n if (!theHost || !theHost.length) theHost=title;\n // get POST\n var title=(store.tiddlerExists("unawiki_post"))?"unawiki_post":"SitePost";\n var thePost=store.getTiddlerText(title);\n if (!thePost || !thePost.length) thePost="/"+title;\n // get PARAMS\n var title=(store.tiddlerExists("unawiki_params"))?"unawiki_params":"SiteParams";\n var theParams=store.getTiddlerText(title);\n if (!theParams|| !theParams.length) theParams=title;\n var serverURL = which+"//"+theHost+thePost+"?"+theParams;\n document.getElementById("exportHTTPServerURL").value=serverURL;\n break;\n case "ftp:": // FTP EXPORT PANEL\n // host\n var siteHost=store.getTiddlerText("SiteHost");\n if (!siteHost || !siteHost.length) siteHost=document.location.host;\n if (!siteHost || !siteHost.length) siteHost="SiteHost";\n document.getElementById("exportFTPHost").value=siteHost;\n // username\n var siteID=store.getTiddlerText("SiteID");\n if (!siteID || !siteID.length) siteID=config.options.txtUserName;\n document.getElementById("exportFTPID").value=siteID;\n // password\n document.getElementById("exportFTPPW").value="";\n // file/path\n document.getElementById("exportFTPFilename").value="";\n break;\n }\n}\n//}}}\n// //===\n\n// // +++[exportInitFilter()]\n//{{{\nfunction exportInitFilter() {\n // TBD: persistent settings via local cookies\n // start date\n document.getElementById("exportFilterStart").checked=false;\n document.getElementById("exportStartDate").value="";\n // end date\n document.getElementById("exportFilterEnd").checked=false;\n document.getElementById("exportEndDate").value="";\n // tags\n document.getElementById("exportFilterTags").checked=false;\n document.getElementById("exportTags").value="not excludeExport";\n // text\n document.getElementById("exportFilterText").checked=false;\n document.getElementById("exportText").value="";\n // show/hide filter input fields\n exportShowFilterFields();\n}\n//}}}\n// //===\n\n// // +++[exportShowFilterFields(which)]\n//{{{\nfunction exportShowFilterFields(which) {\n var show;\n\n show=document.getElementById('exportFilterStart').checked;\n document.getElementById('exportFilterStartBy').style.display=show?"block":"none";\n document.getElementById('exportStartDate').style.display=show?"block":"none";\n var val=document.getElementById('exportFilterStartBy').value;\n document.getElementById('exportStartDate').value\n =getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);\n if (which && (which.id=='exportFilterStartBy') && (val=='other'))\n document.getElementById('exportStartDate').focus();\n\n show=document.getElementById('exportFilterEnd').checked;\n document.getElementById('exportFilterEndBy').style.display=show?"block":"none";\n document.getElementById('exportEndDate').style.display=show?"block":"none";\n var val=document.getElementById('exportFilterEndBy').value;\n document.getElementById('exportEndDate').value\n =getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);\n if (which && (which.id=='exportFilterEndBy') && (val=='other'))\n document.getElementById('exportEndDate').focus();\n\n show=document.getElementById('exportFilterTags').checked;\n document.getElementById('exportTags').style.display=show?"block":"none";\n\n show=document.getElementById('exportFilterText').checked;\n document.getElementById('exportText').style.display=show?"block":"none";\n}\n//}}}\n// //===\n// //===\n\n// // +++[onClickExportButton(which): control interactions]\n//{{{\nfunction onClickExportButton(which)\n{\n // DEBUG alert(which.id);\n var theList=document.getElementById('exportList'); if (!theList) return;\n var count = 0;\n var total = store.getTiddlers('title').length;\n switch (which.id)\n {\n case 'exportFilter':\n count=filterExportList();\n var panel=document.getElementById('exportFilterPanel');\n if (count==-1) { panel.style.display='block'; break; }\n theList.options[0].text=formatExportListHeader(count,total);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage("filtered "+theList.options[0].text);\n if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }\n break;\n case 'exportStart':\n exportTiddlers();\n break;\n case 'exportHideFilter':\n case 'exportToggleFilter':\n var panel=document.getElementById('exportFilterPanel')\n panel.style.display=(panel.style.display=='block')?'none':'block';\n break;\n case 'exportSelectChanges':\n var lastmod=new Date(document.lastModified);\n for (var t = 0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;\n theList.options[t].selected=(tiddler.modified>lastmod);\n count += (tiddler.modified>lastmod)?1:0;\n }\n theList.options[0].text=formatExportListHeader(count,total);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(theList.options[0].text);\n if (count==0) alert("There are no unsaved changes");\n break;\n case 'exportSelectAll':\n for (var t = 0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count += 1;\n }\n theList.options[0].text=formatExportListHeader(count,count);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(theList.options[0].text);\n break;\n case 'exportSelectOpened':\n for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;\n var tiddlerDisplay = document.getElementById("tiddlerDisplay");\n for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {\n var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);\n for (var i = 0; i < theList.options.length; i++) {\n if (theList.options[i].value!=tiddler) continue;\n theList.options[i].selected=true; count++; break;\n }\n }\n theList.options[0].text=formatExportListHeader(count,total);\n document.getElementById("exportStart").disabled=(count==0);\n clearMessage(); displayMessage(theList.options[0].text);\n if (count==0) alert("There are no tiddlers currently opened");\n break;\n case 'exportListSmaller': // decrease current listbox size\n var min=5;\n theList.size-=(theList.size>min)?1:0;\n break;\n case 'exportListLarger': // increase current listbox size\n var max=(theList.options.length>25)?theList.options.length:25;\n theList.size+=(theList.size<max)?1:0;\n break;\n case 'exportClose':\n document.getElementById('exportPanel').style.display='none';\n break;\n }\n}\n//}}}\n// //===\n\n// // +++[list display]\n//{{{\nfunction formatExportListHeader(count,total)\n{\n var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";\n txt += (count==0)?"none":(count==total)?"all":count;\n txt += " selected for export";\n return txt;\n}\n\nfunction refreshExportList(selectedIndex)\n{\n var theList = document.getElementById("exportList");\n var sort;\n if (!theList) return;\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) sort='modified';\n if (selectedIndex==1) sort='title';\n if (selectedIndex==2) sort='modified';\n if (selectedIndex==3) sort='modifier';\n\n // get the alphasorted list of tiddlers\n var tiddlers = store.getTiddlers('title');\n // unselect headings and count number of tiddlers actually selected\n var count=0;\n for (var i=0; i<theList.options.length; i++) {\n if (theList.options[i].value=="") theList.options[i].selected=false;\n count+=theList.options[i].selected?1:0;\n }\n // disable "export" button if no tiddlers selected\n document.getElementById("exportStart").disabled=(count==0);\n // update listbox heading to show selection count\n if (theList.options.length)\n theList.options[0].text=formatExportListHeader(count,tiddlers.length);\n\n // if a [command] item, reload list... otherwise, no further refresh needed\n if (selectedIndex>3) return;\n\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n // add heading and control items to list\n var i=0;\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n theList.options[i++]=\n new Option(formatExportListHeader(0,tiddlers.length), "",false,false);\n theList.options[i++]=\n new Option(((sort=="title" )?">":indent)+' [by title]', "",false,false);\n theList.options[i++]=\n new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);\n theList.options[i++]=\n new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);\n // output the tiddler list\n switch(sort)\n {\n case "title":\n for(var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modifier":\n case "modified":\n var tiddlers = store.getTiddlers(sort);\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++)\n {\n var tiddler = tiddlers[t];\n var theSection = "";\n if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();\n if (sort=="modifier") theSection=tiddler.modifier;\n if (theSection != lastSection)\n {\n theList.options[i++] = new Option(theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n}\n//}}}\n// //===\n\n// // +++[list filtering]\n//{{{\nfunction getFilterDate(val,id)\n{\n var result=0;\n switch (val) {\n case 'site':\n var timestamp=store.getTiddlerText("SiteDate");\n if (!timestamp) timestamp=document.lastModified;\n result=new Date(timestamp);\n break;\n case 'file':\n result=new Date(document.lastModified);\n break;\n case 'other':\n result=new Date(document.getElementById(id).value);\n break;\n default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31\n var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;\n var oneday=86400000;\n if (id=='exportStartDate')\n result=new Date((Math.floor(now/oneday)-val)*oneday+tz);\n else\n result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);\n break;\n }\n // DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\snnow="+now);\n return result;\n}\n\nfunction filterExportList()\n{\n var theList = document.getElementById("exportList"); if (!theList) return -1;\n\n var filterStart=document.getElementById("exportFilterStart").checked;\n var val=document.getElementById("exportFilterStartBy").value;\n var startDate=getFilterDate(val,'exportStartDate');\n\n var filterEnd=document.getElementById("exportFilterEnd").checked;\n var val=document.getElementById("exportFilterEndBy").value;\n var endDate=getFilterDate(val,'exportEndDate');\n\n var filterTags=document.getElementById("exportFilterTags").checked;\n var tags=document.getElementById("exportTags").value;\n\n var filterText=document.getElementById("exportFilterText").checked;\n var text=document.getElementById("exportText").value;\n\n if (!(filterStart||filterEnd||filterTags||filterText)) {\n alert("Please set the selection filter");\n document.getElementById('exportFilterPanel').style.display="block";\n return -1;\n }\n if (filterStart&&filterEnd&&(startDate>endDate)) {\n var msg="starting date/time:\sn"\n msg+=startDate.toLocaleString()+"\sn";\n msg+="is later than ending date/time:\sn"\n msg+=endDate.toLocaleString()\n alert(msg);\n return -1;\n }\n\n // scan list and select tiddlers that match all applicable criteria\n var total=0;\n var count=0;\n for (var i=0; i<theList.options.length; i++) {\n // get item, skip non-tiddler list items (section headings)\n var opt=theList.options[i]; if (opt.value=="") continue;\n // get tiddler, skip missing tiddlers (this should NOT happen)\n var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; \n var sel=true;\n if ( (filterStart && tiddler.modified<startDate)\n || (filterEnd && tiddler.modified>endDate)\n || (filterTags && !matchTags(tiddler,tags))\n || (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))\n sel=false;\n opt.selected=sel;\n count+=sel?1:0;\n total++;\n }\n return count;\n}\n//}}}\n\n//{{{\nfunction matchTags(tiddler,cond)\n{\n if (!cond||!cond.trim().length) return false;\n\n // build a regex of all tags as a big-old regex that \n // OR's the tags together (tag1|tag2|tag3...) in length order\n var tgs = store.getTags();\n if ( tgs.length == 0 ) return results ;\n var tags = tgs.sort( function(a,b){return (a[0].length<b[0].length)-(a[0].length>b[0].length);});\n var exp = "(" + tags.join("|") + ")" ;\n exp = exp.replace( /(,[\sd]+)/g, "" ) ;\n var regex = new RegExp( exp, "ig" );\n\n // build a string such that an expression that looks like this: tag1 AND tag2 OR NOT tag3\n // turns into : /tag1/.test(...) && /tag2/.test(...) || ! /tag2/.test(...)\n cond = cond.replace( regex, "/$1\s\s|/.test(tiddlerTags)" );\n cond = cond.replace( /\ssand\ss/ig, " && " ) ;\n cond = cond.replace( /\ssor\ss/ig, " || " ) ;\n cond = cond.replace( /\ss?not\ss/ig, " ! " ) ;\n\n // if a boolean uses a tag that doesn't exist - it will get left alone \n // (we only turn existing tags into actual tests).\n // replace anything that wasn't found as a tag, AND, OR, or NOT with the string "false"\n // if the tag doesn't exist then /tag/.test(...) will always return false.\n cond = cond.replace( /(\ss|^)+[^\s/\s|&!][^\ss]*/g, "false" ) ;\n\n // make a string of the tags in the tiddler and eval the 'cond' string against that string \n // if it's TRUE then the tiddler qualifies!\n var tiddlerTags = (tiddler.tags?tiddler.tags.join("|"):"")+"|" ;\n try { if ( eval( cond ) ) return true; }\n catch( e ) { displayMessage("Error in tag filter '" + e + "'" ); }\n return false;\n}\n//}}}\n// //===\n\n// // +++[output data formatting]>\n// // +++[exportHeader(format)]\n//{{{\nfunction exportHeader(format)\n{\n switch (format) {\n case "TW": return exportTWHeader();\n case "DIV": return exportDIVHeader();\n case "XML": return exportXMLHeader();\n }\n}\n//}}}\n// //===\n\n// // +++[exportFooter(format)]\n//{{{\nfunction exportFooter(format)\n{\n switch (format) {\n case "TW": return exportDIVFooter();\n case "DIV": return exportDIVFooter();\n case "XML": return exportXMLFooter();\n }\n}\n//}}}\n// //===\n\n// // +++[exportTWHeader()]\n//{{{\nfunction exportTWHeader()\n{\n // Get the URL of the document\n var originalPath = document.location.toString();\n // Check we were loaded from a file URL\n if(originalPath.substr(0,5) != "file:")\n { alert(config.messages.notFileUrlError); return; }\n // Remove any location part of the URL\n var hashPos = originalPath.indexOf("#"); if(hashPos != -1) originalPath = originalPath.substr(0,hashPos);\n // Convert to a native file format assuming\n // "file:///x:/path/path/path..." - pc local file --> "x:\spath\spath\spath..."\n // "file://///server/share/path/path/path..." - FireFox pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n // "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."\n // "file://server/share/path/path/path..." - pc network file --> "\s\sserver\sshare\spath\spath\spath..."\n var localPath;\n if(originalPath.charAt(9) == ":") // pc local file\n localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file://///") == 0) // FireFox pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\s\s");\n else if(originalPath.indexOf("file:///") == 0) // mac/unix local file\n localPath = unescape(originalPath.substr(7));\n else if(originalPath.indexOf("file:/") == 0) // mac/unix local file\n localPath = unescape(originalPath.substr(5));\n else // pc network file\n localPath = "\s\s\s\s" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\s\s");\n // Load the original file\n var original = loadFile(localPath);\n if(original == null)\n { alert(config.messages.cantSaveError); return; }\n // Locate the storeArea div's\n var posOpeningDiv = original.indexOf(startSaveArea);\n var posClosingDiv = original.lastIndexOf(endSaveArea);\n if((posOpeningDiv == -1) || (posClosingDiv == -1))\n { alert(config.messages.invalidFileError.format([localPath])); return; }\n return original.substr(0,posOpeningDiv+startSaveArea.length)\n}\n//}}}\n// //===\n\n// // +++[exportDIVHeader()]\n//{{{\nfunction exportDIVHeader()\n{\n var out=[];\n var now = new Date();\n var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());\n var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());\n var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());\n var twver = version.major+"."+version.minor+"."+version.revision;\n var pver = version.extensions.exportTiddlers.major+"."\n +version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;\n out.push("<html><body>");\n out.push("<style type=\s"text/css\s">");\n out.push("#storeArea {display:block;margin:1em;}");\n out.push("#storeArea div");\n out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");\n out.push("#javascriptWarning");\n out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");\n out.push("</style>");\n out.push("<div id=\s"javascriptWarning\s">");\n out.push("TiddlyWiki export file<br>");\n out.push("Source: <b>"+convertUnicodeToUTF8(document.location.toString())+"</b><br>");\n out.push("Title: <b>"+title+"</b><br>");\n out.push("Subtitle: <b>"+subtitle+"</b><br>");\n out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");\n out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");\n out.push("</div>");\n out.push("<div id=\s"storeArea\s">");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportDIVFooter()]\n//{{{\nfunction exportDIVFooter()\n{\n var out=[];\n out.push("</div></body></html>");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportXMLHeader()]\n//{{{\nfunction exportXMLHeader()\n{\n var out=[];\n var now = new Date();\n var u = store.getTiddlerText("SiteUrl",null);\n var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());\n var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());\n var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());\n var twver = version.major+"."+version.minor+"."+version.revision;\n var pver = version.extensions.exportTiddlers.major+"."\n +version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;\n out.push("<" + "?xml version=\s"1.0\s"?" + ">");\n out.push("<rss version=\s"2.0\s">");\n out.push("<channel>");\n out.push("<title>" + title + "</title>");\n if(u) out.push("<link>" + convertUnicodeToUTF8(u.htmlEncode()) + "</link>");\n out.push("<description>" + subtitle + "</description>");\n out.push("<language>en-us</language>");\n out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");\n out.push("<pubDate>" + now.toGMTString() + "</pubDate>");\n out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");\n out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");\n out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportXMLFooter()]\n//{{{\nfunction exportXMLFooter()\n{\n var out=[];\n out.push("</channel></rss>");\n return out;\n}\n//}}}\n// //===\n\n// // +++[exportData()]\n//{{{\nfunction exportData(theList,theFormat)\n{\n // scan export listbox and collect DIVs or XML for selected tiddler content\n var out=[];\n for (var i=0; i<theList.options.length; i++) {\n // get item, skip non-selected items and section headings\n var opt=theList.options[i]; if (!opt.selected||(opt.value=="")) continue;\n // get tiddler, skip missing tiddlers (this should NOT happen)\n var thisTiddler=store.getTiddler(opt.value); if (!thisTiddler) continue; \n if (theFormat=="TW") out.push(convertUnicodeToUTF8(thisTiddler.saveToDiv()));\n if (theFormat=="DIV") out.push(convertUnicodeToUTF8(thisTiddler.title+"\sn"+thisTiddler.saveToDiv()));\n if (theFormat=="XML") out.push(convertUnicodeToUTF8(thisTiddler.saveToRss()));\n }\n return out;\n}\n//}}}\n// //===\n// //===\n\n// // +++[exportTiddlers(): output selected data to local or server]\n//{{{\nfunction exportTiddlers()\n{\n var theList = document.getElementById("exportList"); if (!theList) return;\n\n // get the export settings\n var theProtocol = document.getElementById("exportTo").value;\n var theFormat = document.getElementById("exportFormat").value;\n\n // assemble output: header + tiddlers + footer\n var theData=exportData(theList,theFormat);\n var count=theData.length;\n var out=[]; var txt=out.concat(exportHeader(theFormat),theData,exportFooter(theFormat)).join("\sn");\n var msg="";\n switch (theProtocol) {\n case "file:":\n var theTarget = document.getElementById("exportFilename").value.trim();\n if (!theTarget.length) msg = "A local path/filename is required\sn";\n if (!msg && saveFile(theTarget,txt))\n msg=count+" tiddler"+((count!=1)?"s":"")+" exported to local file";\n else if (!msg)\n msg+="An error occurred while saving to "+theTarget;\n break;\n case "http:":\n case "https:":\n var theTarget = document.getElementById("exportHTTPServerURL").value.trim();\n if (!theTarget.length) msg = "A server URL is required\sn";\n if (!msg && exportPost(theTarget+encodeURIComponent(txt)))\n msg=count+" tiddler"+((count!=1)?"s":"")+" exported to "+theProtocol+" server";\n else if (!msg)\n msg+="An error occurred while saving to "+theTarget;\n break;\n case "ftp:":\n default:\n msg="Sorry, export to "+theLocation+" is not yet available";\n break;\n }\n clearMessage(); displayMessage(msg,theTarget);\n}\n//}}}\n// //===\n\n// // +++[exportPost(url): cross-domain post] uses hidden iframe to submit url and capture responses\n//{{{\nfunction exportPost(url)\n{\n var f=document.getElementById("exportFrame"); if (f) document.body.removeChild(f);\n f=document.createElement("iframe"); f.id="exportFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\n var d=f.document;\n if (f.contentDocument) d=f.contentDocument; // For NS6\n else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6\n d.location.replace(url);\n return true;\n}\n//}}}\n// //===\n
<html>\nPer l'utilizzo della memoria SD, la scelta del Filesystem è inevitabilmente ricaduta su uno di tipo FAT; in questo modo è possibile\ncaricare i file direttamente da pc.<br />\nNel file <em>fat16.c</em> è implementato il supporto a FAT16, realizzando la stessa interfaccia di MPFS, in modo tale da essere compatibile con esso (per ora in sola lettura).\nCiò significa che i metodi di questo file hanno lo stesso nome, parametri e comportamento di quelli presenti nel file <em>MPFS.c</em>.<br />\n<br />\nPer meglio comprendere il funzionamento del codice, vediamo com'è organizzata una generica memoria di massa.<br />\nInannzitutto, la memoria è divisa in <em>settori</em> solitamente costituiti da 512byte; più settori insieme formano\nun <em>cluster</em>, la cui dimensione viene stabilita durante la creazione della partizione, e scritta in un apposito campo del Filesystem.\nIl <em>cluster</em> è l'unità di base della FAT16, ad esempio un file di dimensione nulla, occupa comunque un intero cluster.<br />\nIl primo settore è denominato <em>MBR</em> (Master Boot Record), e contiene principalmente codice eseguibile per il lancio del sistema operativo.\nIl nostro interesse, però, ricade su una piccola porzione di questo settore, ovvero la <em>Partition Table</em>, nella quale troviamo informazioni sulle partizioni.\nIn particolare, da un campo di tale tabella si può ricavare la locazione d'inizio della partizione, e quindi del Filesystem.\n<table class="simple_table" style="width:500px">\n <tr>\n <td><b>Offset</b></td>\n <td><b>Descrizione</b></td>\n <td><b>Dimensione</b></td>\n </tr>\n\n <tr>\n <td>0x000</td>\n <td>Codice eseguibile</td>\n <td>446 Byte</td>\n </tr>\n <tr>\n <td>0x1BE</td>\n <td>Informazioni sulla Prima Partizione</td>\n <td>16 Byte</td>\n </tr>\n <tr>\n <td>0x1CE</td>\n <td>Informazioni sulla Seconda Partizione</td>\n <td>16 Byte</td>\n </tr>\n <tr>\n <td>0x1DE</td>\n <td>Informazioni sulla Terza Partizione</td>\n <td>16 Byte</td>\n </tr>\n <tr>\n <td>0x1EE</td>\n <td>Informazioni sulla Quarta Partizione</td>\n <td>16 Byte</td>\n </tr>\n <tr>\n <td>0x1FE</td>\n <td>Firma Boot Sector: sempre 0x55AA</td>\n <td>2 Byte</td>\n </tr>\n</table>\n<br />\nTali informazioni sulle partizioni sono così formate:\n<table class="simple_table" style="width:500px">\n <tr>\n <td><b>Offset</b></td>\n <td><b>Descrizione</b></td>\n <td><b>Dimensione</b></td>\n </tr>\n <tr>\n <td>0x00</td>\n <td>Stato della partizione (attivo o inattivo)</td>\n <td>1 Byte</td>\n </tr>\n <tr>\n <td>0x01</td>\n <td>Inizio partizione: Head</td>\n <td>1 Byte</td>\n </tr>\n <tr>\n <td>0x02</td>\n <td>Inizio partizione: Cylinder/Sector </td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x04</td>\n <td>Tipo della partizione</td>\n <td>1 Byte</td>\n </tr>\n <tr>\n <td>0x05</td>\n <td>Fine partizione: Head</td>\n <td>1 Byte</td>\n </tr>\n <tr>\n <td>0x06</td>\n <td>Fine partizione: Cylinder/Sector</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td><b>0x08</b></td>\n <td><b>Inizio della partizione in settori</b></td>\n <td><b>4 Byte</b></td>\n </tr>\n <tr>\n <td>0x0C</td>\n <td>Numero di settori nella partizione</td>\n <td>4 Byte</td>\n </tr>\n</table>\nQuindi il campo che vogliamo leggere è il byte 0x1C6 del primo settore.<br />\n<br />\nA questo punto possiamo leggere il primo settore della FAT16 (detto <em>Boot Record</em>), nel quale troviamo\nnumerose informazioni che devono essere salvate in alcune varibili.\n<table class="simple_table" style="width:500px">\n <tr>\n <td><b>Offset</b></td>\n <td><b>Descrizione</b></td>\n <td><b>Dimensione</b></td>\n </tr>\n <tr>\n <td>0x000</td>\n <td>Jump Code e NOP</td>\n <td>3 Byte</td>\n </tr>\n <tr>\n <td>0x003</td>\n <td>Nome OEM</td>\n <td>8 Byte</td>\n </tr>\n <tr>\n <td>0x00B</td>\n <td>Byte Per Settore</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td><em>0x00D</em></td>\n <td><em>Settori Per Cluster</em></td>\n <td><em>1 Byte</em></td>\n </tr>\n <tr>\n <td><em>0x00E</em></td>\n <td><em>Settori Riservati</em></td>\n <td><em>2 Byte</em></td>\n </tr>\n <tr>\n <td><em>0x010</em></td>\n <td><em>Numero di Aree FAT</em></td>\n <td><em>1 Byte</em></td>\n </tr>\n <tr>\n <td><em>0x011</em></td>\n <td><em>Numero massimo di elementi nella Root Directory</em></td>\n <td><em>2 Byte</em></td>\n </tr>\n <tr>\n <td>0x013</td>\n <td>Numero di settori in partizioni < 32MB</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x015</td>\n <td>Tipo di supporto (HardDisk, ecc.)</td>\n <td>1 Byte</td>\n </tr>\n <tr>\n <td><em>0x016</em></td>\n <td><em>Dimensioni in settori della FAT Area</em></td>\n <td><em>2 Byte</em></td>\n </tr>\n <tr>\n <td>0x018</td>\n <td>Settori per Traccia</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x01A</td>\n <td>Numero di Head</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x01C</td>\n <td>Numero di settori nascosti</td>\n <td>4 Byte</td>\n </tr>\n <tr>\n <td>0x020</td>\n <td>Dimensione in settori della partizione</td>\n <td>4 Byte</td>\n </tr>\n <tr>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <td>0x1FE</td>\n <td>Firma Boot Sector: sempre 0x55AA</td>\n <td>2 Byte</td>\n </tr>\n</table>\n<br />\nUno sguardo d'insieme del Filesystem (non in proporzione):\n<div class="center"><img src="http://www.itentropy.it/images/tutorials/fat.gif" alt="" /></div>\nAbbiamo già visto il MBR e il FBR, mentre per quando riguarda le altre zone:\n<ul>\n <li><em>FAT (File Allocation Table)</em>: nel Filesystem FAT16, come in molti altri, i cluster che formano un file\n non sono necessariamente contigui, ma sono spesso frammentati (cioè sparsi dove capita nel disco); per questo motivo esiste\n l'area denominata FAT, la quale contiene liste concatenate che permettono di rimettere in ordine i cluster di un singolo file.</li>\n <li><em>FAT2</em>: è semplicemente una copia di sicurezza della FAT.</li>\n <li><em>Root Directory</em>: contiene l'elenco dei file contenuti nella directory radice del disco.</li>\n <li><em>Data Area</em>: qui è dove si trovano i file.</li>\n</ul>\n<br />\nNel Filesystem MPFS i file sono contigui, quindi per semplificare il codice, nello stack Microchip un file è indentificato\ndal suo indirizzo nella memoria (ma viene chiamato <em>handle</em>). Nel caso della FAT16, però, tale informazione non è\nsufficiente, o meglio, richiederebbe di effettuare diversi calcoli ogni volta che si deve eseguire una lettura dalla memoria;\nper tale motivo, è presente una tabella (denominata <em>handleTable</em>) contenente alcune informazioni. La define <em>MAX_OPENED_FILES</em>\ndetermina la dimensione massima della tabella.\n<pre class="code">\ntypedef struct {\n BYTE attrib;\n WORD cluster; // cluster in DataArea\n BYTE sector; // sector in cluster\n WORD byte; // byte in sector;\n DWORD filesize;\n} handleEntry;\n\nhandleEntry handleTable[MAX_OPENED_FILES];</pre>\n<br />\nGiunti qui, possiamo vedere l'inizializzazione del driver FAT16:\n<pre class="code">/* partition data */\nDWORD partitionStart; \nBYTE clusterSize; // sectors per cluster\nDWORD fatStart;\nDWORD rootStart;\nDWORD dataArea;\nBYTE rootSize;\n\nBOOL FATInit() {\n char* buf_pt = &sd_buffer[0];\n char i;\n\n sdPresent = SDInit();\n\n if (!sdPresent)\n return FALSE;\n\n SDReadSector(0);\n partitionStart = *(DWORD*)(buf_pt+0x1C6);\n\n SDReadSector(partitionStart);\n clusterSize = buf_pt[0x0D]; \n fatStart = partitionStart + *(WORD*)(buf_pt+0x0E);\n rootStart = fatStart + (*(WORD*)(buf_pt+0x16)) * buf_pt[0x10];\n rootSize = *(WORD*)(buf_pt+0x11) * sizeof(dirEntry) / SECTOR_SIZE;\n dataArea = rootStart + rootSize;\n\n for (i = 0; i < MAX_OPENED_FILES; i++)\n handleTable[i].attrib = FREE_HANDLE;\n\n mpfsOpenCount = 0;\n\n return TRUE;\n}</pre>\nOltre ad inizializzare la memoria SD e la tabella degli Handle, vengono calcolati alcuni indirizzi caratteristici del Filesystem:\n<table class="simple_table" style="width:700px">\n <tr>\n <td><b>Variabile</b></td>\n <td><b>Descrizione</b></td>\n <td><b>Valore</b></td>\n </tr>\n <tr>\n <td>clusterSize</td>\n <td>Numero di settori in un cluster</td>\n <td> </td>\n </tr>\n <tr>\n <td>fatStart</td>\n <td>Inizio della FAT1</td>\n <td>inzio della partizione + settori riservati</td>\n </tr>\n <tr>\n <td>rootStart</td>\n <td>Inizio della Root Directory</td>\n <td>Indirizzo della FAT + (numero di FAT per dimensione di una FAT)</td>\n </tr>\n <tr>\n <td>rootSize</td>\n <td>Dimensione della Root Directory</td>\n <td>Numero di elementi nella directory per dimensione di un elemento</td>\n </tr>\n <tr>\n <td>dataArea</td>\n <td>Inizio dell'Area Dati</td>\n <td>Inizio della Root Directory + la sua dimensione</td>\n </tr>\n</table>\nQuesti indirizzi e dimensioni sono espressi in settori di 512byte. <br />\n<br />\nUna directory è costituita da elementi della stessa dimensione (32 byte)\nche, per quanto concerne i file con nomi corti (8+3), contengono questi campi:\n<table class="simple_table" style="width:500px">\n <tr>\n <td><b>Offset</b></td>\n <td><b>Descrizione</b></td>\n <td><b>Dimensione</b></td>\n </tr>\n <tr>\n <td>0x00</td>\n <td>Nome</td>\n <td>8 Byte</td>\n </tr>\n <tr>\n <td>0x08</td>\n <td>Estensione </td>\n <td>3 Byte</td>\n </tr>\n <tr>\n <td>0x0B </td>\n <td>Attributi</td>\n <td>1 Byte </td>\n </tr>\n <tr>\n <td>0x0C </td>\n <td>Riservato</td>\n <td>1 Byte </td>\n </tr>\n <tr>\n <td>0x0D </td>\n <td>Data e ora della creazione</td>\n <td>7 Byte </td>\n </tr>\n <tr>\n <td>0x14 </td>\n <td>Attributi Estesi</td>\n <td>2 Byte </td>\n </tr>\n <tr>\n <td>0x16</td>\n <td>Ora</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x18</td>\n <td>Data</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x20</td>\n <td>Primo cluster del File</td>\n <td>2 Byte</td>\n </tr>\n <tr>\n <td>0x1C</td>\n <td>Dimensione del File</td>\n <td>4 Byte</td>\n </tr>\n</table>\nIn particolare i campi <em>Nome</em> ed <em>Estensione</em> sono sempre scritti in maiscuolo, ed i caratteri non presenti\nsono riempiti con il carattere spazio (0x20 in esadecimale). Ad esempio il file <em>Pippo.txt</em> sarà scritto nella forma\n<pre class="code">PIPPO TXT 50 49 50 50 4F 20 20 20 54 58 54</pre>\n<br />\nIl metodo <em>MPFSOpen</em> cerca un file nella memoria, e se lo trova crea un handle e lo restituisce al chiamante:\n<pre class="code">MPFS MPFSOpen(BYTE* name){\n BYTE scount, ecount;\n dirEntry* entry;\n char* buf_pt = &sd_buffer[0];\n char i;\n char name_ext[11];\n\n if (!sdPresent) return MPFS_INVALID;\n\n for (i=0; i<11; i++)\n name_ext[i] = 0x20;\n \n for (i=0; i<8 && *name!='.' && *name; i++)\n name_ext[i] = toupper(*name++);\n\n if (*name == '.') {\n name++;\n for (i=8; i<11 && *name; i++)\n name_ext[i] = toupper(*name++);\n }\n\n scount = 0;\n while (scount < rootSize) {\n SDReadSector(rootStart + scount);\n\n ecount = 16;\n entry = (dirEntry*)buf_pt;\n while (ecount--) {\n if (entry->attrib == 0x0F) goto next; // Long File Name\n if (entry->name_ext[0] == 0x00 || entry->name_ext[0] == 0xE5) goto next; // Empty Entry\n if (memcmp((void*)name_ext, (void*)entry->name_ext, 11) == 0) { // found!\n for (i=0; i < MAX_OPENED_FILES && handleTable[i].attrib!=FREE_HANDLE; i++);\n if (i == MAX_OPENED_FILES) return MPFS_NOT_AVAILABLE;\n handleTable[i].attrib = USED_HANDLE;\n handleTable[i].cluster = entry->cluster;\n handleTable[i].filesize = entry->size; \n handleTable[i].sector = 0; \n handleTable[i].byte = 0;\n mpfsOpenCount++;\n return i;\n }\n next:\n entry++;\n }\n\n scount++;\n }\n\n return MPFS_INVALID;\n}</pre>\nNella prima parte, il nome del file viene scritto nella forma 8+3 vista in precedenza. In questo modo sarà\npossibile confrontarlo con quelli presenti nella Root Directory. A questo punto vengono lette tutte le <em>entry</em> (elementi)\ndella Directory, partendo dal primo settore ed eventualmente leggendo i settori successivi.<br />\nQuando il confronto tra il nome del file cercato e quello letto dalla memoria ha esito positivo, viene cercato un handle libero\nnella tabella, quindi vengono salvati alcuni dati:\n<ul>\n <li><em>filesize</em>: la dimensione del file in byte.</li>\n <li><em>cluster</em>: il primo cluster del file nella Data Area.</li>\n <li><em>sector</em>: inizializzato a zero perchè tiene traccia di quale settore stiamo leggendo all'interno dello stesso cluster</li>\n <li><em>byte</em>: analogamente a <em>sector</em>, tiene traccia dell'ultimo byte letto all'interno del settore.</li>\n</ul>\n<br />\nCon <em>MPFSGetBegin</em> il driver si prepara a leggere il file aperto con <em>MPFSOpen</em>, caricando nel buffer il settore\ndel file puntato dalle varibili salvate nella tabella:\n<pre class="code">BOOL MPFSGetBegin(MPFS handle){\n if (handle >= MAX_OPENED_FILES || handleTable[handle].attrib != USED_HANDLE)\n return FALSE; // invalid handle\n\n if (handleTable[handle].filesize == 0)\n return TRUE;\n\n _currentHandle = handle;\n SDReadSector(dataArea + (handleTable[handle].cluster-2)*clusterSize + handleTable[handle].sector);\n\n return TRUE;\n}</pre>\nDa notare che i cluster iniziano da 2 e non da zero, inoltre il numero di cluster non è un indirizzo assoluto rispetto all'intera memoria\nma è relativo alla Data Area, quindi all'indirizzo da caricare va sommato l'indirizzo della Data Area.<br />\n<br />\nLa funzione <em>MPFSGet</em> legge e restituisce un byte del file alla volta. Se tale byte si trova caricato nel buffer\ndella memoria SD, è sufficiente leggerlo da lì, altrimenti bisogna calcolare il prossimo settore da caricare. Quest'ultimo\nse si trova all'interno dello stesso cluster sarà semplicemente il successivo, altrimenti è necessario leggere la FAT per individuare il prossimo cluster.\n<pre class="code">BYTE MPFSGet() {\n char* buf_pt = &sd_buffer[0];\n BYTE b = 0;\n WORD tmp;\n\n if (_currentHandle == MPFS_INVALID)\n return 0;\n\n if (handleTable[_currentHandle].byte >= SECTOR_SIZE) {\n handleTable[_currentHandle].byte = 0;\n handleTable[_currentHandle].sector++;\n if (handleTable[_currentHandle].sector >= clusterSize) {\n tmp = handleTable[_currentHandle].cluster;\n SDReadSector(fatStart + tmp / (SECTOR_SIZE /2) ); // read FAT Area\n handleTable[_currentHandle].cluster = *(WORD*)(buf_pt + (tmp % (SECTOR_SIZE/2)) * 2); // next cluster in chain\n handleTable[_currentHandle].sector = 0;\n }\n SDReadSector(dataArea + (handleTable[_currentHandle].cluster-2)*clusterSize + handleTable[_currentHandle].sector);\n }\n\n\n b = buf_pt[handleTable[_currentHandle].byte++];\n handleTable[_currentHandle].filesize--;\n\n return b;\n}</pre>\nNella FAT, ad ogni parola di 16 bit corrisponde un cluster. Per fare un esempio, se stiamo leggendo il file che inizia al cluster 4 (cioè il 5°),\nper conoscere il prossimo cluster del file, sarà sufficiente leggere la parola corrispondente nella FAT, ovvero la 5°. L'ultima parola di una catena\nè 0xFFFF.<br />\nEssendo le parole di 16bit, in un settore della FAT sono presenti 256 elementi; perciò per sapere quale settore della FAT è necessario\ncaricare viene eseguito questo calcolo:\n<pre class="code">cluster_corrente / (SECTOR_SIZE /2)</pre>\nA questo punto, possiamo conoscere il prossimo cluster leggendo la parola numero\n<pre class="code">(cluster_corrente % (SECTOR_SIZE/2)) * 2</pre>\nall'interno di tale settore.<br />\n<br />\nAltri metodi:\n<pre class="code">\nvoid MPFSClose() {\n mpfsOpenCount--; // decrementa il numero di file aperti\n handleTable[_currentHandle].attrib = FREE_HANDLE; // libera l'handle\n}\n\nBOOL MPFSIsEOF(void) {\n return (handleTable[_currentHandle].filesize == -1); // se la dimensione è -1, il file è finito\n}</pre>\n</html>
[img[FTPmicro|ftpmicro.jpg][ftpmicroH.jpg]] [img[FTPmicro_back|ftpmicro_back.jpg][ftpmicro_backH.jpg]]
config.fontSize={};\n\n//configuration settings\nconfig.fontSize.settings =\n{\n defaultSize : 100, // all sizes in %\n maxSize : 200,\n minSize : 40,\n stepSize : 10\n};\n\n//startup code\nvar fontSettings = config.fontSize.settings;\n\nif (!config.options.txtFontSize)\n {config.options.txtFontSize = fontSettings.defaultSize;\n saveOptionCookie("txtFontSize");}\nsetStylesheet(".tiddler .viewer {font-size:"+config.options.txtFontSize+"%;}\sn","fontResizerStyles");\nsetStylesheet("#contentWrapper .fontResizer .button {display:inline;font-size:105%; font-weight:bold; margin:0 1px; padding: 0 3px; text-align:center !important;}\sn .fontResizer {margin:0 0.5em;}","fontResizerButtonStyles");\n\n//macro\nconfig.macros.fontSize={};\nconfig.macros.fontSize.handler = function (place,macroName,params,wikifier,paramString,tiddler)\n{\n\n var sp = createTiddlyElement(place,"span",null,"fontResizer");\n sp.ondblclick=this.onDblClick;\n if (params[0])\n createTiddlyText(sp,params[0]);\n createTiddlyButton(sp,"+","ingrandisci caratteri",this.incFont);\n createTiddlyButton(sp,"=","reset caratteri",this.resetFont);\n createTiddlyButton(sp,"–","diminuisci caratteri",this.decFont);\n}\n\nconfig.macros.fontSize.onDblClick = function (e)\n{\n if (!e) var e = window.event;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return false;\n}\n\nconfig.macros.fontSize.setFont = function ()\n{\n saveOptionCookie("txtFontSize");\n setStylesheet(".tiddler .viewer {font-size:"+config.options.txtFontSize+"%;}\sn","fontResizerStyles");\n}\n\nconfig.macros.fontSize.incFont=function()\n{\n if (config.options.txtFontSize < fontSettings.maxSize)\n config.options.txtFontSize = (config.options.txtFontSize*1)+fontSettings.stepSize;\n config.macros.fontSize.setFont();\n}\n\nconfig.macros.fontSize.decFont=function()\n{\n\n if (config.options.txtFontSize > fontSettings.minSize)\n config.options.txtFontSize = (config.options.txtFontSize*1) - fontSettings.stepSize;\n config.macros.fontSize.setFont();\n}\n\nconfig.macros.fontSize.resetFont=function()\n{\n\n config.options.txtFontSize=fontSettings.defaultSize;\n config.macros.fontSize.setFont();\n}\n\nconfig.paramifiers.font =\n{\n onstart: function(v)\n {\n config.options.txtFontSize = v;\n config.macros.fontSize.setFont();\n }\n};
esempio di ftp client
[img[ICD2|icd2.jpg][icd2_h.jpg]]
<html>\nGrazie al server HTTP, è possibile comunicare con la scheda semplicemente con un web-browser, da qualunque sistema operativo. <br />\nIl server è in grado di prelevare un file direttamente dalla memoria SD ed inviarlo a destinazione.\nInoltre una richiesta può interagire con il software (e quindi con l'hardware) essenzialmente in due modi: in "lettura", richiedendo\ndati tramite una pagina CGI, ed in "scrittura" ovvero inviando dei comandi.<br />\nUna pagina CGI (Common Gateway Interface) non è altro che una pagina html, che però può contenere il carattere di escape % seguito da un\nnumero decimale a due cifre; tale numero identifica una variabile che sarà richiesta al programma.<br />\nIn particolare viene invocata la funzione <em>HTTPGetVar</em> che si trova nel file MainDemo.c:\n<pre class="code">WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val)</pre>\nil primo parametro identifica la varibile di cui si richiede il valore; il secondo è un indice, utilizzato per varibili composte da più byte;\nl'ultimo parametro punta alla locazione dove scriveremo il valore della variabile (più precisamente scriveremo il byte ref-esimo).<br />\nIl valore di ritorno sarà <em>HTTP_END_OF_VAR</em> se abbiamo inviato tutti i byte della varibile <em>var</em>, altrimenti\nsarà l'indice del prossimo byte da inviare, ovvero ref+1.<br />\n<br />\nVediamo un breve esempio:\n<pre class="code"><b>Variabile 1</b>: %01 <br>\n<b>Varibile 2</b>: <em>%02</em></pre>\nIn questo file CGI sono presenti due variabili, quindi verrà chiamata <em>HTTPGetVar</em>, con var pari a 1, la\nquale restituirà attraverso <em>val</em>, ad esempio il carattere 'A'. Successivamente viene richiamata <em>HTTPGetVar</em>, ma\ncon var uguale a 2; stavolta supponiamo che il dato sia una stringa, perciò tale funzione verrà chiamata più volte\nfin quando non si giungerà al termine della stringa (ad esempio "Ciao").<br />\nA questo punto il server può inviare la risposta a chi ha richiesto la pagina, che riceverà:\n<pre class="code"><b>Variabile 1</b>: A <br>\n<b>Varibile 2</b>: <em>Ciao</em></pre>\n<br />\nSe alla pagina richiesta aggiungiamo dei parametri sarà possibile far eseguire delle azioni al software.\nUna richiesta con parametri ha questo aspetto:\n<pre class="code">http://10.0.0.6/pagina.htm?param1=val1¶m2=val2</pre>\nTale richiesta viene automaticamente analizzata dal server HTTP e passata al metodo <em>HTTPExecCmd</em>, sottoforma di array di stringhe.<br />\nIl metodo <em>HTTPExecCmd</em> è così definito:\n<pre class="code">void HTTPExecCmd(BYTE** argv, BYTE argc)</pre>\nQuindi nell'esempio fatto prima, <em>argv</em> sarà:\n<pre class="code">argv[0] = pagina.htm\nargv[1] = param1\nargv[2] = val1\nargv[3] = param2\nargv[4] = val2</pre>\nmentre <em>argc</em> (numero di elementi) varrà 5. In questo modo, scrivendo del codice opportuno all'interno di tale metodo,\nil PIC può eseguire diverse funzioni a seconda dei parametri ricevuti. <br />\nInoltre al termine del metodo, <em>argv[0]</em> deve contenere il nome della pagina da restituire, che può essere quella richiesta (ad es. <em>pagina.htm</em>) oppure un'altra.<br />\n\n</html>
<<importTiddlers inline>>
/***\n''Import Tiddlers Plugin for TiddlyWiki version 1.2.x, 2.0 and 2.1beta''\n^^author: Eric Shulman - ELS Design Studios\nsource: http://www.TiddlyTools.com/#ImportTiddlersPlugin\nlicense: [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]^^\n\nWhen many people share and edit copies of the same TiddlyWiki document, the ability to quickly collect all these changes back into a single, updated document that can then be redistributed to the entire group is very important. This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents. It can also be very useful when moving your own tiddlers from document to document (e.g., when upgrading to the latest version of TiddlyWiki, or 'pre-loading' your favorite stylesheets into a new 'empty' TiddlyWiki document.)\n\n!!!!!Interactive interface\n<<<\n{{{<<importTiddlers>>}}}\ncreates "import tiddlers" link. click to show/hide import control panel\n\n{{{<<importTiddlers inline>>}}}\ncreates import control panel directly in tiddler content\n\n<<importTiddlers inline>>\n\nPress ''[browse]'' to select a TiddlyWiki document file to import. You can also type in the path/filename or a remote document URL (starting with http://)and press ''[open]''. //Note: There may be some delay to permit the browser time to access and load the document before updating the listbox with the titles of all tiddlers that are available to be imported.//\n\nSelect one or more titles from the listbox (hold CTRL or SHIFT while clicking to add/remove the highlight from individual list items). You can press ''[select all]'' to quickly highlight all tiddler titles in the list. Use the ''[-]'', ''[+]'', or ''[=]'' links to adjust the listbox size so you can view more (or less) tiddler titles at one time. When you have chosen the tiddlers you want to import and entered any extra tags, press ''[import]'' to begin copying them to the current TiddlyWiki document.\n\n''select: all, new, changes, or differences''\n\nYou can click on ''all'', ''new'', ''changes'', or ''differences'' to automatically select a subset of tiddlers from the list. This makes it very quick and easy to find and import just the updated tiddlers you are interested in:\n>''"all"'' selects ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' selects only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' selects only tiddlers that exist in both documents but that are newer in the source document\n>''"differences"'' selects all new and existing tiddlers that are different from the destination document (even if destination tiddler is newer)\n\n''Import Tagging:''\n\nTiddlers that have been imported can be automatically tagged, so they will be easier to find later on, after they have been added to your document. New tags are entered into the "add tags" input field, and then //added// to the existing tags for each tiddler as it is imported.\n\n''Skip, Rename, Merge, or Replace:''\n\nWhen importing a tiddler whose title is identical to one that already exists, the import process pauses and the tiddler title is displayed in an input field, along with four push buttons: ''[skip]'', ''[rename]'', ''[merge]'' and ''[replace]''.\n\nTo bypass importing this tiddler, press ''[skip]''. To import the tiddler with a different name (so that both the tiddlers will exist when the import is done), enter a new title in the input field and then press ''[rename]''. Press ''[merge]'' to combine the content from both tiddlers into a single tiddler. Press ''[replace]'' to overwrite the existing tiddler with the imported one, discarding the previous tiddler content.\n\n//Note: if both the title ''and'' modification date/////time match, the imported tiddler is assumed to be identical to the existing one, and will be automatically skipped (i.e., not imported) without asking.//\n\n''Import Report History''\n\nWhen tiddlers are imported, a report is generated into ImportedTiddlers, indicating when the latest import was performed, the number of tiddlers successfully imported, from what location, and by whom. It also includes a list with the title, date and author of each tiddler that was imported.\n\nWhen the import process is completed, the ImportedTiddlers report is automatically displayed for your review. If more tiddlers are subsequently imported, a new report is //added// to ImportedTiddlers, above the previous report (i.e., at the top of the tiddler), so that a reverse-chronological history of imports is maintained.\n\nIf a cumulative record is not desired, the ImportedTiddlers report may be deleted at any time. A new ImportedTiddlers report will be created the next time tiddlers are imported.\n\nNote: You can prevent the ImportedTiddlers report from being generated for any given import activity by clearing the "create a report" checkbox before beginning the import processing.\n\n<<<\n!!!!!non-interactive 'load tiddlers' macro\n<<<\nUseful for automated installation/update of plugins and other tiddler content.\n\n{{{<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>}}}\n<<loadTiddlers "label:load tiddlers from %0" http://www.tiddlytools.com/example.html confirm>>\n\nSyntax:\n{{{<<loadTiddlers label:text prompt:text filter source quiet confirm>>}}}\n\n''label:text'' and ''prompt:text''\n>defines link text and tooltip (prompt) that can be clicked to trigger the load tiddler processing. If a label is NOT provided, then no link is created and loadTiddlers() is executed whenever the containing tiddler is rendered.\n''filter'' (optional) determines which tiddlers will be automatically selected for importing. Use one of the following keywords:\n>''"all"'' retrieves ALL tiddlers from the import source document, even if they have not been changed.\n>''"new"'' retrieves only tiddlers that are found in the import source document, but do not yet exist in the destination document\n>''"changes"'' retrieves only tiddlers that exist in both documents for which the import source tiddler is newer than the existing tiddler\n>''"updates"'' retrieves both ''new'' and ''changed'' tiddlers (this is the default action when none is specified)\n>''"tiddler:~TiddlerName"'' retrieves only the specific tiddler named in the parameter.\n>''"tag:text"'' retrieves only the tiddlers tagged with the indicated text.\n''source'' (required) is the location of the imported document. It can be either a local document path/filename in whatever format your system requires, or a remote web location (starting with "http://" or "https://")\n>use the keyword ''ask'' to prompt for a source location whenever the macro is invoked\n''"quiet"'' (optional)\n>supresses all status message during the import processing (e.g., "opening local file...", "found NN tiddlers..." etc). Note that if ANY tiddlers are actualy imported, a final information message will still be displayed (along with the ImportedTiddlers report), even when 'quiet' is specified. This ensures that changes to your document cannot occur without any visible indication at all.\n''"confirm"'' (optional)\n>adds interactive confirmation. A browser message box (OK/Cancel) is displayed for each tiddler that will be imported, so that you can manually bypass any tiddlers that you do not want to import.\n<<<\n!!!!!Installation\n<<<\ncopy/paste the following tiddlers into your document:\n''ImportTiddlersPlugin'' (tagged with <<tag systemConfig>>)\n\ncreate/edit ''SideBarOptions'': (sidebar menu items) \n^^Add "< < ImportTiddlers > >" macro^^\n\n''Quick Installation Tip #1:''\nIf you are using an unmodified version of TiddlyWiki (core release version <<version>>), you can get a new, empty TiddlyWiki with the Import Tiddlers plugin pre-installed (''[[download from here|TW+ImportExport.html]]''), and then simply import all your content from your old document into this new, empty document.\n<<<\n!!!!!Revision History\n<<<\n''2006.04.04 [3.0.1]''\nin refreshImportList(), when using [by tags], tiddlers without tags are now included in a new "untagged" psuedo-tag list section\n''2006.04.04 [3.0.0]''\nSeparate non-interactive {{{<<importTiddlers...>>}}} macro functionality for incorporation into TW2.1 core and renamed as {{{<<loadTiddlers>>}}} macro. New parameters for loadTiddlers: ''label:text'' and ''prompt:text'' for link creation, ''ask'' for filename/URL, ''tag:text'' for filtering, "confirm" for accept/reject of individual inbound tiddlers. Also, ImportedTiddlers report generator output has been simplified and "importReplace/importPublic" tags and associated "force" param (which were rarely, if ever, used) has been dropped.\n''2006.03.30 [2.9.1]''\nwhen extracting store area from remote URL, look for "</body>" instead of "</body>\sn</html>" so it will match even if the "\sn" is absent from the source.\n''2006.03.30 [2.9.0]''\nadded optional 'force' macro param. When present, autoImportTiddlers() bypasses the checks for importPublic and importReplace. Based on a request from Tom Otvos.\n''2006.03.28 [2.8.1]''\nin loadImportFile(), added checks to see if 'netscape' and 'x.overrideMimeType()' are defined (IE does *not* define these values, so we bypass this code)\nAlso, when extracting store area from remote URL, explicitly look for "</body>\sn</html>" to exclude any extra content that may have been added to the end of the file by hosting environments such as GeoCities. Thanks to Tom Otvos for finding these bugs and suggesting some fixes.\n''2006.02.21 [2.8.0]''\nadded support for "tiddler:TiddlerName" filtering parameter in auto-import processing\n''2006.02.21 [2.7.1]''\nClean up layout problems with IE. (Use tables for alignment instead of SPANs styled with float:left and float:right)\n''2006.02.21 [2.7.0]''\nAdded "local file" and "web server" radio buttons for selecting dynamic import source controls in ImportPanel. Default file control is replaced with URL text input field when "web server" is selected. Default remote document URL is defined in SiteURL tiddler. Also, added option for prepending SiteProxy URL as prefix to remote URL to mask cross-domain document access (requires compatible server-side script)\n''2006.02.17 [2.6.0]''\nRemoved "differences only" listbox display mode, replaced with selection filter 'presets': all/new/changes/differences. Also fixed initialization handling for "add new tags" so that checkbox state is correctly tracked when panel is first displayed.\n''2006.02.16 [2.5.4]''\nadded checkbox options to control "import remote tags" and "keep existing tags" behavior, in addition to existing "add new tags" functionality.\n''2006.02.14 [2.5.3]''\nFF1501 corrected unintended global 't' (loop index) in importReport() and autoImportTiddlers()\n''2006.02.10 [2.5.2]''\ncorrected unintended global variable in importReport().\n''2006.02.05 [2.5.1]''\nmoved globals from window.* to config.macros.importTiddlers.* to avoid FireFox 1.5.0.1 crash bug when referencing globals\n''2006.01.18 [2.5.0]''\nadded checkbox for "create a report". Default is to create/update the ImportedTiddlers report. Clear the checkbox to skip this step.\n''2006.01.15 [2.4.1]''\nadded "importPublic" tag and inverted default so that auto sharing is NOT done unless tagged with importPublic\n''2006.01.15 [2.4.0]''\nAdded support for tagging individual tiddlers with importSkip, importReplace, and/or importPrivate to control which tiddlers can be overwritten or shared with others when using auto-import macro syntax. Defaults are to SKIP overwriting existing tiddlers with imported tiddlers, and ALLOW your tiddlers to be auto-imported by others.\n''2006.01.15 [2.3.2]''\nAdded "ask" parameter to confirm each tiddler before importing (for use with auto-importing)\n''2006.01.15 [2.3.1]''\nStrip TW core scripts from import source content and load just the storeArea into the hidden IFRAME. Makes loading more efficient by reducing the document size and by preventing the import document from executing its TW initialization (including plugins). Seems to resolve the "Found 0 tiddlers" problem. Also, when importing local documents, use convertUTF8ToUnicode() to convert the file contents so support international characters sets.\n''2006.01.12 [2.3.0]''\nReorganized code to use callback function for loading import files to support event-driven I/O via an ASYNCHRONOUS XMLHttpRequest. Let's processing continue while waiting for remote hosts to respond to URL requests. Added non-interactive 'batch' macro mode, using parameters to specify which tiddlers to import, and from what document source. Improved error messages and diagnostics, plus an optional 'quiet' switch for batch mode to eliminate //most// feedback.\n''2006.01.11 [2.2.0]''\nAdded "[by tags]" to list of tiddlers, based on code submitted by BradleyMeck\n''2006.01.09 [2.1.1]''\nWhen a URL is typed in, and then the "open" button is pressed, it generates both an onChange event for the file input and a click event for open button. This results in multiple XMLHttpRequest()'s which seem to jam things up quite a bit. I removed the onChange handling for file input field. To open a file (local or URL), you must now explicitly press the "open" button in the control panel.\n''2006.01.08 [2.1.0]''\nIMPORT FROM ANYWHERE!!! re-write getImportedTiddlers() logic to either read a local file (using local I/O), OR... read a remote file, using a combination of XML and an iframe to permit cross-domain reading of DOM elements. Adapted from example code and techniques courtesy of Jonny LeRoy.\n''2006.01.06 [2.0.2]''\nWhen refreshing list contents, fixed check for tiddlerExists() when "show differences only" is selected, so that imported tiddlers that don't exist in the current file will be recognized as differences and included in the list.\n''2006.01.04 [2.0.1]''\nWhen "show differences only" is NOT checked, import all tiddlers that have been selected even when they have a matching title and date.\n''2005.12.27 [2.0.0]''\nUpdate for TW2.0\nDefer initial panel creation and only register a notification function when panel first is created\n''2005.12.22 [1.3.1]''\ntweak formatting in importReport() and add 'discard report' link to output\n''2005.12.03 [1.3.0]''\nDynamically create/remove importPanel as needed to ensure only one instance of interface elements exists, even if there are multiple instances of macro embedding. Also, dynamically create/recreate importFrame each time an external TW document is loaded for importation (reduces DOM overhead and ensures a 'fresh' frame for each document)\n''2005.11.29 [1.2.1]''\nfixed formatting of 'detail info' in importReport()\n''2005.11.11 [1.2.0]''\nadded 'inline' param to embed controls in a tiddler\n''2005.11.09 [1.1.0]''\nonly load HTML and CSS the first time the macro handler is called. Allows for redundant placement of the macro without creating multiple instances of controls with the same ID's.\n''2005.10.25 [1.0.5]''\nfixed typo in importReport() that prevented reports from being generated\n''2005.10.09 [1.0.4]''\ncombined documentation with plugin code instead of using separate tiddlers\n''2005.08.05 [1.0.3]''\nmoved CSS and HTML definitions into plugin code instead of using separate tiddlers\n''2005.07.27 [1.0.2]''\ncore update 1.2.29: custom overlayStyleSheet() replaced with new core setStylesheet()\n''2005.07.23 [1.0.1]''\nadded parameter checks and corrected addNotification() usage\n''2005.07.20 [1.0.0]''\nInitial Release\n<<<\n!!!!!Credits\n<<<\nThis feature was developed by EricShulman from [[ELS Design Studios|http:/www.elsdesign.com]]\n<<<\n!!!!!Code\n***/\n// // ''MACRO DEFINITION''\n//{{{\n// Version\nversion.extensions.importTiddlers = {major: 3, minor: 0, revision: 1, date: new Date(2006,4,6)};\n\n// IE needs explicit global scoping for functions/vars called from browser events\nwindow.onClickImportButton=onClickImportButton;\nwindow.refreshImportList=refreshImportList;\n\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\nconfig.macros.importTiddlers = { };\nconfig.macros.importTiddlers = {\n label: "import tiddlers",\n prompt: "Copy tiddlers from another document",\n countMsg: "%0 tiddlers selected for import",\n src: "", // path/filename or URL of document to import (retrieved from SiteUrl tiddler)\n proxy: "", // URL for remote proxy script (retrieved from SiteProxy tiddler)\n useProxy: false, // use specific proxy script in front of remote URL\n inbound: null, // hash-indexed array of tiddlers from other document\n newTags: "", // text of tags added to imported tiddlers\n addTags: true, // add new tags to imported tiddlers\n listsize: 8, // # of lines to show in imported tiddler list\n importTags: true, // include tags from remote source document when importing a tiddler\n keepTags: true, // retain existing tags when replacing a tiddler\n index: 0, // current processing index in import list\n sort: "" // sort order for imported tiddler listbox\n};\n\nconfig.macros.importTiddlers.handler = function(place,macroName,params) {\n if (!config.macros.loadTiddlers.handler)\n { alert("importTiddlers error: this plugin requires LoadTiddlersPlugin or TiddlyWiki 2.1+"); return; }\n if (!params[0]) // LINK TO FLOATING PANEL\n createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);\n else if (params[0]=="inline") {// // INLINE TIDDLER CONTENT\n createImportPanel(place);\n document.getElementById("importPanel").style.position="static";\n document.getElementById("importPanel").style.display="block";\n }\n else config.macros.loadTiddlers.handler(place,macroName,params); // FALLBACK: PASS TO LOADTIDDLERS\n}\n//}}}\n\n// // ''INTERFACE DEFINITION''\n\n// // Handle link click to create/show/hide control panel\n//{{{\nfunction onClickImportMenu(e)\n{\n if (!e) var e = window.event;\n var parent=resolveTarget(e).parentNode;\n var panel = document.getElementById("importPanel");\n if (panel==undefined || panel.parentNode!=parent)\n panel=createImportPanel(parent);\n var isOpen = panel.style.display=="block";\n if(config.options.chkAnimate)\n anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));\n else\n panel.style.display = isOpen ? "none" : "block" ;\n e.cancelBubble = true;\n if (e.stopPropagation) e.stopPropagation();\n return(false);\n}\n//}}}\n\n// // Create control panel: HTML, CSS, register for notification\n//{{{\nfunction createImportPanel(place) {\n var panel=document.getElementById("importPanel");\n if (panel) { panel.parentNode.removeChild(panel); }\n setStylesheet(config.macros.importTiddlers.css,"importTiddlers");\n panel=createTiddlyElement(place,"span","importPanel",null,null)\n panel.innerHTML=config.macros.importTiddlers.html;\n store.addNotification(null,refreshImportList); // refresh listbox after every tiddler change\n refreshImportList();\n var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";\n document.getElementById("importSourceURL").value=siteURL;\n config.macros.importTiddlers.src=siteURL;\n var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";\n document.getElementById("importSiteProxy").value=siteProxy;\n config.macros.importTiddlers.proxy=siteProxy;\n return panel;\n}\n//}}}\n\n// // CSS\n//{{{\nconfig.macros.importTiddlers.css = '\s\n#importPanel {\s\n display: none; position:absolute; z-index:11; width:35em; right:105%; top:3em;\s\n background-color: #eee; color:#000; font-size: 8pt; line-height:110%;\s\n border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\s\n padding: 0.5em; margin:0em; -moz-border-radius:1em;\s\n}\s\n#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\s\n#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:8pt; line-height:110%; background:transparent; }\s\n#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\s\n#importPanel select { width:98%;margin:0px;font-size:8pt;line-height:110%;}\s\n#importPanel input { width:98%;padding:0px;margin:0px;font-size:8pt;line-height:110%}\s\n#importPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px;}\s\n#importPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\s\n#importPanel .rad { width:auto; }\s\n#importPanel .chk { width:auto; margin:1px; }\s\n#importPanel .btn { width:auto; }\s\n#importPanel .btn1 { width:98%; }\s\n#importPanel .btn2 { width:48%; }\s\n#importPanel .btn3 { width:32%; }\s\n#importPanel .btn4 { width:24%; }\s\n#importPanel .btn5 { width:19%; }\s\n#importPanel .importButton { padding: 0em; margin: 0px; font-size:8pt; }\s\n#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\s\n#importCollisionPanel { display:none; margin:0.5em 0em 0em 0em; }\s\n';\n//}}}\n\n// // HTML \n//{{{\nconfig.macros.importTiddlers.html = '\s\n<!-- source and report -->\s\n<table><tr><td align=left>\s\n import from\s\n <input type="radio" class="rad" name="importFrom" value="file" CHECKED\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=!this.checked?\s'block\s':\s'none\s'"> local file\s\n <input type="radio" class="rad" name="importFrom" value="http"\s\n onClick="document.getElementById(\s'importLocalPanel\s').style.display=!this.checked?\s'block\s':\s'none\s';\s\n document.getElementById(\s'importHTTPPanel\s').style.display=this.checked?\s'block\s':\s'none\s'"> web server\s\n</td><td align=right>\s\n <input type=checkbox class="chk" id="chkImportReport" checked\s\n onClick="config.options[\s'chkImportReport\s']=this.checked;"> create a report\s\n</td></tr></table>\s\n<!-- import from local file -->\s\n<div id="importLocalPanel" style="display:block;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\nlocal document path/filename:<br>\s\n<input type="file" id="fileImportSource" size=57 style="width:100%"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<!-- import from http server -->\s\n<div id="importHTTPPanel" style="display:none;margin-bottom:5px;margin-top:5px;padding-top:3px;border-top:1px solid #999">\s\n<table><tr><td align=left>\s\n remote document URL:<br>\s\n</td><td align=right>\s\n <input type="checkbox" class="chk" id="importUseProxy"\s\n onClick="config.macros.importTiddlers.useProxy=this.checked;\s\n document.getElementById(\s'importSiteProxy\s').style.display=this.checked?\s'block\s':\s'none\s'"> use a proxy script\s\n</td></tr></table>\s\n<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\s\n onKeyUp="config.macros.importTiddlers.proxy=this.value"\s\n onChange="config.macros.importTiddlers.proxy=this.value;">\s\n<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\s\n onKeyUp="config.macros.importTiddlers.src=this.value"\s\n onChange="config.macros.importTiddlers.src=this.value;">\s\n</div><!--panel-->\s\n\s\n<table><tr><td align=left>\s\n select:\s\n <a href="JavaScript:;" id="importSelectAll"\s\n onclick="onClickImportButton(this)" title="select all tiddlers">\s\n all </a>\s\n <a href="JavaScript:;" id="importSelectNew"\s\n onclick="onClickImportButton(this)" title="select tiddlers not already in destination document">\s\n added </a> \s\n <a href="JavaScript:;" id="importSelectChanges"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been updated in source document">\s\n changes </a> \s\n <a href="JavaScript:;" id="importSelectDifferences"\s\n onclick="onClickImportButton(this)" title="select tiddlers that have been added or are different from existing tiddlers">\s\n differences </a> \s\n <a href="JavaScript:;" id="importToggleFilter"\s\n onclick="onClickImportButton(this)" title="show/hide selection filter">\s\n filter </a> \s\n</td><td align=right>\s\n <a href="JavaScript:;" id="importListSmaller"\s\n onclick="onClickImportButton(this)" title="reduce list size">\s\n – </a>\s\n <a href="JavaScript:;" id="importListLarger"\s\n onclick="onClickImportButton(this)" title="increase list size">\s\n + </a>\s\n <a href="JavaScript:;" id="importListMaximize"\s\n onclick="onClickImportButton(this)" title="maximize/restore list size">\s\n = </a>\s\n</td></tr></table>\s\n<select id="importList" size=8 multiple\s\n onchange="setTimeout(\s'refreshImportList(\s'+this.selectedIndex+\s')\s',1)">\s\n <!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\s\n</select>\s\n<input type=checkbox class="chk" id="chkAddTags" checked\s\n onClick="config.macros.importTiddlers.addTags=this.checked;">add new tags \s\n<input type=checkbox class="chk" id="chkImportTags" checked\s\n onClick="config.macros.importTiddlers.importTags=this.checked;">import source tags \s\n<input type=checkbox class="chk" id="chkKeepTags" checked\s\n onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing tags<br>\s\n<input type=text id="txtNewTags" size=15 onKeyUp="config.macros.importTiddlers.newTags=this.value" autocomplete=off>\s\n<div align=center>\s\n <input type=button id="importOpen" class="importButton" style="width:32%" value="open"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importStart" class="importButton" style="width:32%" value="import"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importClose" class="importButton" style="width:32%" value="close"\s\n onclick="onClickImportButton(this)">\s\n</div>\s\n<div id="importCollisionPanel">\s\n tiddler already exists:\s\n <input type=text id="importNewTitle" size=15 autocomplete=off">\s\n <div align=center>\s\n <input type=button id="importSkip" class="importButton" style="width:23%" value="skip"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importRename" class="importButton" style="width:23%" value="rename"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importMerge" class="importButton" style="width:23%" value="merge"\s\n onclick="onClickImportButton(this)">\s\n <input type=button id="importReplace" class="importButton" style="width:23%" value="replace"\s\n onclick="onClickImportButton(this)">\s\n </div>\s\n</div>\s\n';\n//}}}\n\n// // Control interactions\n//{{{\nfunction onClickImportButton(which)\n{\n // DEBUG alert(which.id);\n var theList = document.getElementById('importList');\n if (!theList) return;\n var thePanel = document.getElementById('importPanel');\n var theCollisionPanel = document.getElementById('importCollisionPanel');\n var theNewTitle = document.getElementById('importNewTitle');\n var count=0;\n switch (which.id)\n {\n case 'fileImportSource':\n case 'importOpen': // load import source into hidden frame\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n if (config.macros.importTiddlers.src=="") break;\n // Load document into hidden iframe so we can read it's DOM and fill the list\n loadTiddlers(config.macros.importTiddlers.src,"all",false,false,\n function(src,tiddlers){config.macros.importTiddlers.inbound=tiddlers;window.refreshImportList(0);});\n break;\n case 'importSelectAll': // select all tiddler list items (i.e., not headings)\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=true;\n count++;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectNew': // select tiddlers not in current document\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n theList.options[t].selected=!store.tiddlerExists(theList.options[t].value);\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectChanges': // select tiddlers that are updated from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value==""||!store.tiddlerExists(theList.options[t].value)) continue;\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified>0); // updated tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importSelectDifferences': // select tiddlers that are new or different from existing tiddlers\n importReport(); // if an import was in progress, generate a report\n for (var t=0,count=0; t < theList.options.length; t++) {\n theList.options[t].selected=false;\n if (theList.options[t].value=="") continue;\n if (!store.tiddlerExists(theList.options[t].value)) { theList.options[t].selected=true; count++; continue; }\n for (var i=0; i<config.macros.importTiddlers.inbound.length; i++) // find matching inbound tiddler\n { var inbound=config.macros.importTiddlers.inbound[i]; if (inbound.title==theList.options[t].value) break; }\n theList.options[t].selected=(inbound.modified-store.getTiddler(theList.options[t].value).modified!=0); // changed tiddler\n count+=theList.options[t].selected?1:0;\n }\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n break;\n case 'importToggleFilter': // show/hide filter\n case 'importFilter': // apply filter\n alert("coming soon!");\n break;\n case 'importStart': // initiate the import processing\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.index=0;\n config.macros.importTiddlers.index=importTiddlers(0);\n importStopped();\n break;\n case 'importClose': // unload imported tiddlers or hide the import control panel\n // if imported tiddlers not loaded, close the import control panel\n if (!config.macros.importTiddlers.inbound) { thePanel.style.display='none'; break; }\n importReport(); // if an import was in progress, generate a report\n config.macros.importTiddlers.inbound=null; // clear the imported tiddler buffer\n refreshImportList(); // reset/resize the listbox\n break;\n case 'importSkip': // don't import the tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status='skipped after asking'; // mark item as skipped\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index+1); // resume with NEXT item\n importStopped();\n break;\n case 'importRename': // change name of imported tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n theImported.status = 'renamed from '+theImported.title; // mark item as renamed\n theImported.set(theNewTitle.value,null,null,null,null); // change the tiddler title\n theItem.value = theNewTitle.value; // change the listbox item text\n theItem.text = theNewTitle.value; // change the listbox item text\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importMerge': // join existing and imported tiddler content\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n var theText = theExisting.text+'\sn----\sn^^merged from: ';\n theText +='[['+config.macros.importTiddlers.src+'#'+theItem.value+'|'+config.macros.importTiddlers.src+'#'+theItem.value+']]^^\sn';\n theText +='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\sn'+theImported.text;\n var theDate = new Date();\n var theTags = theExisting.getTags()+' '+theImported.getTags();\n theImported.set(null,theText,null,theDate,theTags);\n theImported.status = 'merged with '+theExisting.title; // mark item as merged\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with this item\n importStopped();\n break;\n case 'importReplace': // substitute imported tiddler for existing tiddler\n var theItem = theList.options[config.macros.importTiddlers.index];\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==theItem.value) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theItem.value);\n theImported.status = 'replaces '+theExisting.title; // mark item for replace\n theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");\n theImported.status += ' by '+theExisting.modifier;\n theCollisionPanel.style.display='none';\n config.macros.importTiddlers.index=importTiddlers(config.macros.importTiddlers.index); // resume with THIS item\n importStopped();\n break;\n case 'importListSmaller': // decrease current listbox size, minimum=5\n if (theList.options.length==1) break;\n theList.size-=(theList.size>5)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListLarger': // increase current listbox size, maximum=number of items in list\n if (theList.options.length==1) break;\n theList.size+=(theList.size<theList.options.length)?1:0;\n config.macros.importTiddlers.listsize=theList.size;\n break;\n case 'importListMaximize': // toggle listbox size between current and maximum\n if (theList.options.length==1) break;\n theList.size=(theList.size==theList.options.length)?config.macros.importTiddlers.listsize:theList.options.length;\n break;\n }\n}\n//}}}\n\n// // refresh listbox\n//{{{\nfunction refreshImportList(selectedIndex)\n{\n var theList = document.getElementById("importList");\n if (!theList) return;\n // if nothing to show, reset list content and size\n if (!config.macros.importTiddlers.inbound) \n {\n while (theList.length > 0) { theList.options[0] = null; }\n theList.options[0]=new Option('please open a document...',"",false,false);\n theList.size=config.macros.importTiddlers.listsize;\n return;\n }\n // get the sort order\n if (!selectedIndex) selectedIndex=0;\n if (selectedIndex==0) config.macros.importTiddlers.sort='title'; // heading\n if (selectedIndex==1) config.macros.importTiddlers.sort='title';\n if (selectedIndex==2) config.macros.importTiddlers.sort='modified';\n if (selectedIndex==3) config.macros.importTiddlers.sort='tags';\n if (selectedIndex>3) {\n // display selected tiddler count\n for (var t=0,count=0; t < theList.options.length; t++) count+=(theList.options[t].selected&&theList.options[t].value!="")?1:0;\n clearMessage(); displayMessage(config.macros.importTiddlers.countMsg.format([count]));\n return; // no refresh needed\n }\n\n // get the alphasorted list of tiddlers (optionally, filter out unchanged tiddlers)\n var tiddlers=config.macros.importTiddlers.inbound;\n tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });\n // clear current list contents\n while (theList.length > 0) { theList.options[0] = null; }\n // add heading and control items to list\n var i=0;\n var indent=String.fromCharCode(160)+String.fromCharCode(160);\n theList.options[i++]=new Option(tiddlers.length+' tiddler'+((tiddlers.length!=1)?'s are':' is')+' in the document',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="title" )?">":indent)+' [by title]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="modified")?">":indent)+' [by date]',"",false,false);\n theList.options[i++]=new Option(((config.macros.importTiddlers.sort=="tags")?">":indent)+' [by tags]',"",false,false);\n // output the tiddler list\n switch(config.macros.importTiddlers.sort)\n {\n case "title":\n for(var t = 0; t < tiddlers.length; t++)\n theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);\n break;\n case "modified":\n // sort descending for newest date first\n tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });\n var lastSection = "";\n for(var t = 0; t < tiddlers.length; t++) {\n var tiddler = tiddlers[t];\n var theSection = tiddler.modified.toLocaleDateString();\n if (theSection != lastSection) {\n theList.options[i++] = new Option(theSection,"",false,false);\n lastSection = theSection;\n }\n theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);\n }\n break;\n case "tags":\n var theTitles = {}; // all tiddler titles, hash indexed by tag value\n var theTags = new Array();\n for(var t=0; t<tiddlers.length; t++) {\n var title=tiddlers[t].title;\n var tags=tiddlers[t].tags;\n if (!tags || !tags.length) {\n if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }\n theTitles["untagged"].push(title);\n }\n else for(var s=0; s<tags.length; s++) {\n if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }\n theTitles[tags[s]].push(title);\n }\n }\n theTags.sort();\n for(var tagindex=0; tagindex<theTags.length; tagindex++) {\n var theTag=theTags[tagindex];\n theList.options[i++]=new Option(theTag,"",false,false);\n for(var t=0; t<theTitles[theTag].length; t++)\n theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);\n }\n break;\n }\n theList.selectedIndex=selectedIndex; // select current control item\n if (theList.size<config.macros.importTiddlers.listsize) theList.size=config.macros.importTiddlers.listsize;\n if (theList.size>theList.options.length) theList.size=theList.options.length;\n}\n//}}}\n\n// // re-entrant processing for handling import with interactive collision prompting\n//{{{\nfunction importTiddlers(startIndex)\n{\n if (!config.macros.importTiddlers.inbound) return -1;\n\n var theList = document.getElementById('importList');\n if (!theList) return;\n var t;\n // if starting new import, reset import status flags\n if (startIndex==0)\n for (var t=0;t<config.macros.importTiddlers.inbound.length;t++)\n config.macros.importTiddlers.inbound[t].status="";\n for (var i=startIndex; i<theList.options.length; i++)\n {\n // if list item is not selected or is a heading (i.e., has no value), skip it\n if ((!theList.options[i].selected) || ((t=theList.options[i].value)==""))\n continue;\n for (var j=0;j<config.macros.importTiddlers.inbound.length;j++)\n if (config.macros.importTiddlers.inbound[j].title==t) break;\n var theImported = config.macros.importTiddlers.inbound[j];\n var theExisting = store.getTiddler(theImported.title);\n // avoid redundant import for tiddlers that are listed multiple times (when 'by tags')\n if (theImported.status=="added")\n continue;\n // don't import the "ImportedTiddlers" history from the other document...\n if (theImported.title=='ImportedTiddlers')\n continue;\n // if tiddler exists and import not marked for replace or merge, stop importing\n if (theExisting && (theImported.status.substr(0,7)!="replace") && (theImported.status.substr(0,5)!="merge"))\n return i;\n // assemble tags (remote + existing + added)\n var newTags = "";\n if (config.macros.importTiddlers.importTags)\n newTags+=theImported.getTags() // import remote tags\n if (config.macros.importTiddlers.keepTags && theExisting)\n newTags+=" "+theExisting.getTags(); // keep existing tags\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newTags+=" "+config.macros.importTiddlers.newTags; // add new tags\n theImported.set(null,null,null,null,newTags.trim());\n // set the status to 'added' (if not already set by the 'ask the user' UI)\n theImported.status=(theImported.status=="")?'added':theImported.status;\n // do the import!\n store.addTiddler(theImported);\n store.setDirty(true);\n }\n return(-1); // signals that we really finished the entire list\n}\n//}}}\n\n//{{{\nfunction importStopped()\n{\n var theList = document.getElementById('importList');\n var theNewTitle = document.getElementById('importNewTitle');\n if (!theList) return;\n if (config.macros.importTiddlers.index==-1)\n importReport(); // import finished... generate the report\n else\n {\n // DEBUG alert('import stopped at: '+config.macros.importTiddlers.index);\n // import collision... show the collision panel and set the title edit field\n document.getElementById('importCollisionPanel').style.display='block';\n theNewTitle.value=theList.options[config.macros.importTiddlers.index].value;\n }\n}\n//}}}\n\n// // ''REPORT GENERATOR''\n//{{{\nfunction importReport(quiet)\n{\n if (!config.macros.importTiddlers.inbound) return;\n // DEBUG alert('importReport: start');\n\n // if import was not completed, the collision panel will still be open... close it now.\n var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';\n\n // get the alphasorted list of tiddlers\n var tiddlers = config.macros.importTiddlers.inbound;\n // gather the statistics\n var count=0;\n for (var t=0; t<tiddlers.length; t++)\n if (tiddlers[t].status && tiddlers[t].status.trim().length && tiddlers[t].status.substr(0,7)!="skipped") count++;\n\n // generate a report\n if (count && config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName\n newText +=" loaded "+count+" tiddlers from\sn[["+config.macros.importTiddlers.src+"|"+config.macros.importTiddlers.src+"]]:\sn";\n if (config.macros.importTiddlers.addTags && config.macros.importTiddlers.newTags.trim().length)\n newText += "imported tiddlers were tagged with: \s""+config.macros.importTiddlers.newTags+"\s"\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n store.addTiddler(theReport);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n\n // reset status flags\n for (var t=0; t<config.macros.importTiddlers.inbound.length; t++) config.macros.importTiddlers.inbound[t].status="";\n\n // refresh display if tiddlers have been loaded\n if (count) { store.setDirty(true); store.notifyAll(); }\n\n // always show final message when tiddlers were actually loaded\n if (count) displayMessage("Imported "+count+" of "+tiddlers.length+" tiddlers from "+config.macros.importTiddlers.src);\n}\n//}}}\n\n/***\n!!!!!TW 2.1beta Core Code Candidate\n//The following section is a preliminary 'code candidate' for incorporation of non-interactive 'load tiddlers' functionality into TW2.1beta. //\n***/\n//{{{\n// default cookie/option values\nif (!config.options.chkImportReport) config.options.chkImportReport=true;\n\nconfig.macros.loadTiddlers = { label:"", prompt:"add/update tiddlers from '%0'" };\nconfig.macros.loadTiddlers.handler = function(place,macroName,params) {\n var label=(params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;\n var prompt=(params[0].substr(0,7)=='prompt:')?params.shift().substr(6):this.prompt;\n var filter="updates";\n if (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'\n || params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:')\n filter=params.shift();\n var src=params.shift(); if (!src || !src.length) return; // filename is required\n var quiet=(params[0]=="quiet"); if (quiet) params.shift();\n var ask=(params[0]=="confirm"); if (ask) params.shift();\n if (label.trim().length) {\n // link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store\n createTiddlyButton(place,label.format([src]),prompt.format([src]),function(){loadTiddlers(src,filter,quiet,ask,copyTiddlersToStore);})\n }\n else {\n // load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store\n loadTiddlers(src,filter,quiet,ask,copyTiddlersToStore);\n }\n}\n\nfunction copyTiddlersToStore(src,tiddlers,filter,quiet,ask)\n{\n var count=0;\n if (tiddlers) for (var t=0;t<tiddlers.length;t++) {\n var theInbound = tiddlers[t];\n var theExisting = store.getTiddler(theInbound.title);\n if (theInbound.title=='ImportedTiddlers')\n continue; // skip "ImportedTiddlers" history from the other document...\n\n // apply the all/new/changes/updates filter (if any)\n if (filter && filter!="all") {\n if ((filter=="new") && theExisting) // skip existing tiddlers\n { tiddlers[t].status="skipped - tiddler already exists"; continue; }\n if ((filter=="changes") && !theExisting) // skip new tiddlers\n { tiddlers[t].status="skipped - no existing tiddler"; continue; }\n if ((filter.substr(0,4)=="tag:") && theInbound.tags.find(filter.substr(4))==null) // must match specific tag value\n { tiddlers[t].status="skipped - does not match tag"; continue; }\n if ((filter.substr(0,8)=="tiddler:") && theInbound.title!=filter.substr(8)) // must match specific tiddler name\n { continue; } // no status means don't show in report\n if (store.tiddlerExists(theInbound.title) && ((theExisting.modified.getTime()-theInbound.modified.getTime())>=0)) // tiddler is unchanged\n { tiddlers[t].status="skipped - tiddler is unchanged"; continue; }\n }\n // get confirmation if required\n if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+theInbound.title+"'\snfrom "+src))\n { tiddlers[t].status="skipped - cancelled by user"; continue; }\n // DO IT!\n store.addTiddler(theInbound);\n tiddlers[t].status=theExisting?"updated":"added"\n count++;\n }\n\n // generate a report\n if (count && config.options.chkImportReport) {\n // get/create the report tiddler\n var theReport = store.getTiddler('ImportedTiddlers');\n if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text = ""; }\n // format the report content\n var now = new Date();\n var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName+" loaded "+count+" tiddlers from\sn[["+src+"|"+src+"]]:\sn";\n newText += "<<<\sn";\n for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\sn";\n newText += "<<<\sn";\n newText += "<html><input type=\s"button\s" href=\s"javascript:;\s" ";\n newText += "onclick=\s"story.closeTiddler('"+theReport.title+"'); store.deleteTiddler('"+theReport.title+"');\s" ";\n newText += "value=\s"discard report\s"></html>";\n // update the ImportedTiddlers content and show the tiddler\n theReport.text = newText+((theReport.text!="")?'\sn----\sn':"")+theReport.text;\n theReport.modifier = config.options.txtUserName;\n theReport.modified = new Date();\n store.addTiddler(theReport);\n if (!quiet) { story.displayTiddler(null,theReport.title,1,null,null,false); story.refreshTiddler(theReport.title,1,true); }\n }\n\n // refresh display if tiddlers have been loaded\n if (count) { store.setDirty(true); store.notifyAll(); }\n\n // always show final message when tiddlers were actually loaded\n if (!quiet||count) displayMessage("Loaded "+count+" of "+tiddlers.length+" tiddlers from "+src);\n}\n\nfunction loadTiddlers(src,filter,quiet,ask,callback) {\n if (!quiet) clearMessage();\n if (src=="ask") src=prompt("Enter a local path/filename or a remote URL");\n if (!src || !src.length) return; // filename is required\n if (src.substr(0,4)!="http") {\n if (!quiet) displayMessage("Opening local document: "+ src);\n var txt=loadFile(src);\n if(!txt) { if (!quiet) displayMessage("Could not open local document: "+src); }\n else {\n var start=txt.indexOf('<div id="storeArea">');\n var end=txt.indexOf('</body>');\n var sa="<html><body>"+txt.substring(start,end)+"</body></html>";\n if (!quiet) displayMessage(txt.length+" bytes in document. ("+sa.length+" bytes used for tiddler storage)");\n var tiddlers = getTiddlersFromHTML(convertUTF8ToUnicode(sa));\n var count=tiddlers?tiddlers.length:0;\n if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);\n if (callback) callback(src,tiddlers,filter,quiet,ask);\n }\n }\n else {\n if (!quiet) displayMessage("Opening remote document: "+ src);\n var x; // XML object\n try {x = new XMLHttpRequest()}\n catch(e) {\n try {x = new ActiveXObject("Msxml2.XMLHTTP")}\n catch (e) {\n try {x = new ActiveXObject("Microsoft.XMLHTTP")}\n catch (e) { return }\n }\n }\n x.onreadystatechange = function() {\n if (x.readyState == 4) {\n if (x.status == 200) {\n var start=x.responseText.indexOf('<div id="storeArea">');\n var end=x.responseText.indexOf('</body>',start);\n var sa="<html><body>"+x.responseText.substring(start,end)+"</body></html>";\n if (!quiet) displayMessage(x.responseText.length+" bytes in document. ("+sa.length+" bytes used for tiddler storage)");\n var tiddlers = getTiddlersFromHTML(sa);\n var count=tiddlers?tiddlers.length:0;\n if (!quiet) displayMessage("Found "+count+" tiddlers in "+src);\n if (callback) callback(src,tiddlers,filter,quiet,ask);\n }\n else\n if (!quiet) displayMessage("Could not open remote document:"+ src+" (error="+x.status+")");\n }\n }\n if ((document.location.protocol=="file:") && (typeof(netscape)!="undefined")) { // UniversalBrowserRead only works from a local file context\n try { netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead')}\n catch (e) { if (!quiet) displayMessage(e.description?e.description:e.toString()); }\n }\n try {\n var url=src+(src.indexOf('?')<0?'?':'&')+'nocache='+Math.random();\n x.open("GET",url,true);\n if (x.overrideMimeType) x.overrideMimeType('text/html');\n x.send(null);\n }\n catch (e) {\n if (!quiet) {\n displayMessage("Could not open remote document: "+src);\n displayMessage(e.description?e.description:e.toString());\n }\n }\n }\n}\n\nfunction getTiddlersFromHTML(html)\n{\n // load html into iframe document\n var f=document.getElementById("loaderFrame"); if (f) document.body.removeChild(f);\n f=document.createElement("iframe"); f.id="loaderFrame";\n f.style.width="0px"; f.style.height="0px"; f.style.border="0px";\n document.body.appendChild(f);\n var d=f.document;\n if (f.contentDocument) d=f.contentDocument; // For NS6\n else if (f.contentWindow) d=f.contentWindow.document; // For IE5.5 and IE6\n d.open(); d.writeln(html); d.close();\n\n // read tiddler DIVs from storeArea DOM element \n var sa = d.getElementById("storeArea");\n if (!sa) return null;\n sa.normalize();\n var nodes = sa.childNodes;\n if (!nodes || !nodes.length) return null;\n var tiddlers = [];\n for(var t = 0; t < nodes.length; t++) {\n var title = null;\n if(nodes[t].getAttribute)\n title = nodes[t].getAttribute("tiddler");\n if(!title && nodes[t].id && (nodes[t].id.substr(0,5) == "store"))\n title = nodes[t].id.substr(5);\n if(title && title != "")\n tiddlers.push((new Tiddler()).loadFromDiv(nodes[t],title));\n }\n return tiddlers;\n}\n//}}}
FTPmicro è un web-server grande quanto un package [[DIP40]], realizzato grazie ad un PIC18F67J60.\nTale microcontrollore è un PIC ad 8-bit di fascia alta che integra, nel suo piccolo package, un controller\nethernet 10BaseT.\nNonostante le ridotte dimensioni, la scheda ha caratteristiche davvero interessanti, infatti dispone di uno slot per schede di memoria microSD,\nun sensore di temperatura TC1047, e numerosi pin di I/O digitali ed analogici. Ma ancora più importante è il software\nche può essere eseguito su questo dispositivo; in particolare, utilizzando lo stack TCP/IP di Microchip, adattato\na questo particolare hardware, è possibile avere in pochi minuti un server HTTP ed UDP con client DHCP.\n\nFTPMicro non richiede alcun componente esterno per il suo funzionamento: è sufficiente\ncaricare il software nel PIC ed alimentare la scheda a circa 5V. E' poi presente un comodo\nconnettore per il programmatore/debugger ICD2 di Microchip. \n\nGrazie alla presenza della memoria SD, si possono immagazzinare un gran numero di\nfile che saranno disponibili al server HTTP.\nCosì si può creare un completo sito web, composto sia da parti statiche (HTML, CSS, JavaScript, ecc.) che da parti dinamiche (CGI).\nLeggendo dati in tempo reale ed inviando comandi, è possibile controllare qualunque hardware.\n
Nella scheda di memoria [[microSD]], può essere immagazzinato qualunque tipo di file direttamente da computer; infatti\nviene utilizzato il FileSystem FAT16 quindi perfettamente compatibile con i Sistemi Operativi più comuni.\nDunque, affinchè FTPmicro sia in grado di leggere la scheda, è necessario formattarla con questo FileSystem. <br />\nInoltre, il software supporta soltanto i nomi corti per i file, ovvero al massimo 8 caratteri per il nome, e 3 caratteri per l'estenzione.<br />\n<html>\nNomi più lunghi sono supportati, ma il limite è imposto dalla seguente <em>define</em> dichiarata nel file <em>FAT16.h</em>:\n<pre class="code">#define MAX_FILENAME_LEN (32)</pre>\n<br />\nLa scheda può essere inserita e rimossa dal sistema anche durante il funzionamento, infatti è supportato l'<em>hot-plug</em>.<br />\n</html>
IniziaQuì\n[[La Memoria SD]]\n[[Configurazione]]\n[[Il Server HTTP]]\n[[Esempio Pratico]]\n[[Sorgenti]]\nSchemaElettrico\nPinOut\n[[FAT16.c]]\n[[SD.c]]\n\n[[Electronics BLOG|http://dev.emcelettronica.com]]\n\n@@bgcolor(yellow):''[[ORDER NOW|http://store.emcelettronica.com]]''@@\n\n[img[Projenius|projenius.png][http://www.fortronic.it/page.asp?pag=497&focusid=395]]\n[[3° CLASSIFICATO|http://www.repertorio.fortronic.it/page.asp?pag=449&focusid=395]]\n\n[img[English|uk-flag.jpg][index_en.html]]\n\n^^<<today "DDD DD MMM YYYY">>^^\n© [[EMCelettronica Srl|http://www.emcelettronica.com]]\n\n^^[img[favicon.ico]] TiddlyWiki <<version>>^^
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">\n</script>\n<script type="text/javascript">\n_uacct = "UA-811279-8";\nurchinTracker();\n</script>
<<option chkOpenInNewWindow>> ApriCollegamentiInNuovaFinestra\n<<option chkSaveEmptyTemplate>> SalvaModelloVuoto\n<<option chkToggleLinks>> Cliccando su un collegamento ad un frammento già aperto lo chiude\n^^(evita con Control o altro tasto modificabile)^^ \n<<option chkHttpReadOnly>> Non rendere editabile dal web\n<<option chkForceMinorUpdate>> Tratta le modifiche minori e mantieni data ed ora precedenti\n^^(disattiva con Shift in modifica o con la combinazione Ctrl-Shift-Enter)^^\n<<option chkConfirmDelete>> Richiedi Conferma prima di eliminare il frammento\n <<option txtMaxEditRows>>Numero massimo di righe per ciascun frammento: \n <<option txtBackupFolder>>Percorso della directory di backup: \n
[img[PIC18F67J60|pic18f67j60.jpg][pic18f67j60_h.jpg]]
Choose Your preferited <<fontSize font-size: >> and click on Pin Name for description\n|!PIN|!DIR|!NAME| |!PIN|!DIR|!NAME| |!PIN|!DIR|!NAME| |!PIN|!DIR|!NAME|\n|bgcolor(#EEEEEE): 1 |bgcolor(#EEEEEE): |bgcolor(#EEEEEE): GND | |bgcolor(#EFEFD0): 9 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RE0 | |bgcolor(#EEEEEE): 17 |bgcolor(#EEEEEE): |bgcolor(#EEEEEE): GND | |bgcolor(#FF8888): 25 |bgcolor(#FF8888): |bgcolor(#FF8888): 3V3 |\n|bgcolor(#EFEFD0): 2 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RB5 | |bgcolor(#EFEFD0): 10 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RE1 | |bgcolor(#FF8888): 18 |bgcolor(#FF8888): |bgcolor(#FF8888): 3V3 | |bgcolor(#EFEFD0): 26 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RA2 |\n|bgcolor(#EFEFD0): 3 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RB4 | |bgcolor(#EFEFD0): 11 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RE2 | |bgcolor(#EFEFD0): 19 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RF6 | |bgcolor(#EFEFD0): 27 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RA3 |\n|bgcolor(#EFEFD0): 4 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RB3 | |bgcolor(#EFEFD0): 12 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RE3 | |bgcolor(#EFEFD0): 20 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RF5 | |bgcolor(#EFEFD0): 28 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RC6 |\n|bgcolor(#EFEFD0): 5 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RB2 | |bgcolor(#EFEFD0): 13 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RE4 | |bgcolor(#EFEFD0): 21 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RF4 | |bgcolor(#EFEFD0): 29 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RC7 |\n|bgcolor(#EFEFD0): 6 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RB1 | |bgcolor(#EFEFD0): 14 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RE5 | |bgcolor(#EFEFD0): 22 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RF3 | |bgcolor(#EFEFD0): 30 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RC0 |\n|bgcolor(#EFEFD0): 7 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RB0 | |bgcolor(#FFEE66): 15 |bgcolor(#FFEE66): |bgcolor(#FFEE66): +5V | |bgcolor(#EFEFD0): 23 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RF2 | |bgcolor(#EFEFD0): 31 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RC1 |\n|bgcolor(#EFEFD0): 8 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RG4 | |bgcolor(#EEEEEE): 16 |bgcolor(#EEEEEE): |bgcolor(#EEEEEE): GND | |bgcolor(#EFEFD0): 24 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RF1 | |bgcolor(#EFEFD0): 32 |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): RC2 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RA2'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN2'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 2 |\n|! ''Vref-'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): A/D reference voltage (low) input |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RA3'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN3'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 3 |\n|! ''Vref+'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): A/D reference voltage (high) input |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RB0'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~INT0'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): External interrupt 0 |\n|! ''~FLT0'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Enhanced PWM Fault input (ECCP modules) enabled in software |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RB1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~INT1'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): External interrupt 1 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RB2'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~INT2'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): External interrupt 2 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RB3'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~INT3'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): External interrupt 3 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RB4'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~KBI0'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Interrupt on-change pin |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RB5'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Digital I/O |\n|! ''~KBI1'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): TTL |bgcolor(#EFEFD0): Interrupt on-change pin |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RC0'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~T1OSO'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): Timer1 oscillator output |\n|! ''~T13CKI'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Timer1/Timer3 external clock input |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RC1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~T1OSI'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): CMOS |bgcolor(#EFEFD0): Timer1 oscillator input |\n|! ''~ECCP2'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Capture 2 input/Compare 2 output/~PWM2 output |\n|! ''~P2A'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP2 PWM output A |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RC2'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~ECCP1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Capture 1 input/Compare 1 output/~PWM1 output |\n|! ''~P1A'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP1 PWM output A |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RC6'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~TX1'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~EUSART1 asynchronous transmit |\n|! ''~CK1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): ~EUSART1 synchronous clock |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RC7'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~RX1'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): ~EUSART1 asynchronous receive |\n|! ''~DT1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): ~EUSART1 synchronous data |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RE0'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~P2D'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP2 PWM output D |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RE1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~P2C'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP2 PWM output C |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RE2'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~P2B'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP2 PWM output B |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RE3'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~P3C'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP3 PWM output C |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RE4'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~P3B'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP3 PWM output B |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RE5'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~P1C'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP1 PWM output C |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RF1'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN6'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 6 |\n|! ''C2out'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): Comparator 2 output |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RF2'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN7'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 7 |\n|! ''C1out'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): Comparator 1 output |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RF3'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN8'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 8 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RF4'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN9'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 9 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RF5'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN10'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 10 |\n|! ''~CVref'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): Comparator reference voltage output |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RF6'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~AN11'' |bgcolor(#EFEFD0): I |bgcolor(#EFEFD0): Analog |bgcolor(#EFEFD0): Analog input 11 |
|! Pin |! Type |! Buffer |! Description |\n|! ''~RG4'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Digital I/O |\n|! ''~CCP5'' |bgcolor(#EFEFD0): I/O |bgcolor(#EFEFD0): ST |bgcolor(#EFEFD0): Capture 5 input/Compare 5 output/~PWM5 output |\n|! ''~P1D'' |bgcolor(#EFEFD0): O |bgcolor(#EFEFD0): - |bgcolor(#EFEFD0): ~ECCP1 PWM output D |
<html>\nLe schede di memoria <a href="http://www.sandisk.com/Assets/File/OEM/Manuals/SD_SDIO_specsv1.pdf">MMC/SD</a>\nhanno diverse modalità di comunicazione (alcune opzionali), in particolare\nle memorie di tipo SD (<em>Secure Digital</em>) supportano sempre il protocollo <em>SPI</em> ed il protocollo nativo ad 1bit.<br />\nLa comunicazione avviene attraverso l'invio di diversi comandi, ai quale segue sempre una risposta da parte della memoria.<br />\nPer entrare in modalità SPI, è sufficiente portare il segnale CS basso durante l'invio del comando CMD0 (Che porta il dispositivo in <em>Idle Mode</em>).\nA questo punto, per terminare l'inizializzazione, è necessario inviare il comando ACMD41 finchè la SD non esce dallo stato <em>Idle</em>\n(lo status è contenuto nel primo byte di una risposta). <br />\nIl comando ACMD41, però, è di tipo <em>Application-Specific</em> perciò esso è sempre preceduto dal comando <em>CMD55</em>.<br />\n<br />\n<pre class="code">char SDInit() \n{\n char i;\n char status;\n \n TRISCbits.TRISC5 = 0;\n TRISCbits.TRISC4 = 1;\n TRISCbits.TRISC3 = 0;\n SSP1STAT = 0x00;\n SSP1CON1 = 0x30; // SPI master, Fosc/4\n PIR1bits.SSP1IF = 0;\n SD_CS_TRIS = 0;\n SD_CS = 1; \n\n for(i=0; i < 16; i++)\n spi(0xFF); // Clock extra per il powerup \n\n SD_CS = 0;\n\n SDCmd(CMD0, 0); // Invia il comando di reset\n if (SDWait()!=0x01)\n goto SDError;\n\n i = 20;\n do {\n SDCmd(CMD55, 0);\n SDWait();\n SDCmd(ACMD41, 0); // Invia il comando ACMD41 per terminare l'inizializzazione\n if (i-- < 0)\n goto SDError;\n } while ((SDWait()&1) != 0x00); // attende l'uscita dallo stato Idle\n\n SD_CS = 1;\n return TRUE;\nSDError:\n SD_CS = 1;\n return FALSE;\n}</pre>\nCon il metodo <em>SDInit</em> viene configurato il modulo SPI e vengono effettuate le operazioni appena descritte per inizializzare la memoria SD.<br />\n<br />\nIn questo frammento di codice si fa uso di due metodi: <em>SDCmd</em> serve ad inviare un comando alla scheda, mentre con <em>SDWait</em> si attende la risposta.\n<pre class="code">char SDCmd(char cmd, unsigned long param)\n{\n spi(0xFF); // extra clock\n spi(cmd); // command\n spi(param >> 24);\n spi(param >> 16);\n spi(param >> 8);\n spi(param);\n spi(cmd == CMD0 ? 0x95 : 0xFF); // CRC, obbligatorio solo per CMD0\n}\n\nchar SDWait(void)\n{\n unsigned short count = 0xFF;\n char response;\n\n while((response=spi(0xFF)) == 0xFF && --count > 0); // attende una risposta diversa da 0xFF, con timeout\n\n return response;\n}</pre>\n<br />\nInfine, il metodo che ci permette di leggere dalla memoria, sfruttando il comando <em>CMD17</em> è <em>SDReadSector</em>.\nLa lettura deve avvenire a blocchi di <em>n</em> byte, dove <em>n</em> per default vale 512.\n<pre class="code">char SDReadSector(unsigned long sector)\n{\n int i;\n char* buf_pt = &sd_buffer[0];\n char status;\n\n SD_CS = 0;\n SDCmd(CMD17, (sector * SECTOR_SIZE)); // legge a partire dal byte sector*512\n\n if(SDWait()!=0x00 || SDWait()!=0xFE) // attende prima una risposta al comando, poi attende l'inizio del campo dati\n {\n SD_CS = 1;\n sdPresent = FALSE; // se la lettura fallisce, si suppone che la SD sia stata rimossa\n return FALSE; \n }\n\n for (i = 0; i < SECTOR_SIZE; i++)\n buf_pt[i] = spi(0xFF); // read block\n\n spi(0xFF);\n spi(0xFF); // flush CRC\n\n SD_CS = 1;\n return TRUE;\n}</pre>\nIl settore letto viene memorizzato in un buffer, che per la sua dimensione deve essere collocato esattamente in due\nbanchi RAM, grazie alla direttiva <em>pragma</em>; inoltre questa zona deve essere dichiarata protetta nel linker, affinchè non venga\noccupata da altre variabili.\n</html>
foto connettore sd micro
[img[Schematic|schematic.jpg][schematicH.jpg]]
Schemaelettrico
<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel Opzioni 'Modifica le opzioni avanzate di interfaccia del TiddlyWiki'>>
Il WebServer e FtpClient, con funzionalità DHCP e UDP, più piccolo del mondo!\n
FTPmicro
<html>\nIl software di FTPMicro, è disponibile a <a href="FTPMicro_1v01.rar">QUI</a>.<br />\nI sorgenti includono tutti i file necessari a realizzare l'esempio proposto nell'articolo </html> "[[Esempio Pratico]]".\n
<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></div>\n<div class='title' macro='view title'></div>\n<div class='subtitle'><span macro='view modifier link'></span>, modificato il <span macro='view modified date [[DD MMM YYYY]]'></span> (creato il <span macro='view created date [[DD MMM YYYY]]'></span>)</div>\n<div class='tagging' macro='tagging'></div>\n<div class='tagged' macro='tags'></div>\n<div class='viewer' macro='view text wikified'></div>\n<div class='tagClear'></div>
Inserire la micro-sd nell'adattatore, inserire la SD nel PC, scaricare il sito web sulla memoria sd, togliere la sd dal pc e poi dall'adattatore, inserire la micro sd nell'adattatore SDholder di ftp micro
//TW Italian Plugin by Mathew Warburton 2.0.1 release\n\nconfig.commands.closeTiddler.text = "Chiudi";\nconfig.commands.closeTiddler.tooltip = "Chiude questo frammento";\nconfig.commands.closeOthers.text = "Chiude altri ";\nconfig.commands.closeOthers.tooltip = "Chiude gli altri frammenti";\nconfig.commands.editTiddler.text = "Modifica";\nconfig.commands.editTiddler.tooltip = "Edita il frammento";\nconfig.commands.saveTiddler.text = "Salva";\nconfig.commands.saveTiddler.tooltip = "Salva le modifiche";\nconfig.commands.cancelTiddler.text = "Annulla";\nconfig.commands.cancelTiddler.tooltip = "Annulla le modifiche";\nconfig.commands.deleteTiddler.text = "Elimina";\nconfig.commands.deleteTiddler.tooltip = "Elimina questo frammento";\nconfig.commands.deleteTiddler.warning = "Sicuro di voler eliminare '%0'?";\nconfig.commands.permalink.text = "Indirizzo";\nconfig.commands.permalink.tooltip = "Indica sulla barra l'indirizzo di questo frammento";\nconfig.commands.references.text = "Collegati";\nconfig.commands.references.tooltip = "Elenca i frammenti che puntano qui";\nconfig.commands.references.popupNone = "Nessun frammento punta qui";\nconfig.commands.jump.text = "Vai a ";\nconfig.commands.jump.tooltip = "Vai ad un altro frammento aperto";\n\nconfig.macros.allTags.noTags = "Non ci sono frammenti categorizzati";\nconfig.macros.allTags.tooltip = "Mostra i frammenti del tipo ";\nconfig.macros.closeAll.label = "Chiudi tutti";\nconfig.macros.closeAll.prompt = "Chiude tutti i frammenti aperti(esclusi quelli in modifica)";\nconfig.macros.list.all.prompt = "Elenca tutti i frammenti in ordine alfabetico";\nconfig.macros.list.missing.prompt = "Elenca frammenti collegati tra loro non ancora definiti";\nconfig.macros.list.orphans.prompt = "Elenca i frammenti non collegati";\n\nconfig.macros.list.shadowed.prompt = "Frammenti nascosti contenenti le impostazioni del programma";\n\nconfig.macros.newJournal.label = "Oggi";\nconfig.macros.newJournal.months = ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre","Dicembre"];\nconfig.macros.newJournal.prompt = "Crea un nuovo frammento con data e ora corrente";\nconfig.macros.newTiddler.label = "Nuovo";\nconfig.macros.newTiddler.prompt = "Crea un nuovo frammento";\nconfig.macros.permaview.label = "Indirizzo di Pagina";\nconfig.macros.permaview.prompt = "Indica sulla barra l'indirizzo della pagina e dei frammenti aperti";\nconfig.macros.saveChanges.label = "Salva modifiche";\nconfig.macros.saveChanges.prompt = "Salva tutti i frammenti per creare un nuovo TiddlyWiki";\nconfig.macros.search.label = "Trova";\nconfig.macros.search.prompt = "Cerca in questo TiddlyWiki";\nconfig.macros.search.successMsg = " Trovati frammenti contenenti ";\nconfig.macros.search.failureMsg = "Nessun frammento contiene: ";\nconfig.macros.timeline.dateFormat = "DD MMM YYYY";\nconfig.macros.tagging.label = "Crea Categorie:";\nconfig.macros.tagging.labelNotTag = "Categoria:";\nconfig.macros.tagging.tooltip = "Frammenti di Tipo '%0'";\n\nconfig.messages.backupFailed = "Salvataggio file di backup non riuscito";\nconfig.messages.backupSaved = "Backup riuscito";\nconfig.messages.cantSaveError = "Non si possono salvare le modifiche con questo browser. Se puoi usa Firefox";\nconfig.messages.customConfigError = "Errore in customConfig - '%0' ";\nconfig.messages.emptyFailed = "Salvataggio file modello vuoto non riuscito";\nconfig.messages.emptySaved = "Modello vuoto salvato";\nconfig.messages.externalLinkTooltip = "Collegamento a %0";\nconfig.messages.invalidFileError = "Il file originale non sembra di tipo TiddlyWiki: ";\nconfig.messages.macroError = "Errore nella macro <<%0>>";\nconfig.messages.macroErrorDetails = "Errore in esecuzione della macro <<%0>>:\sn%1";\nconfig.messages.missingMacro = "La macro non esiste";\nconfig.messages.mainFailed = "File TiddlyWiki principale non salvato. Le tue modifiche non sono state salvate";\nconfig.messages.mainSaved = "File TiddlyWiki primario salvato ";\nconfig.messages.noTags = "Non ci sono frammenti del tipo ";\nconfig.messages.notFileUrlError = "Devi esportare questo TiddlyWiki prima di poterlo salvare";\nconfig.messages.overwriteWarning = "Il frammento '%0' esiste già. OK per sostituirlo";\nconfig.messages.rssFailed = "Salvataggio RSS feed file non riuscito";\nconfig.messages.rssSaved = "RSS feed salvato come";\nconfig.messages.savedSnapshotError = "Sembra che questo TiddlyWiki sia stato salvato scorrettamente. Per informazioni vai a http://www.tiddlywiki.com/#DownloadSoftware";\nconfig.messages.subtitleUnknown = "( sconosciuto )";\nconfig.messages.undefinedTiddlerToolTip = "Il frammento '%0'non esiste ";\nconfig.messages.shadowedTiddlerToolTip = "Il frammento '%0' non esiste, è un modello predefinito ";\nconfig.messages.unsavedChangesWarning = "ATTENZIONE non sono state ancora salvate le modifiche in TiddlyWiki\sn\snOK per salvare\snANNULLA per annullarle";\nconfig.messages.messageClose.text = "Chiudi";\nconfig.messages.messageClose.tooltip = "Chiudi l'area di messaggio";\n\n\nconfig.messages.dates.months = ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre","Dicembre"];\nconfig.messages.dates.days = ["Domenica", "Lunedì","Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"];\n\nconfig.views.editor.defaultText = "Edita '%0'.";\nconfig.views.editor.tagChooser.popupNone = "Nessuna categoria è definita";\nconfig.views.editor.tagChooser.tagTooltip = "Aggiungi la categoria ";\nconfig.views.editor.tagChooser.text = "Esistenti";\nconfig.views.editor.tagChooser.tooltip = "Seleziona la categoria tra quelle già presenti";\nconfig.views.editor.tagPrompt = "Aggiungi le categorie separandole con uno spazio, [[se il titolo è di più di una parola mettilo tra due parentesi quadre]] o scegli tra quelle ";\n\nconfig.shadowTiddlers.OptionsPanel = "'Queste OpzioniInterfaccia per personalizzare il tuo TiddlyWiky vengono salvate nel browser\sn\snDigita un nome utente per firmare le tue modifiche. Usa un formato di parola Wiki (es PincoPallino)\sn\sn <<option txtUserName>>\sn<<option chkSaveBackups>> SalvaBackups\sn<<option chkAutoSave>> SalvataggioAutomatico\sn<<option chkGenerateAnRssFeed>> GeneraUnArchivioRSS\sn<<option chkRegExpSearch>> RicercaEstesa\sn<<option chkCaseSensitiveSearch>> ConsideraCaratteriInRicerca\sn<<option chkAnimate>> AbilitaAnimazioni\sn\sn Apri OpzioniAvanzate";\n\nconfig.shadowTiddlers.SideBarOptions = "<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel Opzioni 'Modifica le opzioni avanzate di interfaccia del TiddlyWiki'>>";\n\nconfig.shadowTiddlers.SideBarTabs = "<<tabs txtMainTab 'Data' 'Elenca i frammenti cronologicamente' TabTimeline Tutti 'Tutti i frammenti in ordine alfabetico' TabAll 'Categorie' 'Elenca i frammenti per tipo' TabTags 'Altro' 'Altri Elenchi' TabMore>>";\nconfig.shadowTiddlers.TabMore = "<<tabs txtMoreTab 'Mancanti' 'Frammenti non ancora editati' TabMoreMissing 'Orfani' 'Frammenti non collegati tra loro' TabMoreOrphans 'Nascosti' 'Frammenti Nascosti' TabMoreShadowed >>";\n\n\nconfig.shadowTiddlers.OpzioniAvanzate = "<<option chkOpenInNewWindow>> ApriCollegamentiInNuovaFinestra\sn<<option chkSaveEmptyTemplate>> SalvaModelloVuoto\sn<<option chkToggleLinks>> Cliccando su un collegamento ad un frammento già aperto lo chiude\sn^^(evita con Control o altro tasto modificabile)^^ \sn<<option chkHttpReadOnly>> Non rendere editabile dal web\sn<<option chkForceMinorUpdate>> Tratta le modifiche minori e mantieni data ed ora precedenti\sn^^(disattiva con Shift in modifica o con la combinazione Ctrl-Shift-Enter)^^\sn<<option chkConfirmDelete>> Richiedi Conferma prima di eliminare il frammento\sn <<option txtMaxEditRows>>Numero massimo di righe per ciascun frammento: \sn <<option txtBackupFolder>>Percorso della directory di backup: \sn";\n\nconfig.shadowTiddlers.GettingStarted = "Per iniziare ad usare questo documento vuoto, comincia ad editare i seguenti frammenti:\sn* SiteTitle e SiteSubtitle: Il titolo ed il sottotitolo della pagina visibili nella barra del browser\sn* MainMenu: Il menù principale di TW\sn* DefaultTiddlers: Inserisci i collegamenti ai frammenti che desideri compaiono all'apertura di questo TiddlyWiki.\sn Inserisci anche un tuo nome utente che ti permetterà di firmare le tue modifiche: <<option txtUserName>>";\n\n\nconfig.views.wikified.defaultText = "Questo frammento non esiste ancora. Doppio click per crearlo";\nconfig.views.wikified.tag.labelTags = "Categorie : ";\nconfig.views.wikified.tag.openTag = "Apri la categoria '%0'";\nconfig.views.wikified.tag.labelNoTags = "Nessuna categoria.";\nconfig.views.wikified.tag.openAllText = "Apri tutti i tiddler di questa categoria ";\nconfig.views.wikified.tag.openAllTooltip = "Apri tutti ";\nconfig.views.wikified.tag.popupNone = "Non ci sono altri frammenti del tipo '%0'";\nconfig.views.wikified.tag.tooltip = "Mostra frammenti del tipo '%0' ";