<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
In Socialtext Unplugged, the selected pages of your Socialtext workspace are displayed as individual "tiddlers" on the page. When the mouse passes over a tiddler a short toolbar menu appears at the top right. Use the commands here to manipulate that particular tiddler: notably closing and editting it. (You can double click on a tiddler as a shortcut to directly enter edit mode).

Over on the right hand side of the window are commands that affect the entire page, in particular "close all" which can be useful to clear the decks when many tiddlers are open at once.

The user is encouraged to ensure that they can SaveChanges before embarking on widespread editing.
Welcome to Socialtext Unplugged. This is a specially designed web page that you can use to view and edit your Socialtext content without having to be online to your Socialtext server.

There are three steps to using Socialtext Unplugged:
* First, learn how to SaveChanges to your local hard drive. This keeps your work safe even if you close your browser or have to reboot your computer
* Secondly, find out how to BrowseAndEdit your content while it is unplugged
* Thirdly, when you can reconnect to your Socialtext server, you can SyncChanges to save your unplugged changes to the server so that other people can see them too

You should also check your system meets the SystemRequirements.
Socialtext Unplugged lets you browse and edit your content while you're offline. When you make a change you need to SaveChanges to save the change to your local hard drive, before later performing a SyncChanges to synchronise the change back to the server.

The procedure for SaveChanges is slightly different for different browsers:
* SavingOnInternetExplorer
* SavingOnFireFox
* SavingOnSafari
* SavingOnOpera
You can save changes with any version of FireFox, and also many other browsers in the FireFox family, such as Camino on the Mac and MiniMo on mobile devices. The procedure is:
# Click the button labelled 'save changes' over in the right hand sidebar
# If prompted with an "Internet Security" dialog as follows, click the checkbox labelled "Remember this decision" and then the "Allow" button
## "A script from "file://" is requesting enhanced capabilities that are UNSAFE and could be used to compromise your machine or data..."
# You should then see a message at the top right of the window saying "Main TiddlyWiki file saved"
If you accidentally //deny// permission instead, you may need to UnravelFireFoxPermissions.
You can save changes with Internet Explorer versions 6 and 7, but not the earlier versions. The procedure is:
# Click the button labelled 'save changes' over in the right hand sidebar
# If prompted as follows, click "Yes":
## "An ActiveX control on this page might be unsafe to interact with other parts of the page. Do you want to allow this interaction?"
# You should then see a message at the top right of the window saying "Main TiddlyWiki file saved"
Note that there is currently [[a bug|http://trac.tiddlywiki.org/tiddlywiki/ticket/39]] that prevents Internet Explorer from saving correctly if you have specified a backup directory in AdvancedOptions.
To SaveChanges on Opera, see the instructions for using the TiddlySaver Java applet.
To SaveChanges on Safari, see the instructions for using the TiddlySaver Java applet.
<<search>><<closeAll>><<permaview>><<newTiddler 'New Tiddler' fields:'server.host:"https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443" server.workspace:"rot13" wikiformat:socialtext'>><<newJournal 'DD MMM YYYY' fields:'server.host:"https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443" server.workspace:"rot13" wikiformat:socialtext'>><<saveChanges>><<backstage sync>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
Dobrica Pavlinušić's random unstructured stuff
Socialtext Unplugged
https://saturn.ffzg.hr/rot13/
[[SocialtextScreenStyle]]
[[SocialtextStyleOverrides]]
[[Styles HorizontalMainMenu]]
<<sync>>
@@The user interface for synchronization is not finalized@@
To synchronize your changes back to the Socialtext server:
# click on [[Sync]] in the right-hand sidebar
<<tabs txtMoreTab Orphans 'Orphaned tiddlers' TabMoreOrphans Shadowed 'Shadowed tiddlers' TabMoreShadowed>>
Under FireFox, you can run into problems if you accidentally click 'Deny' on the permission request dialog, and have selected //Remember this decision//.

To reverse the effects, first locate the file {{{prefs.js}}} in your FireFox profile directory. Under Windows you'll find it at something like {{{C:\Documents and Settings\Jeremy\Application Data\Mozilla\Firefox\Profiles\o3dhupu6.default\prefs.js}}}, where {{{Jeremy}}} is the name of your windows profile and {{{o3dhupu6}}} will be a similar string of gobbledegook. On the Mac it'll be at {{{~/Library/Application Support/Firefox/Profiles/o3dhupu6.default/prefs.js}}} and on most versions of Linux, at {{{~/.mozilla/firefox/o3dhupu6.default/prefs.js}}}.

Open the file in a text editor and find the line {{{user_pref("capability.principal.codebase.p0.denied", "UniversalXPConnect");}}} and simply replace the word {{{denied}}} with {{{granted}}}.
//(Thanks to JonScully for figuring out this fix)//
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler references > fields syncing jump'></div>
<div class='workspace' id='st-page-wiki-title' macro='view socialtext.workspace'></div>
<div class='title' id='st-page-titletext' macro='view title'></div>
<div class='subtitle'>
Created on <span macro='view created date [[MMM DD, 0hh:0mm]]'></span>.
Updated by <span macro='view modifier link'></span>
on <span macro='view modified date [[MMM DD, 0hh:0mm]]'></span></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></span></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
To use, add {{{[[Styles HorizontalMainMenu]]}}} to your StyleSheet tiddler.
See http://www.w3schools.com/css/css_colors.asp for a color chart.
***/
/*{{{*/
#mainMenu {position:relative;left:auto;width:auto;text-align:left;line-height:normal;padding 0em 1em 0em 1em;font-size:normal;}
#mainMenu br {display:none;}
#mainMenu {background:#336699;}
#mainMenu {padding:2px;}
#mainMenu .button, #mainMenu .tiddlyLink {padding-left:0.5em;padding-right:0.5em;color:white;font-size:115%;}

#displayArea {
	margin-top:0;margin-right:20em;margin-bottom:0;margin-left:1em;
	padding-top:.1em;padding-bottom:.1em;
}
/*}}}*/
|''Type:''|socialtext|
|''URL:''|https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443 |
|''Workspace:''|rot13|
|''WorkspaceList:''||
|''Description:''|Dobrica Pavlinušić's random unstructured stuff|
The TiddlySaver Java applet allows TiddlyWiki from a {{{file://}}} URL to save changes Safari, Opera and other browsers.

It is a small file named [["TiddlySaver.jar"|TiddlySaver.jar]] that must be placed in the same directory as your TiddlyWiki file. Before you can use it, you need to give it the necessary privileges by editting your {{{.java.policy}}} file.

For Windows, the file will be at {{{C:\Documents and Settings\your-user-name\.java.policy}}}. Add the following lines (substituting the directory of your TiddlyWiki file as appropriate):
{{{
grant codeBase "file:${user.home}/My Documents/tiddlywiki-folder/*" {
  permission java.io.FilePermission "${user.home}${/}My Documents${/}tiddlywiki-folder${/}*", "read,write";
};
}}}
On Mac OS X, the file is found at {{{/Users/your-user-name/.java.policy}}}:
{{{
grant codeBase "file:${user.home}/Documents/tiddlywiki-folder/*" {
  permission java.io.FilePermission "${user.home}${/}Documents${/}tiddlywiki-folder${/}*", "read,write";
};
}}}
It can be tricky creating files whose name starts with a period, so you can use this [[pre-built .java.policy file|.java.policy]]. The same file is suitable for Macs too, just edit it and delete the "My " bit, leaving just "Documents". Make sure you save it in the right place for each operating system!

If you have trouble setting up the permissions correctly, you can try granting broader permissions to the applet like this:

{{{
grant codeBase "file://localhost/home/users/Desktop/
TiddlySaver.jar"
 { permission java.security.AllPermission; };
}}}

Note that there is currently [[a bug|http://trac.tiddlywiki.org/ticket/172]] that prevents TiddlySaver from working if you have specified a backup directory in AdvancedOptions.
/***
|''Name:''|SocialtextLocaleOverrides|
|''Description:''|Text changes for Socialtext|
***/

//{{{
merge(config.views.wikified.tag,{
	labelNoTags: "No Tags",
	labelTags: "Tags"});

merge(config.commands.references,{
	text: "incoming links",
	tooltip: "Show tiddlers that link to this one",
	popupNone: "No incoming links"});
//}}}
/***
|''Name:''|SocialtextTweaksPlugin|
|''Description:''|Allows changes to be synchronised with a Socialtext server|
|''Source:''|http://stunplugged.tiddlywiki.com/#SocialtextTweaksPlugin|
|''Author:''|JeremyRuston (jeremy (at) osmosoft (dot) com)|
|''Version:''|1.0.2|
|''Date:''|Jun 15, 2006|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[BSD open source license]]|
|''~CoreVersion:''|2.2|

Make minor configuration tweaks specific to Socialtext Unplugged
***/

//{{{
// Ensure that the SocialtextTweaksPlugin is only installed once.
if(!version.extensions.SocialtextTweaksPlugin) {
version.extensions.SocialtextTweaksPlugin = {installed:true};
// Check version number of core code
if(version.major < 2 || (version.major == 2 && version.minor < 2))
	{alertAndThrow("SocialtextTweaksPlugin requires TiddlyWiki 2.2 or later.");}

merge(config.defaultCustomFields,{
	wikiformat:'socialtext',
	'server.host':'https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443'
});

config.options.chkSinglePageMode = true;
config.options.chkEnableAnimations = true;

} // end of "install only once"
//}}}
/***
|''Name:''|SocialtextFormatterPlugin|
|''Description:''|Allows Tiddlers to use [[Socialtext|http://www.socialtext.com/]] text formatting|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com)|
|''Source:''|http://www.martinswiki.com/#SocialtextFormatterPlugin|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/formatters/SocialtextFormatterPlugin.js|
|''Version:''|0.9.4|
|''Date:''|Jan 21, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.1.0|

This is the SocialtextFormatterPlugin, which allows you to insert Socialtext formated text into a TiddlyWiki.

The aim is not to fully emulate Socialtext, but to allow you to work with Socialtext content off-line and then resync the content with your Socialtext wiki later on, with the expectation that only minor edits will be required.

To use Socialtext format in a Tiddler, tag the Tiddler with SocialtextFormat or set the tiddler's {{{wikiformat}}} extended field to {{{socialtext}}}

Please report any defects you find at http://groups.google.co.uk/group/TiddlyWikiDev
***/

//{{{
// Ensure that the SocialtextFormatter Plugin is only installed once.
if(!version.extensions.SocialtextFormatterPlugin) {
version.extensions.SocialtextFormatterPlugin = {installed:true};

if(version.major < 2 || (version.major == 2 && version.minor < 1))
	{alertAndThrow('SocialtextFormatterPlugin requires TiddlyWiki 2.1 or later.');}

SocialtextFormatter = {}; // 'namespace' for local functions

wikify = function(source,output,highlightRegExp,tiddler)
{
	if(source && source != '') {
		var w = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
		var out = output;
		if(tiddler && (tiddler.isTagged(config.parsers.socialtextFormatter.formatTag) || (tiddler.fields.wikiformat==config.parsers.socialtextFormatter.format)) ) {
			var d1 = createTiddlyElement(output,'div','content-display-body','content-section-visible');
			var d2 = createTiddlyElement(d1,'div','wikipage');
			out = createTiddlyElement(d2,'div',null,'wiki');
		}
		var time1,time0 = new Date();
		w.subWikifyUnterm(out);
		if(tiddler && config.options.chkDisplayInstrumentation) {
			time1 = new Date();
			var t = tiddler ? tiddler.title : source.substr(0,10);
			displayMessage("Wikify '"+t+"' in " + (time1-time0) + " ms");
		}
	}
};

stDebug = function(out,str)
{
	createTiddlyText(out,str.replace(/\n/mg,'\\n').replace(/\r/mg,'RR'));
	createTiddlyElement(out,'br');
};

SocialtextFormatter.Tiddler_changed = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
	if((this.fields.wikiformat==config.parsers.socialtextFormatter.format) || this.isTagged(config.parsers.socialtextFormatter.formatTag)) {
		// update the links array, by checking for Socialtext format links
		this.links = [];
		var tiddlerLinkRegExp = /(?:\"(.*?)\" ?)?\[([^\]]*?)\]/mg;
		tiddlerLinkRegExp.lastIndex = 0;
		var match = tiddlerLinkRegExp.exec(this.text);
		while(match) {
			var link = match[2];
			this.links.pushUnique(link);
			match = tiddlerLinkRegExp.exec(this.text);
		}
	}/* else {
		return SocialtextFormatter.Tiddler_changed.apply(this,arguments);
	}*/
	this.linksUpdated = true;
};

SocialtextFormatter.wafl = function(w)
{
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var lm2 = lookaheadMatch[2];
		switch(lookaheadMatch[1]) {
		case 'image':
			var img = createTiddlyElement(w.output,'img');
			img.src = w.tiddler.title + '/' + lm2;
			createTiddlyText(img,lm2);
			break;
		case 'file':
			var s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			var a = createTiddlyElement(s,'a');
			a.href = w.tiddler.title + '/' + lm2;
			createTiddlyText(a,lm2);
			break;
		case 'link':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createTiddlyElement(s,'a');
			var t = w.tiddler ? w.tiddler.title + ':' : '';
			a.setAttribute('href','#' + t + lm2);
			a.title = 'section link';
			createTiddlyText(a,lm2);
			break;
		case 'weblog':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			var text = lm2;
			var link = 'Weblog: ' + lm2;
			createTiddlyText(createTiddlyLink(s,link,false,null,w.isStatic),text);
			break;
		case 'section':
			a = createTiddlyElement(w.output,'a');// drop anchor
			t = w.tiddler ? w.tiddler.title + ':' : '';
			a.setAttribute('name',t + lm2);
			break;
		case 'date':
			createTiddlyText(w.output,lm2);
			break;
		case 'user':
			var oldSource = w.source;
			w.source = lm2;
			w.nextMatch = 0;
			w.subWikifyUnterm(w.output);
			w.source = oldSource;
			break;
// Shortcut expansions - not strictly syntax
		case 'google':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://www.google.com/search?q='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'fedex':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://www.fedex.com/Tracking?tracknumbers='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'map':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://maps.google.com/maps?q='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'wikipedia':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://en.wikipedia.org/wiki/'+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'rt':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://rt.socialtext.net/Ticket/Display.html?id='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'stcal':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'https://calendar.socialtext.net:445/view_t.php?timeb=1&id=3&date='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'svn':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'https://repo.socialtext.net/listing.php?rev='+lm2+'sc=1');
			createTiddlyText(a,lm2);
			break;
		default:
			w.outputText(w.output,w.matchStart,w.nextMatch);
			return;
		}
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	} else {
		w.outputText(w.output,w.matchStart,w.nextMatch);
	}
};

SocialtextFormatter.presence = function(w)
{
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var p = lookaheadMatch[1];
		var text = lookaheadMatch[2];
		var link;
		var src;
		if(p=='aim') {
			link = 'aim:goim?screenname=' + text + '&message=hello';
			src = 'http://big.oscar.aol.com/sleepleft?on_url=http://www.aim.com/remote/gr/MNB_online.gif&amp;off_url=http://www.aim.com/remote/gr/MNB_offline.gif';
		} else if(p=='yahoo'||p=='ymsgr') {
			link = 'ymsgr:sendIM?'+text;
			src = 'http://opi.yahoo.com/online?u=chrislondonbridge&f=.gif';
		} else if(p=='skype'||p=='callto') {
			link = 'callto:'+text;
			src = 'http://goodies.skype.com/graphics/skypeme_btn_small_green.gif';
		} else if(p=='asap') {
			link = 'http://asap2.convoq.com/AsapLinks/Meet.aspx?l='+text;
			src = 'http://asap2.convoq.com/AsapLinks/Presence.aspx?l='+text;
		}
		var s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
		var a = createExternalLink(s,link);
		var img = createTiddlyElement(a,'img');
		createTiddlyText(a,text);
		img.src = src;
		img.border='0';
		img.alt = '(' + lookaheadMatch[1] + ')';
		if(p=='aim') {
			img.width='11'; img.height='13';
		}
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	}
};

config.formatterHelpers.singleCharFormat = function(w)
{
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[0].substr(lookaheadMatch[0].length-2,1) != ' ') {
		w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
	} else {
		w.outputText(w.output,w.matchStart,w.nextMatch);
	}
};

config.socialtext = {};
config.socialtext.formatters = [
{
	name: 'socialtextHeading',
	match: '^\\^{1,6} ?',
	termRegExp: /(\n+)/mg,
	handler: function(w)
	{
		var len = w.matchText.trim().length;
		var e = createTiddlyElement(w.output,'h' + len);
		var a = createTiddlyElement(e,'a');// drop anchor
		var t = w.tiddler ? w.tiddler.title + ':' : '';
		len = w.source.substr(w.nextMatch).indexOf('\n');
		a.setAttribute('name',t+w.source.substr(w.nextMatch,len));
		w.subWikifyTerm(e,this.termRegExp);
	}
},

{
	name: 'socialtextTable',
	match: '^\\|(?:(?:.|\n)*)\\|$',
	lookaheadRegExp: /^\|(?:(?:.|\n)*)\|$/mg,
	cellRegExp: /(?:\|(?:[^\|]*)\|)(\n|$)?/mg,
	cellTermRegExp: /((?:\x20*)\|)/mg,
	handler: function(w)
	{
		var table = createTiddlyElement(w.output,'table');
		var rowContainer = createTiddlyElement(table,'tbody');
		var prevColumns = [];
		w.nextMatch = w.matchStart;
		this.lookaheadRegExp.lastIndex = w.nextMatch;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
			var r = this.rowHandler(w,createTiddlyElement(rowContainer,'tr'),prevColumns);
			if(!r) {
				w.nextMatch++;
				break;
			}
			this.lookaheadRegExp.lastIndex = w.nextMatch;
			lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		}
	},
	rowHandler: function(w,e,prevColumns)
	{
		this.cellRegExp.lastIndex = w.nextMatch;
		var cellMatch = this.cellRegExp.exec(w.source);
		while(cellMatch && cellMatch.index == w.nextMatch) {
			w.nextMatch++;
			var cell = createTiddlyElement(e,'td');
			w.subWikifyTerm(cell,this.cellTermRegExp);
			if(cellMatch[1]) {
				// End of row
				w.nextMatch = this.cellRegExp.lastIndex;
				return true;
			}
			// Cell
			w.nextMatch--;
			this.cellRegExp.lastIndex = w.nextMatch;
			cellMatch = this.cellRegExp.exec(w.source);
		}
		return false;
	}
},

{
	name: 'socialtextList',
	match: '^[\\*#]+ ',
	lookaheadRegExp: /^([\*#])+ /mg,
	termRegExp: /(\n+)/mg,
	handler: function(w)
	{
		var stack = [w.output];
		var currLevel = 0, currType = null;
		var itemType = 'li';
		w.nextMatch = w.matchStart;
		this.lookaheadRegExp.lastIndex = w.nextMatch;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
			var listType = lookaheadMatch[1] == '*' ? 'ul' : 'ol';
			var listLevel = lookaheadMatch[0].length;
			w.nextMatch += listLevel;
			if(listLevel > currLevel) {
				for(var i=currLevel; i<listLevel; i++) {
					stack.push(createTiddlyElement(stack[stack.length-1],listType));
				}
			} else if(listLevel < currLevel) {
				for(i=currLevel; i>listLevel; i--) {
					stack.pop();
				}
			} else if(listLevel == currLevel && listType != currType) {
				stack.pop();
				stack.push(createTiddlyElement(stack[stack.length-1],listType));
			}
			currLevel = listLevel;
			currType = listType;
			var e = createTiddlyElement(stack[stack.length-1],itemType);
			w.subWikifyTerm(e,this.termRegExp);
			this.lookaheadRegExp.lastIndex = w.nextMatch;
			lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		}
	}
},

{
	name: 'socialtextQuoteByLine',
	match: '^>+',
	lookaheadRegExp: /^>+/mg,
	termRegExp: /(\n)/mg,
	element: 'blockquote',
	handler: function(w)
	{
		var stack = [w.output];
		var currLevel = 0;
		var newLevel = w.matchLength;
		var i;
		do {
			if(newLevel > currLevel) {
				for(i=currLevel; i<newLevel; i++) {
					stack.push(createTiddlyElement(stack[stack.length-1],this.element));
				}
			} else if(newLevel < currLevel) {
				for(i=currLevel; i>newLevel; i--) {
					stack.pop();
				}
			}
			currLevel = newLevel;
			w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
			createTiddlyElement(stack[stack.length-1],'br');
			this.lookaheadRegExp.lastIndex = w.nextMatch;
			var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
			var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
			if(matched) {
				newLevel = lookaheadMatch[0].length;
				w.nextMatch += newLevel;
			}
		} while(matched);
	}
},

{
	name: 'socialtextRule',
	match: '^----+$\\n+',
	handler: function(w)
	{
		createTiddlyElement(w.output,'hr');
	}
},

{
	name: 'socialtextPreformatted',
	match: '^\\.pre\\s*\\n',
	lookaheadRegExp: /^.pre\s*\n((?:.|\n)*?)\n.pre\s*\n/mg,
	element: 'pre',
	handler: config.formatterHelpers.enclosedTextHelper
},

{
	name: 'socialtextHtml',
	match: '^\\.html',
	lookaheadRegExp: /\.html((?:.|\n)*?)\.html/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			createTiddlyElement(w.output,'span').innerHTML = lookaheadMatch[1];
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'macro',
	match: '<<',
	lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
			w.nextMatch = this.lookaheadRegExp.lastIndex;
			invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
		}
	}
},

{
	name: 'socialtextExplicitLink',
	match: '(?:".*?" ?)?\\[',
	lookaheadRegExp: /(?:\"(.*?)\" ?)?\[([^\]]*?)\]/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var link = lookaheadMatch[2];
			var text = lookaheadMatch[1] ? lookaheadMatch[1] : link;
			createTiddlyText(createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler),text);
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'socialtextExternalLink',
	match: '(?:".*?" ?)?<[a-z]{2,8}:',
	lookaheadRegExp: /(?:\"(.*?)\" ?)?<([a-z]{2,8}:.*?)>/mg,
	imgRegExp: /\.(?:gif|ico|jpg|png)/g,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var link = lookaheadMatch[2];
			var text = lookaheadMatch[1] ? lookaheadMatch[1] : link;
			this.imgRegExp.lastIndex = 0;
			if(this.imgRegExp.exec(link)) {
				var img = createTiddlyElement(w.output,'img');
				if(lookaheadMatch[1]) {
					img.title = text;
				}
				img.alt = text;
				img.src = link;
			} else {
				createTiddlyText(createExternalLink(w.output,link),text);
			}
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'socialtextUrlLink',
	match: config.textPrimitives.urlPattern,
	handler: function(w)
	{
		w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch);
	}
},

{
	name: 'socialtextBold',
	match: '\\*(?![\\s\\*])',
	lookaheadRegExp: /\*(?!\s)(?:.*?)(?!\s)\*(?=[$\s\|\._\-,])/mg,
	termRegExp: /((?!\s)\*(?=[$\s\|\.\-_,]))/mg,
	element: 'strong',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextItalic',
	match: '_(?![\\s_])',
	lookaheadRegExp: /_(?!\s)(?:.*?)(?!\s)_(?=[$\s\|\.\*\-,])/mg,
	termRegExp: /((?!\s)_(?=[$\s\|\.\*\-,]))/mg,
	element: 'em',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextStrike',
	match: '-(?![\\s\\-])',
	lookaheadRegExp: /-(?!\s)(?:.*?)(?!\s)-(?=[$\s\|\.\*_,])/mg,
	termRegExp: /((?!\s)-(?=[$\s\|\.\*_,]))/mg,
	element: 'del',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextMonoSpaced',
	match: '`(?![\\s`])',
	lookaheadRegExp: /`(?!\s)(?:.*?)(?!\s)`(?=[$\s\.\*\-_,])/mg,
	termRegExp: /((?!\s)`(?=[$\s\.\*\-_,]))/mg,
	element: 'tt',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextParagraph',
	match: '\\n{2,}',
	handler: function(w)
	{
		createTiddlyElement(w.output,'p');
	}
},

{
	name: 'socialtextLineBreak',
	match: '\\n',
	handler: function(w)
	{
		createTiddlyElement(w.output,'br');
	}
},

{
	name: 'socialtextNoWiki',
	match: '\\{\\{',
	lookaheadRegExp: /\{\{((?:.|\n)*?)\}\}/mg,
	element: 'span',
	handler: config.formatterHelpers.enclosedTextHelper
},

{
	name: 'socialtextTrademark',
	match: '\\{tm\\}',
	handler: function(w)
	{
		createTiddlyElement(w.output,'span').innerHTML = '&trade;';
	}
},

{
	name: 'socialtextWafl',
	match: '\\{(?:[a-z]{2,16}): ?.*?\\}',
	lookaheadRegExp: /\{([a-z]{2,16}): ?(.*?)\}/mg,
	handler: SocialtextFormatter.wafl
},

{
	name: 'socialtextPresence',
	match: '(?:aim|yahoo|ymsgr|skype|callto|asap):\\w+',
	lookaheadRegExp: /(aim|yahoo|ymsgr|skype|callto|asap):(\w+)/mg,
	handler: SocialtextFormatter.presence
},

{
	name: 'socialtextMailTo',
	match: '[\\w\.]+@[\\w]+\.[\\w\.]+',
	lookaheadRegExp: /([\w\.]+@[\w]+\.[\w\.]+)/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var text = lookaheadMatch[1];
			createTiddlyText(createExternalLink(w.output,'mailto:'+text),text);
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'socialtextHtmlEntitiesEncoding',
	match: '&#?[a-zA-Z0-9]{2,8};',
	handler: function(w)
	{
		createTiddlyElement(w.output,'span').innerHTML = w.matchText;
	}
}
];

config.parsers.socialtextFormatter = new Formatter(config.socialtext.formatters);
config.parsers.socialtextFormatter.format = 'socialtext';
config.parsers.socialtextFormatter.formatTag = 'SocialtextFormat';

} // end of 'install only once'
//}}}
/***
|''Name:''|SocialtextAdaptorPlugin|
|''Description:''|Adaptor for moving and converting data to and from Socialtext Wikis|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com) and JeremyRuston (jeremy (at) osmosoft (dot) com)|
|''Source:''|http://www.martinswiki.com/#SocialtextAdaptorPlugin|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/adaptors/SocialtextAdaptorPlugin.js|
|''Version:''|0.5.1|
|''Date:''|Feb 25, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|

Socialtext REST documentation is at:
http://www.eu.socialtext.net/st-rest-docs/index.cgi?socialtext_rest_documentation

***/

//{{{
if(!version.extensions.SocialtextAdaptorPlugin) {
version.extensions.SocialtextAdaptorPlugin = {installed:true};

function SocialtextAdaptor()
{
	this.host = null;
	this.workspace = null;
	return this;
}

SocialtextAdaptor.mimeType = 'text/x.socialtext-wiki';
SocialtextAdaptor.serverType = 'socialtext';
SocialtextAdaptor.serverParsingErrorMessage = "Error parsing result from server";
SocialtextAdaptor.errorInFunctionMessage = "Error in function SocialtextAdaptor.%0";

SocialtextAdaptor.prototype.setContext = function(context,userParams,callback)
{
	if(!context) context = {};
	context.userParams = userParams;
	if(callback) context.callback = callback;
	context.adaptor = this;
	if(!context.host)
		context.host = this.host;
	if(!context.workspace && this.workspace)
		context.workspace = this.workspace;
	return context;
};

SocialtextAdaptor.doHttpGET = function(uri,callback,params,headers,data,contentType,username,password)
{
	return doHttp('GET',uri,data,contentType,username,password,callback,params,headers);
};

SocialtextAdaptor.doHttpPOST = function(uri,callback,params,headers,data,contentType,username,password)
{
	return doHttp('POST',uri,data,contentType,username,password,callback,params,headers);
};

SocialtextAdaptor.fullHostName = function(host)
{
	if(!host)
		return '';
	if(!host.match(/:\/\//))
		host = 'http://' + host;
	if(host.substr(host.length-1) != '/')
		host = host + '/';
	return host;
};

SocialtextAdaptor.minHostName = function(host)
{
	return host ? host.replace(/^http:\/\//,'').replace(/\/$/,'') : '';
};

// Convert a page title to the normalized form used in uris
SocialtextAdaptor.normalizedTitle = function(title)
{
	var n = title.toLowerCase();
	n = n.replace(/\s/g,'_').replace(/\//g,'_').replace(/\./g,'_').replace(/:/g,'').replace(/\?/g,'');
	if(n.charAt(0)=='_')
		n = n.substr(1);
	return String(n);
};

// Convert a Socialtext date in YYYY-MM-DD hh:mm format into a JavaScript Date object
SocialtextAdaptor.dateFromEditTime = function(editTime)
{
	var dt = editTime;
	return new Date(Date.UTC(dt.substr(0,4),dt.substr(5,2)-1,dt.substr(8,2),dt.substr(11,2),dt.substr(14,2)));
};

SocialtextAdaptor.prototype.openHost = function(host,context,userParams,callback)
{
	this.host = SocialtextAdaptor.fullHostName(host);
	context = this.setContext(context,userParams,callback);
	if(context.callback) {
		context.status = true;
		window.setTimeout(function() {callback(context,userParams);},0);
	}
	return true;
};

SocialtextAdaptor.prototype.openWorkspace = function(workspace,context,userParams,callback)
{
	this.workspace = workspace;
	context = this.setContext(context,userParams,callback);
	if(context.callback) {
		context.status = true;
		window.setTimeout(function() {callback(context,userParams);},0);
	}
	return true;
};


SocialtextAdaptor.prototype.getWorkspaceList = function(context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);
	var uriTemplate = '%0data/workspaces';
	var uri = uriTemplate.format([context.host]);
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getWorkspaceListCallback,context,{'accept':'application/json'});
	return typeof req == 'string' ? req : true;
};

SocialtextAdaptor.getWorkspaceListCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getWorkspaceListCallback']);
	if(status) {
		try {
			eval('var info=' + responseText);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		var list = [];
		for(var i=0; i<info.length; i++) {
			var item = {
				title:info[i].title,
				name:info[i].name,
				modified:SocialtextAdaptor.dateFromEditTime(info[i].modified_time)
				};
			list.push(item);
		}
		context.workspaces = list;
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.getTiddlerList = function(context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);
	var uriTemplate = '%0data/workspaces/%1/pages?order=newest';//!! ? or ;
	var uri = uriTemplate.format([context.host,context.workspace]);
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerListCallback,context,{'accept':'application/json'});
	return typeof req == 'string' ? req : true;
};


SocialtextAdaptor.getTiddlerListCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getTiddlerListCallback']);
	if(status) {
		try {
			eval('var info=' + responseText);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		var list = [];
		for(var i=0; i<info.length; i++) {
			var tiddler = new Tiddler(info[i].name);
			tiddler.modified = SocialtextAdaptor.dateFromEditTime(info[i].last_edit_time);
			tiddler.modifier = info[i].last_editor;
			tiddler.tags = info[i].tags;
			tiddler.fields['server.page.id'] = info[i].page_id;
			tiddler.fields['server.page.name'] = info[i].name;
			tiddler.fields['server.page.revision'] = String(info[i].revision_id);
			list.push(tiddler);
		}
		context.tiddlers = list;
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.generateTiddlerInfo = function(tiddler)
{
	var info = {};
	var host = this && this.host ? this.host : SocialtextAdaptor.fullHostName(tiddler.fields['server.host']);
	var workspace = this && this.workspace ? this.workspace : tiddler.fields['server.workspace'];
	uriTemplate = '%0%1/index.cgi?%2';
	info.uri = uriTemplate.format([host,workspace,SocialtextAdaptor.normalizedTitle(tiddler.title)]);
	return info;
};

SocialtextAdaptor.prototype.getTiddler = function(title,context,userParams,callback)
{
	return this.getTiddlerRevision(title,null,context,userParams,callback);
};

SocialtextAdaptor.prototype.getTiddlerRevision = function(title,revision,context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);

	// request the page in json format to get the page attributes
	if(revision) {
		var uriTemplate = '%0data/workspaces/%1/pages/%2/revisions/%3';
		context.revision = revision;
	} else {
		uriTemplate = '%0data/workspaces/%1/pages/%2';
		context.revision = null;
	}
	uri = uriTemplate.format([context.host,context.workspace,SocialtextAdaptor.normalizedTitle(title),revision]);

	context.tiddler = new Tiddler(title);
	context.tiddler.fields.wikiformat = 'socialtext';
	context.tiddler.fields['server.host'] = SocialtextAdaptor.minHostName(context.host);
	context.tiddler.fields['server.workspace'] = context.workspace;
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerCallback,context,{'accept':'application/json'});
	return typeof req == 'string' ? req : true;
};


SocialtextAdaptor.getTiddlerCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getTiddlerCallback']);
	if(status) {
		try {
			eval('var info=' + responseText);
			context.tiddler.tags = info.tags;
			context.tiddler.fields['server.page.id'] = info.page_id;
			context.tiddler.fields['server.page.name'] = info.name;
			context.tiddler.fields['server.page.revision'] = String(info.revision_id);
			context.tiddler.modifier = info.last_editor;
			context.tiddler.modified = SocialtextAdaptor.dateFromEditTime(info.last_edit_time);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
		if(context.callback)
			context.callback(context,context.userParams);
		return;
	}
	var uriTemplate = context.revision ? '%0data/workspaces/%1/pages/%2/revisions/%3' : '%0data/workspaces/%1/pages/%2';
	var host = SocialtextAdaptor.fullHostName(context.tiddler.fields['server.host']);
	var workspace = context.workspace ? context.workspace : context.tiddler.fields['server.workspace'];
	uri = uriTemplate.format([host,workspace,SocialtextAdaptor.normalizedTitle(context.tiddler.title),context.revision]);
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerCallback2,context,{'accept':SocialtextAdaptor.mimeType});
};

SocialtextAdaptor.getTiddlerCallback2 = function(status,context,responseText,uri,xhr)
{
	context.tiddler.text = responseText;
	if(status) {
		context.status = true;
	} else {
		context.status = false;
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.getTiddlerRevisionList = function(title,limit,context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);

	var uriTemplate = '%0data/workspaces/%1/pages/%2/revisions?accept=application/json';
	if(!limit)
		limit = 5;
	var uri = uriTemplate.format([context.host,context.workspace,SocialtextAdaptor.normalizedTitle(title),limit]);

	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerRevisionListCallback,context);
	return typeof req == 'string' ? req : true;
};

SocialtextAdaptor.getTiddlerRevisionListCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	if(status) {
		var content = null;
		try {
			eval('var info=' + responseText);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		list = [];
		for(var i=0; i<info.length; i++) {
			var tiddler = new Tiddler(info[i].name);
			tiddler.modified = SocialtextAdaptor.dateFromEditTime(info[i].last_edit_time);
			tiddler.modifier = info[i].last_editor;
			tiddler.tags = info[i].tags;
			tiddler.fields['server.page.id'] = info[i].page_id;
			tiddler.fields['server.page.name'] = info[i].name;
			tiddler.fields['server.page.revision'] = info[i].revision_id;
			list.push(tiddler);
		}
		var sortField = 'server.page.revision';
		list.sort(function(a,b) {return a.fields[sortField] < b.fields[sortField] ? +1 : (a.fields[sortField] == b.fields[sortField] ? 0 : -1);});
		context.revisions = list;
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.putTiddler = function(tiddler,context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);
	context.tiddler = tiddler;
	context.title = tiddler.title;
	var uriTemplate = '%0data/workspaces/%1/pages/%2';
	var host = context.host ? context.host : SocialtextAdaptor.fullHostName(tiddler.fields['server.host']);
	var workspace = context.workspace ? context.workspace : tiddler.fields['server.workspace'];
	var uri = uriTemplate.format([host,workspace,tiddler.title,tiddler.text]);
	//var req = doHttp('POST',uri,tiddler.text,SocialtextAdaptor.mimeType,null,null,SocialtextAdaptor.putTiddlerCallback,context,{"X-Http-Method": "PUT"});
	var req = SocialtextAdaptor.doHttpPOST(uri,SocialtextAdaptor.putTiddlerCallback,context,{"X-Http-Method": "PUT"},tiddler.text,SocialtextAdaptor.mimeType);
	return typeof req == 'string' ? req : true;
};

SocialtextAdaptor.putTiddlerCallback = function(status,context,responseText,uri,xhr)
{
	if(status) {
		context.status = true;
	} else {
		context.status = false;
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.close = function()
{
	return true;
};

config.adaptors[SocialtextAdaptor.serverType] = SocialtextAdaptor;
} //# end of 'install only once'
//}}}
/***
SocialtextStyleOverrides
***/

/*{{{*/
.headerShadow {padding: 2em 0em .5em 1em;}
.headerForeground {padding: 2em 0em .5em 1em;}

#st-page-wiki-title {
	font-size: 80%;
}
.subtitle {
	font-style: italic;
	font-size 80%;
}

/* from #st-tags */
.tagged {
	border-color: #bbeebb;
	background-color: #f4fff4;
}

.tagged .listTitle {
	color: #595;
	font-weight: bold;
}

.tagged .button {
	color: #000;
}

.selected .tagged {
	background-color: ColorPalette::TertiaryLight;
	border: 1px solid ColorPalette::TertiaryMid;
}

/* from #st-incoming-links */
.tagging {
	border-color: #ebb;
	background-color: #fff4f4;
}

.tagging .listTitle {
	color: #b78;
	font-weight: bold;
}

.tagging .button {
	color: #999;
}

.selected .tagging {
	background-color: ColorPalette::TertiaryLight;
	border: 1px solid ColorPalette::TertiaryMid;
}

.tiddler {/* Tiddler body */
	border:1px solid #ccc;
	margin:0.5em;
	background:#fff;
	padding:0.5em;
}

.viewer blockquote {border-left: 0px solid}

.tiddlyLinkNonExisting {
	font-style: italic;
	border-bottom: 1px dashed;
}

.editor input, .editor textarea {
	background: #ffd;
	border-style: solid;
	border-color: #888 #ccc #ccc #888;
	border-width: 2px;
}

.tabContents {white-space: nowrap;}

#displayArea {margin: 1em 20em 0em 14em;}

#sidebar {
	position: absolute;
	right: 3px;
	width: 21em;
	font-size: .9em;
}

#sidebarOptions .button {
	border-color: #eee;
}

#sidebarTabs .tabContents {
	width: 20em;
	overflow: hidden;
}

.viewer tt {
	font-size: 1.2em;
	line-height: 1.4em;
}

ul {list-style-type: square;}
ul ul {list-style-type: circle;}

ol {list-style-type: decimal;}
ol ol {list-style-type: decimal;}
ol ol ol {list-style-type: decimal;}
ol ol ol ol {list-style-type: decimal;}
ol ol ol ol ol {list-style-type: decimal;}
ol ol ol ol ol ol {list-style-type: decimal;}

/*}}}*/
/***
SocialtextScreenStyle
http://www.eu.socialtext.net/static/2.0.0.1/css/st/screen.css
***/

/*{{{*/
body {
	font-family: Arial, sans-serif;
	color: #000;
	background: #eee;
	margin: 0;
}

/* Wiki Navigation */

.st-wiki-nav {
	clear: both;
	margin-left: 10px;
	margin-right: 10px;
}
.st-wiki-nav-content {
	background: url('../../images/st/wiki-nav/solid.gif') repeat-x left bottom;
	margin-left: 24px;
	margin-right: 24px;
	padding-top: 3px;
	min-height: 24px;
}
* html .st-wiki-nav-content {
	padding-bottom: 3px;
	height: 24px;
}

.st-wiki-nav-right {
	background: url('../../images/st/wiki-nav/right-round.gif') no-repeat bottom right;
}

.st-wiki-nav-left {
	background: url('../../images/st/wiki-nav/left-round.gif') no-repeat bottom left;
}

#st-home {
	float: left;
	margin-right: 60px;
	padding-top: 2px;
}

#st-home-link {
	color: white;
	text-decoration: none;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	font-size: 90%;
}

#st-editing-prefix-container {
	border-collapse: collapse;
	width: 100%;
	padding: 0px;
	margin: 0px;
	margin-bottom: -20px;
}

#st-editing-prefix-container tr td {
	margin: 0px;
	padding: 0px;
}

#st-editing-title {
	color: black;
	background-color: white;
	text-decoration: none;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	margin-bottom: 0.4em;
}

#st-wiki-title-invite {
	font-size: 50%;
	font-family: Helvetica, sans-serif;
}

#st-wiki-title-central-page-link {
	font-size: 50%;
	font-family: Helvetica, sans-serif;
}

#st-wiki-title-invite a {
	color: #00f;
}

#st-wiki-logo {
	text-align: center;
	clear: both;
}

#st-wiki-logo-image {
}

.st-wiki-nav-actions {
	float: right;
	color: black;
	font-size: 75%;
	padding-top: 3px;
}

.st-wiki-nav-actions a {
	padding: 2px;
	color: white;
	text-decoration: none;
	font-family: Helvetica, sans-serif;
}

/* Wiki Subnav */

#st-wiki-subnav {
	margin-top: 2px;
	font-size: 70%;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	color: #888;
}

#st-wiki-subnav a {
	padding: 2px;
	color: #008;
	text-decoration: none;
}

#st-wiki-subnav-right {
	float: right;
	margin-right: 6em;
}

#st-wiki-subnav-left {
	float: left;
	margin-left: 6em;
}
* html #st-wiki-subnav-left {
	margin-left: 3em;
}

/* Wiki Navigation Search Bar */

#st-search-form {
	margin: 0;
	padding: 0;
	padding-top: 1px;
}

#st-search-form .button-table {
	float: left;
	font-size: 79%;
	font-weight: bold;
	margin-left: 5px;
	margin-top: 1px;
}

#st-search-form #st-search-term {
	float: left;
	font-size: 60%;
}

/* Content Outline */

#st-content-border, #st-edit-border {
	position: relative;
	clear: both;
	margin-left: 3px;
	margin-right: 2px;
	margin-bottom: 0px;
	margin-top: 0px;
	border-bottom: 1px solid #eee;
}

#st-content-border-left, #st-edit-border-left {
	background: url('../../images/st/page-shadow/left.gif') left top repeat-y;
	position: relative;
}

#st-content-border-right, #st-edit-border-right {
	background: url('../../images/st/page-shadow/right.gif') right top repeat-y;
	position: relative;
}

#st-content-border-top, #st-edit-border-top {
	position: relative;
	background: url('../../images/st/page-shadow/top.gif') left top repeat-x;
}

#st-content-border-bottom, #st-edit-border-bottom {
	background: url('../../images/st/page-shadow/bottom.gif') left bottom repeat-x;
	position: relative;
}

#st-content-border-left-top, #st-edit-border-left-top {
	background: url('../../images/st/page-shadow/left-top.gif') left top no-repeat;
	position: relative;
}
#st-content-border-right-top, #st-edit-border-right-top {
	background: url('../../images/st/page-shadow/right-top.gif') right top no-repeat;
	position: relative;
}

#st-content-border-left-bottom, #st-edit-border-left-bottom {
	background: url('../../images/st/page-shadow/left-bottom.gif') left bottom no-repeat;
	position: relative;
}

#st-content-border-right-bottom, #st-edit-border-right-bottom {
	background: url('../../images/st/page-shadow/right-bottom.gif') right bottom no-repeat;
	padding-top: 5px;
	padding-bottom: 9px;
	position: relative;
}

* html #st-content-border-right-bottom, * html #st-edit-border-right-bottom {
	padding-top: 4px;
	padding-left: 7px;
	padding-right: 8px;
	position: relative;
}

.st-content-width-controller {
	width: 100%;
	position: relative;
	border-collapse: collapse;
}
.st-content-width-controller td {
	vertical-align: top;
}
.st-content {
	position: relative;
	background-color: white;
	margin-top: 0px;
	margin-left: 7px;
	margin-right: 8px;
	margin-bottom: -1px;
	border-left: 1px dotted #80a9f3;
	border-right: 1px dotted #80a9f3;
	border: 1px solid #80a9f3;
	padding: 6px 12px 12px 12px;
}
* html .st-content {
	margin-top: 0px;
	margin-left: 0px;
	margin-right: 0px;
}

/* This textarea is only for Safari. However, if we use display:none; here Safari ignores the .value operation in JS */
#st-raw-wikitext-textarea {
	width:1px;
	height:1px;
	margin:0;
	padding:0;
}

/* Action Buttons */
.button-table, .button-table tr td {
	border-collapse: collapse;
	margin: 0;
	padding: 0;
}
.button-rounded {
	background: url('../../images/st/grey-button/left-top-rounded.png') top left no-repeat;
	margin: 0;
}
.button-rounded-right-top {
	background: url('../../images/st/grey-button/right-top-rounded.png') top right no-repeat;
	margin: 0;
}
.button-rounded-left-bottom {
	background: url('../../images/st/grey-button/left-bottom-rounded.png') bottom left no-repeat;
	margin: 0;
}
.button-rounded-right-bottom {
	background: url('../../images/st/grey-button/right-bottom-rounded.png') bottom right no-repeat;
	margin: 0;
}
.button-straight {
	background: url('../../images/st/grey-button/left-top-straight.png') top left no-repeat;
	margin: 0;
}
.button-straight-right-top {
	background: url('../../images/st/grey-button/right-top-straight.png') top right no-repeat;
	margin: 0;
}
.button-straight-left-bottom {
	background: url('../../images/st/grey-button/left-bottom-straight.png') bottom left no-repeat;
	margin: 0;
}
.button-straight-right-bottom {
	background: url('../../images/st/grey-button/right-bottom-straight.png') bottom right no-repeat;
	margin: 0;
}
.button-content {
	font-size: 90%;
}
.button-content a {
	display: block;
	padding: 2px;
	padding-left: 10px;
	padding-right: 10px;
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	text-decoration: none;
	color: black;
}

.button-content input.submit {
	border: 0px;
	padding: 2px;
	padding-left: 10px;
	padding-right: 10px;
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	text-decoration: none;
	color: black;
	background-color: transparent;
}

/* Personal Homepage */

#st-homepage {
	background: white url('../../images/st/homepage/blue-fade.gif') top left no-repeat;
}

#st-homepage-layout {
	margin-top: 15px;
	clear: both;
	width: 100%;
	border-collapse: collapse;
}

#st-homepage-layout tr td.st-homepage-layout-cell {
	padding: 5px;
	vertical-align: top;
}

#st-homepage-layout-dashboard {
	width: 50%
}

#st-homepage-layout-notes {
	width: 50%;
}

#st-homepage-notes, #st-homepage-dashboard {
	text-align: left;
	width: 95%;
}

#st-user-greeting, #st-wiki-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 150%;
}
#st-wiki-title {
	margin-left: 5px;
}

#st-user-greeting {
	position: relative;
	text-align: right;
	float: right;
}

#st-group-notes-content, #st-personal-notes-content {
}

.st-homepage-section {
	margin-bottom: 15px;
}

#st-homepage-notes .st-homepage-section {
	background-color: white;
	border: 1px solid #aaa;
	padding: 15px;
}

.st-homepage-section-title {
	font-size: 110%;
	font-family: Helvetica, Verdana, sans-serif;
}

#st-homepage-notes .st-homepage-section-title {
	color: #aaa;
	text-decoration: underline;
}

.st-homepage-notes-edit-link {
	background: url('../../images/st/homepage/edit-icon.gif') no-repeat left top;
	display: block;
	text-indent: -2000px;
	height: 13px;
	width: 36px;
	text-decoration: none;
	padding:0;
}
* html .st-homepage-notes-edit-link {
	border:1px solid white;
}

.st-homepage-notes-edit {
	font-family: Verdana, sans-serif;
	font-size: 65%;
	float: right;
}

.st-homepage-notes-content {
	font-size: 85%;
	margin-top: 10px;
	padding-top: 0px;
	padding-bottom: 0px;
	font-family: Verdana, Helvetica, sans-serif;
}

#st-dyk {
	border-color: #cca !important;
	background-color: #ffe !important;
}

#st-dyk-title {
	color: #e4a020 !important;
	text-decoration: none !important;
}


/* Homepage Simple List */

#st-whats-new-title-link {
	background: url('../../images/st/homepage/icon-28-pages.gif') no-repeat left top;
}
#st-watchlist-title-link {
	background: url('../../images/st/homepage/icon-28-star.gif') no-repeat left top;
}
#st-wikis-title-link {
	background: url('../../images/st/homepage/icon-28-group.gif') no-repeat left top;
}
.st-homepage-simplelist-title-link {
	display: block;
	padding-left: 32px;
	min-height: 32px;
}
* html .st-homepage-simplelist-title-link {
	height: 32px;
}

.st-homepage-simplelist-title {
}

.st-homepage-simplelist-table {
	margin-left: 25px;
	border: 1px dashed #ddd;
	border-collapse: collapse;
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 80%;
	width: 95%;
}

.st-homepage-simplelist-table td {
	padding: 2px;
}

.st-homepage-simplelist-table tr.st-homepage-simplelist-row-odd {
	background-color: #f3f7f7;
}

.st-homepage-simplelist-table tr.st-homepage-simplelist-row-even {
	background-color: white;
}

.st-homepage-simplelist-table a {
	color: #4f55dd;
	text-decoration: none;
}

.st-homepage-simplelist-table a:visited {
	color: #551a8b;
}

.st-homepage-simplelist-subleft {
	font-size: 80%;
	margin-left: 1em;
	color: #666;
}

.st-homepage-simplelist-right {
	width: 20%;
}

.st-homepage-simplelist-subright {
	font-size: 80%;
	color: #666;
}

.st-homepage-simplelist {
}

.st-homepage-simplelist-header {
	min-height: 35px;
}

.st-homepage-simplelist-header .button-table {
	float: right;
	margin-right: 15px;
	font-size: 95%;
}

.st-homepage-simplelist-header .button-table .button-content {
	padding: 1px;
}

.st-homepage-whatsnew-author, .st-homepage-whatsnew-date {
	color: #555;
}
.st-homepage-whatsnew-attribution {
	padding-left: 1em;
	font-size: 80%;
	color: #aaa;
}

/* Homepage Wikis List */

#st-wikis-title {
}

/* Data and Templates */

.st-jst-template, .st-json {
	display: none;
}

/* Page Sidebox Common Styles */

#st-page-boxes-toggle {
	position: relative;
	float: right;
	text-align: right;
	font-family: Verdana, Arial, sans-serif;
	font-weight: bold;
	font-size: 80%;
	margin-bottom: 0.7em;
}

#st-page-boxes-toggle-link {
	text-decoration: none;
}

#st-page-boxes-underlay {
	float: right;
	margin-top: -10px;
	margin-right: 10px;
	background: white;
	z-index: 198;
	clear: both;
	margin-left: 15px;
}
* html #st-page-boxes-underlay {
	margin-right: 4px;
}
#st-page-boxes {
	background: inherit;
	position: absolute;
	right: 23px;
	z-index: 199;
	margin-top: 15px;
	margin-left: 20px;
}
#st-page-boxes, #st-page-boxes-underlay {
	width: 225px;
	/* padding-left: 15px; */ /* Gives the white border effect, cwest dislikes it. */
}

.st-page-box {
	border: 1px solid black;
	padding: 5px;
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 80%;
	margin-top: 15px;
}

.st-page-box-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	margin-bottom: 10px;
}

.st-page-box-listing {
	margin: 0;
	padding: 0;
}

.st-page-box-listing-entry {
	display: block;
}

.st-page-boxes-nobacklinks {
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 90%;
	color: #888;
}

.st-page-box-first {
	margin-top: 0px;
}

/* Page Display */

#st-page-content {
	clear: left;
	margin-top: 6px;
	margin-bottom: 0;
	padding-bottom: 0;
}

#st-page-content, #st-page-content td {
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 90%;
}

#st-page-wiki-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 65%;
	font-weight: bold;
	color: #aaa;
	margin-bottom: 0.2em;
	margin-top: 0.1em;
	padding-top: 0;
}

#wiki {
	margin: 0;
	padding: 0;
}

#st-page-title {
}

#st-page-titletext, .st-page-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 150%;
	font-weight: bold;
	color: #888;
	border-bottom: 1px solid #888;
}

#st-newpage-pagename-edit {
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	color: #000;
	border: 1px solid black;
	padding-left: 0.3em;
	background-color: #ffd;
}

#st-page-details {
	font-style: italic;
	font-size: 75%;
	font-family: Georgia, serif;
	margin: 6px 10px 0 10px;
}

#st-page-details-feed-icon {
	vertical-align: middle;
	border: none;
}

#st-page-stats {
	float: right;
	vertical-align: middle;
}

#st-attribution {
	float: left;
	margin-bottom: 10px;
}

#st-page-editing-wysiwyg {
	background: #ffd;
	border-style: solid;
	border-color: #888 #ccc #ccc #888;
	border-width: 2px;
	width: 100%;
}

#st-page-editing-toolbar {
	margin-left: -6px;
	overflow: hidden;
	float: left;
	height: 25px;
}

#wikiwyg_wikitext_textarea {
	margin-top: 4px;
	background: #ffd;
	border-style: solid;
	border-color: #888 #ccc #ccc #888;
	border-width: 2px;
	width: 100%;
	font-family: monospace;
}

#st-page-maincontent {
}

#st-page-editing, #wikiwyg_wikitext_textarea {
}

#st-page-editing-pagebody-decoy, #st-page-editing-wysiwyg {
	display: none;
}

#st-editing-tools-edit {
	display: none;
}

#st-mode-wysiwyg-button
{
	font-size: 70%;
	margin-left: 4em;
}

#st-mode-wikitext-button
{
	font-size: 70%;
}

#st-edit-tips
{
	font-size: 70%;
}

.wikiwyg_button {
	background: #FFFFFF;
	border: 1px solid #FFFFFF;
	cursor: pointer;
	width: 20px;
	height: 20px;
	vertical-align: bottom;
}

.wikiwyg_button:hover {
	border: 1px outset;
}

.wikiwyg_button:active {
	border: 1px inset;
}

#wikiwyg_toolbar {
	display: none;
}

/* Sidebox Pagetools: Revisions, Watchlist */
#st-side-box-pagetools {
	border-collapse: collapse;
}

#st-rewind-norevisions {
	font-family: Helvetica, Arial, sans-serif;
	font-size: 11px;
	color: #777;
	text-decoration: none;
}

#st-side-box-pagetools a {
	font-family: Helvetica, Arial, sans-serif;
	font-size: 11px;
	color: #555;
	text-decoration: none;
}

/* Page View Tags/Incoming Links Sidebox */

#st-tags {
	background: #f4fff4;
	border-color: #bbeebb;
	color: #999;
}

#st-tags-title {
	color: #595;
}

#st-tags-addlink, #st-tags-addbutton {
	font-weight: bold;
}

#st-tags-listing {
	margin-bottom: 5px;
}

#st-tags-addinput, #st-tags-message, #st-tags-suggestion {
	display: none;
}

#st-tags-deletemessage {
	font-size: 90%;
	color: #555;
	display: none;
	margin-top: 0.5em;
	margin-bottom: 0.5em;
}

#st-tags-suggestion {
	margin-top: 2px;
}

.st-tags-level1 {
	font-size: 90%;
}

.st-tags-level2 {
	font-size: 100%;
}

.st-tags-level3 {
	font-size: 110%;
}

.st-tags-level4 {
	font-size: 120%;
}

.st-tags-level5 {
	font-size: 130%;
}

.st-tags-tagline .st-tags-tagdelete {
	text-decoration: none;
	color: #ccc;
}

.st-tags-tagline a {
	text-decoration: none;
	color: #444;
}

#st-tags-field {
	width: 95%;
}

#st-incoming-links {
	border-color: #ebb;
	background-color: #fff4f4;
}

#st-incoming-links-title {
	color: #b78;
}

#st-attachments {
	border-color: #bbe;
	background-color: #f4f4ff;
}

#st-attachments-uploadbutton, #st-attachments-managebutton {

}
#st-attachments-buttons-uploadbutton {
	margin: 0px;
	padding: 0px;
	padding-left: 2px;
}
#st-attachments-buttons-managebutton {
	margin: 0px;
	padding: 0px;
	padding-right: 2px;
}

#st-attachments-buttons td {
	padding-right: 3px;
	font-size: 99%;
}

#st-attachments-buttons {
	border-collapse: collapse;
	margin: 0px;
	padding: 0px;
	margin-top: 5px;
}

#st-attachments-title {
	color: #77b;
}

.st-attachments-line {
	width:100%;
	overflow:hidden;
}

/* Actions Bar */

#st-actions-bar-spacer {
	clear:both;
	height:0.5em;
	overflow:hidden;
}

#st-actions-bar-spacer-clear {
	clear:both;
	height:1px;
	overflow:hidden;
}


#st-actions-bar, #st-editing-tools-bar {
	margin-left: 30px !important;
	margin-right: 30px !important;
}

/* Footer */
#st-footer {
	margin-top: -8px;
	margin-bottom: 5px;
	clear: both;
}

/* Socialtext Attribution */

#st-socialtext-attribution {
	clear: both;
	text-align: center;
	font-size: 80%;
	font-family: Helvetica, sans-serif;
}

#st-socialtext-attribution-link {
	text-decoration: none;
}

#st-socialtext-attribution-image {
	border: 0;
}


/* Page Actions */

#st-edit-button-border-left-middle, #st-login-to-edit-button-border-left-middle {
	background: url('../../images/st/button-blue/left-middle.gif') left top repeat-y;
}
#st-edit-button-border-right-middle, #st-login-to-edit-button-border-right-middle {
	background: url('../../images/st/button-blue/right-middle.gif') right top repeat-y;
}

#st-edit-button-border-left-top, #st-login-to-edit-button-border-left-top {
	background: url('../../images/st/button-blue/left-top.gif') left top no-repeat;
}
#st-edit-button-border-right-top, #st-login-to-edit-button-border-right-top {
	background: url('../../images/st/button-blue/right-top.gif') right top no-repeat;
}

#st-edit-button-border-left-bottom, #st-login-to-edit-button-border-left-bottom {
	background: url('../../images/st/button-blue/left-bottom.gif') left bottom no-repeat;
}

#st-edit-button-border-right-bottom, #st-login-to-edit-button-border-right-bottom {
	background: url('../../images/st/button-blue/right-bottom.gif') right bottom no-repeat;
}

#st-edit-button-link, #st-login-to-edit-button-link {
}

#st-comment-button-border-left-middle {
	background: url('../../images/st/button-purple/left-middle.gif') left top repeat-y;
}

#st-comment-button-border-right-middle {
	background: url('../../images/st/button-purple/right-middle.gif') right top repeat-y;
}

#st-comment-button-border-left-top {
	background: url('../../images/st/button-purple/left-top.gif') left top no-repeat;
}

#st-comment-button-border-right-top {
	background: url('../../images/st/button-purple/right-top.gif') right top no-repeat;
}

#st-comment-button-border-left-bottom {
	background: url('../../images/st/button-purple/left-bottom.gif') left bottom no-repeat;
}

#st-comment-button-border-right-bottom {
	background: url('../../images/st/button-purple/right-bottom.gif') right bottom no-repeat;
}

#st-comment-button-link {
}

#st-save-button-border-left-middle {
	background: url('../../images/st/button-green/left-middle.gif') left top repeat-y;
}
#st-save-button-border-right-middle {
	background: url('../../images/st/button-green/right-middle.gif') right top repeat-y;
}

#st-save-button-border-left-top {
	background: url('../../images/st/button-green/left-top.gif') left top no-repeat;
}
#st-save-button-border-right-top {
	background: url('../../images/st/button-green/right-top.gif') right top no-repeat;
}

#st-save-button-border-left-bottom {
	background: url('../../images/st/button-green/left-bottom.gif') left bottom no-repeat;
}

#st-save-button-border-right-bottom {
	background: url('../../images/st/button-green/right-bottom.gif') right bottom no-repeat;
}

#st-save-button-link {
}

#st-preview-button-border-left-middle {
	background: url('../../images/st/button-gold/left-middle.gif') left top repeat-y;
}
#st-preview-button-border-right-middle {
	background: url('../../images/st/button-gold/right-middle.gif') right top repeat-y;
}

#st-preview-button-border-left-top {
	background: url('../../images/st/button-gold/left-top.gif') left top no-repeat;
}
#st-preview-button-border-right-top {
	background: url('../../images/st/button-gold/right-top.gif') right top no-repeat;
}

#st-preview-button-border-left-bottom {
	background: url('../../images/st/button-gold/left-bottom.gif') left bottom no-repeat;
}

#st-preview-button-border-right-bottom {
	background: url('../../images/st/button-gold/right-bottom.gif') right bottom no-repeat;
}

#st-preview-button-link {
}

#st-cancel-button-border-left-middle {
	background: url('../../images/st/button-crimson/left-middle.gif') left top repeat-y;
}
#st-cancel-button-border-right-middle {
	background: url('../../images/st/button-crimson/right-middle.gif') right top repeat-y;
}

#st-cancel-button-border-left-top {
	background: url('../../images/st/button-crimson/left-top.gif') left top no-repeat;
}
#st-cancel-button-border-right-top {
	background: url('../../images/st/button-crimson/right-top.gif') right top no-repeat;
}

#st-cancel-button-border-left-bottom {
	background: url('../../images/st/button-crimson/left-bottom.gif') left bottom no-repeat;
}

#st-cancel-button-border-right-bottom {
	background: url('../../images/st/button-crimson/right-bottom.gif') right bottom no-repeat;
}

#st-cancel-button-link {
}

#st-edit-more-button-border-left-middle {
	background: url('../../images/st/button-blue/left-middle.gif') left top repeat-y;
}
#st-edit-more-button-border-right-middle {
	background: url('../../images/st/button-blue/right-middle.gif') right top repeat-y;
}

#st-edit-more-button-border-left-top {
	background: url('../../images/st/button-blue/left-top.gif') left top no-repeat;
}
#st-edit-more-button-border-right-top {
	background: url('../../images/st/button-blue/right-top.gif') right top no-repeat;
}

#st-edit-more-button-border-left-bottom {
	background: url('../../images/st/button-blue/left-bottom.gif') left bottom no-repeat;
}

#st-edit-more-button-border-right-bottom {
	background: url('../../images/st/button-blue/right-bottom.gif') right bottom no-repeat;
}

#st-edit-more-button-link {
}

.st-page-action-button-link {
	min-height: 24px;
	min-width: 100px;
	text-align: center;
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 90%;
	text-decoration: none;
	color: #fff;
	font-weight: bold;
	display: block;
	padding-top: 8px;
	padding-bottom: 0px;
	margin-bottom: -3px;
	width: 100%;
	margin-left: -2px;
}
* html .st-page-action-button-link {
	padding-top: 5px;
	padding-bottom: 0px;
	height: 24px;
}

.st-page-action-button {
	float: left;
	margin: 0;
	padding: 0;
	margin-right: 10px;
	min-height: 20px;
	border-collapse: collapse;
	width: 100px;
}

/* Attach File Interface */

#st-attachments-attachinterface {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	display: none;
	position: fixed;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	z-index: 2000;
	background-image: url('../../images/st/popup/bg.png');
}
#st-attachments-manageinterface {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	display: none;
	position: absolute;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	z-index: 2000;
	background-image: url('../../images/st/popup/bg.png');
}

* html #st-attachments-attachinterface {
	background-image: none;
}
* html #st-attachments-manageinterface {
	background-image: none;
}
* html .popup-overlay {
	background-image: url('../../images/st/popup/bg.png');
	background-color: #000;
	opacity: .70;
	position: absolute;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	z-index: 2001;
}

#st-attachments-attach-interface {
	z-index: 2002;
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 1em;
	width: 520px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position: absolute;
	top: 0px;
}

* html #st-attachments-attach-interface {
}

#st-attachments-attach-formtarget {
	width: 0px;
	height: 0px;
	border: 0;
	padding: 0;
	margin: 0;
}

#st-attachments-attach-message {
	font-size: 90%;
	font-family: Verdana, Arial, Helvetica, Sans-Serif;
}

#st-attachments-attach-title {
	font-weight: bold;
	font-size: 120%;
}

#st-attachments-attach-close {
	float: right;
	margin-top: 6px;
}

#st-attachments-attach-uploadbutton {
	float: right;
	margin-right: 6px;
	margin-top: 6px;
	padding-bottom: 0;
}

#st-attachments-attach-fileprompt {
	margin: 0.2em 0 0.4em 0;
	padding-bottom: 0px;
}

#st-attachments-attach-submit {
	font-size: 90%;
	font-weight: bold;
}

#st-attachments-attach-filename {
	font-size: 90%;
}

#st-attachments-attach-uploadmessage {
	font-weight: bold;
	margin-bottom: 1em;
	display: none;
}

#st-attachments-attach-error {
	font-weight: bold;
	color: #f00;
	margin-bottom: 1em;
	display: none;
}

#st-attachments-attach-list {
	display: none;
	color: #666;
	font-size: 90%;
	margin-top: 1em;
	margin-bottom: 1em;
	border-top: 1px solid #4949BA;
	border-bottom: 1px solid #4949BA;
	background-color: #F5F5F5;
	padding: 3px;
}

.st-attachments-attach-listlabel {
	font-size: 90%;
	color: #4949BA;
}

/* Queue File Dialog */

#st-attachmentsqueue-interface {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	display: none;
	position: fixed;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	background-image: url('../../images/st/popup/bg.png'); /* Don't forget IE hack for ship! */
	z-index: 2000;
}

* html #st-attachmentsqueue-interface {
	background-image: none;
}

#st-attachmentsqueue-dialog {
	z-index: 2002;
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 1em;
	width: 530px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position: absolute;
	top: 0px;
}

* html #st-attachmentsqueue-dialog {
}

#st-attachmentsqueue-fileprompt {
	margin-bottom: 0.4em;
	margin-top: 0;
	padding-bottom: 0;
}

#st-attachmentsqueue-title {
	font-weight: bold;
	font-size: 120%;
}

#st-attachmentsqueue-close {
	float: right;
	margin-top: 6px;
}

#st-attachmentsqueue-uploadbutton {
	float: right;
	margin-right: 6px;
	margin-top: 6px;
	padding-bottom: 0;
}

#st-attachmentsqueue-submit {
	font-size: 90%;
}

#st-attachmentsqueue-filename {
	font-size: 90%;
}

#st-attachmentsqueue-message {
	font-size: 90%;
	font-family: Verdana, Arial, Helvetica, Sans-Serif;
}

#st-attachmentsqueue-uploadmessage {
	font-weight: bold;
	margin-bottom: 1em;
	display: none;
}

#st-attachmentsqueue-error {
	font-weight: bold;
	color: #f00;
	margin-bottom: 1em;
	display: none;
}

#st-attachmentsqueue-list {
	display: none;
	color: #666;
	font-size: 90%;
	margin-top: 1em;
	margin-bottom: 1em;
	border-top: 1px solid #4949BA;
	border-bottom: 1px solid #4949BA;
	background-color: #F5F5F5;
	padding: 3px;
}

.st-attachmentsqueue-listlabel {
	font-size: 90%;
	color: #4949BA;
}

/* Lists */

tr.st-trbg-even, tr.st-trbg-even td{
	background-color: #f3f7f7;
}

tr.w-st-even-row, tr.w-st-even-row td {
	background-color: #f3f7f7;
}

.query-results-header-title, .query-results-header-last-edit-by {
	text-align: left;
}


.query-results-row-revisions {
	text-align: right;
}

.query-results-content {
	font-size: 85%;
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.query-results-row {
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.query-results-row a {
	text-decoration: underline;
	color: #00f;
}

.query-results-row td {
	font-family: Verdana;
	padding: 0.3em;
	border-left: 1px dashed #ddd;
	border-right: 1px dashed #ddd;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;
}

.query-results-header-row {
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.query-results-header-row a {
	text-decoration: underline;
	color: #00f;
}

.query-results-header-row th {
	font-family: Helvetica;
	padding: 0.3em;
	border-left: 1px dashed #ddd;
	border-right: 1px dashed #ddd;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;
}

div.st-actionbutton {
	float: left;
}

div#deleteme-st-actions-bar {
	clear: both;
	margin: 0.8em 20px 0.2em auto;
	padding: 0;
}

/* Manage File Interface */



#st-attachments-manage-interface {
	z-index: 2002;
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 1em;
	width: 520px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position: absolute;
	top: 0px;
}

#st-attachments-manage-filetable {
	height: 150px;
	margin: 0;
	padding: 0;
	width: 100%;
	overflow: auto;
	border: 1px solid #ccc;
}

#st-attachments-manage-filelisting tbody td {
	font-size: 90%;
}
#st-attachments-manage-filelisting {
	width: 100%;
	border-collapse: collapse;
	border: 0;
	margin: 0;
	padding: 0;
}

#st-attachments-manage-fileheader {
	background: #ccc;
	font-weight: bold;
	border-bottom: 1px black solid;
}

#st-attachments-manage-close {
	float: right;
	margin-top: 3px;
	margin-right: -2px;
	font-weight: bold;
}

#st-attachments-manage-delete {
	margin-top: 3px;
	float: left;
	font-weight: bold;
}

.st-attachments-manage-filerow {
	border-bottom: 1px solid #ccc;
}

.row-odd {
	background-color: #eee;
}

.row-even {
	background-color: #fff;
}

.row-on {
	background-color: #009 !important;
	color: white !important;
}

.row-on a {
	color: #fff !important;
}

#st-attachments-manage-deletemessage {
	color: red;
}

/* Page tools icons */

#st-pagetools-print {
	background: url('../../images/st/pagetools/print.gif')
	left center no-repeat;
}

#st-pagetools-email {
	background: url('../../images/st/pagetools/email.gif')
	left center no-repeat;
}

#st-pagetools-tools {
	background: url('../../images/st/pagetools/tools.gif')
	left center no-repeat;
}

/*
 #st-pagetools-watch {
	background: url('../../images/st/pagetools/watch-blue.gif')
	left center no-repeat;
}
*/


/* *********** Settings *********** */

#st-settings-pane {
}
* html #settings-pane { font-size: 85%;}

.settings-start-table {
}
* html .settings-start-table { font-size: 90%;}

#st-settings-select {
	padding: 0px 10px 10px 10px;
	vertical-align: top;
	width: 1px;

	background-color: #eff1ec;
	border: none;
}

#st-settings-section {
	padding: 0px 10px 10px 10px;
	vertical-align: top;
}

.settings-top-header {
	margin-top: 1em;
	font-weight: bold;
	width: 15em;
}

.settings-header {
	margin-top: 1em;
	font-weight: bold;
}

.settings-selections {
	padding: 0px 0px 0px 20px;
	line-height: 1.5em;
}

.settings-selections a:visited, .settings-selections a:active {
	color: #0000ff;
}

.settings-link {
	clear: both;
	display: block;
}

.settings-section-left {
	text-align: right;
}

.settings-label {
	font-weight: bold;
}

.settings-help {
	color: #888;
}

.settings-comment {
}

.users-invite-message {
	padding: 0.5em 0.5em 0.5em 2em;
	background-color: #eee;
	/* This seems necessary to fix an IE bug that sometimes
		causes the text in this div to be invisible */
	z-index: 1000;
}

.workspace-entry-header {
	margin-top: .5em;
	font-weight: bold;
}

.workspace-entry {
	margin-left: 3em;
}

.workspace-entry-p {
	margin-top: .5em;
	margin-bottom: .75em;
}

.workspace-subentry {
	font-style: italic;
	font-weight: bold;
	margin-left: 1.5em;
}

.preferences-td {
	padding:.5em 0 1.5em 0;
}

.preferences-query {
	text-align: left;
}

.preference-radio {
	background-color: #cec;
}
.user-settings-listall-headings td {
	background-color: #eff3ef;
}

#st-settings-save {
	padding-bottom: 0.5em;
}

.standard-button-cancel {
	font-weight: bold;
	background-color: #71004b;

	border-left: 1px solid #aaa;
	border-top: 1px solid #aaa;
	border-bottom: 2px solid #333;
	border-right: 2px solid #333;
	color: #f4f3b9;
	width: 8em;
}

.standard-button-submit {
	font-weight: bold;
	background-color: #656084;

	border-left: 1px solid #aaa;
	border-top: 1px solid #aaa;
	border-bottom: 2px solid #333;
	border-right: 2px solid #333;
	color: #f4f3b9;
	width: 8em;
}

#st-settings {
	font-family: Verdana, Arial, Helvetica, Sans-Serif;
	font-size: 90%;
}


/* Listview Tabs */


#st-listview a:visited {
	color: #551a8b;
}
#st-listview-tabs ul {
	display: block;
	list-style: none outside;
	margin: 0 0 0 4em;
	padding: 0;
	font-family: Helvetica, Arial, Sans-serif;
	font-size: 80%;
}

#st-listview-tabs li {
	display: block;
	float: left;
	margin: 0 0.8em 0 0;
	padding: 3px 0.6em 0 0.6em;
	border: 1px solid #d8d8d8;
	border-bottom: 1px solid rgb(128, 169, 243);
	background-color: #f4f4f4;
	position: relative;
	bottom: -2px;
}

#st-listview-tabs li.spacer {
	margin: 0 0.8em 0 2em;
}

#st-listview-tabs a {
	color: #bbb;
	text-decoration: none;
}

#st-listview-tabs li.selected {
	background-color: #fff !important;
	border: 1px solid rgb(128, 169, 243) !important;
	border-bottom: 1px solid #fff !important;
	font-weight: bold !important;
}

#st-listview-tabs li.selected a {
	color: #000 !important;
}

/* Category List Display */

#st-category-display-links {
	margin-bottom: 1em;
	font-size: 90%;
}

#st-tag-listbody {
	font-family: Helvetica, Verdana, sans-serif;
}

/* Attachments List Display */

#st-attachments-list-body table.button-table {
	margin-top: 0.1em;
	font-size: 80%;
}


/* ********** PageTools Menu ************** */

div#st-editing-tools {
	float: left;
}

div#st-pagetools {
	z-index: 300;
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 10px;
	float: right;
	margin: 18px 0 0 0em;
	color: #000;
	vertical-align: bottom;
	position: relative;
}

#st-pagetools a {
	text-decoration: none;
	color: black;
	padding-left: 17px;
}

#st-pagetools span {
	color: inherit;
	padding-left: 17px;
	vertical-align: top;
}

#st-pagetools span.st-watchlist-link {
	color: inherit;
	vertical-align: top;
}

.st-watchlist-link {
	cursor: pointer;
}

div#st-pagetools ul.level2 {
	z-index: 300;
	margin: 0;
	padding: 0;
	background: white;
	border: 1px solid #CCC;
	border-width: 0 1px;
}

div#st-pagetools li {
	position: relative;
	list-style: none;
	margin: 0;
	float: left;
	width: 7em;
	line-height: 11px;
}

div#st-pagetools ul ul li:hover {
	background: #BFE2FF;
}

div#st-pagetools li a {
	display: block;
	text-decoration: none;
}

div#st-pagetools>ul a {
	width: auto;
}

div#st-pagetools ul ul {
	position: absolute;
	width: auto;
	display: none;
}

div#st-pagetools ul ul li {
	line-height: 1.5em;
/*	width: 100%; */
	width: 14em;
}

.first {
	border-top: 1px solid #CCC;
}

.separator {
	border-bottom: 1px solid #CCC;
}

div#st-pagetools ul ul li a {
	border-bottom: 1px solid #CCC;
	padding-left: 15px;
	padding-right: 3px;
	margin-right: 3px;
	border: 0px;
}

div#st-pagetools li.submenu li.submenu:hover {
	z-index: 300;
	background-color: #BFE2FF;
}

div#st-pagetools ul.level1 li.submenu:hover ul.level2 {
	display:block;
}

div#st-pagetools ul.level2 {
	top: 1.0em;
	left: -9.5em;
}

/*

=head2 Revision List Display

Change these styles to update the page revision list.

*/

#st-revision-list-table {
	border-collapse: collapse;
	font-size: 85%;
	color: #000;
}

.st-page-title-decorator {
	color: #C80000;
}

.st-revision-header-emphasis {
	color: #C80000;
}

.st-revision-list-compare-button-row {
}

.st-revision-list-compare-button-cell {
	padding-top: 0.3em;
	text-align: center;
}

.st-revision-list-compare-button {
}

#st-revision-list-header-row {
}

#st-revision-list-header-select {
	padding: 6px 2px 2px 2px;
	text-align: center;
}

#st-revision-list-header-revision {
	padding: 6px 2px 2px 2px;
	text-align: left;
}

#st-revision-list-header-edited-by {
	padding: 6px 2px 2px 2px;
	text-align: center;
}

#st-revision-list-header-date {
	padding: 6px 2px 2px 2px;
	text-align: center;
}

.st-revision-list-row {
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.st-revision-list-row td {
	font-family: Verdana;
	padding: 0.3em;
	border-left: 1px dashed #ddd;
	border-right: 1px dashed #ddd;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;
}

.st-revision-list-row-select {
	padding: 3px 0 2px 0;
	text-align: center;
}

.st-revision-list-row-select-old {
}

.st-revision-list-row-select-new {
}

.st-revision-list-row-revision {
}

.st-revision-list-row-revision-link {
}

.st-revision-list-row-edited-by {
}

.st-revision-list-row-date {
}

/* Revision Menu */

#st-pagetools.st-revision-view-bar {
	float: left;
}

ul.st-revision-menu {
	list-style: none;
	margin: 0;
	padding: 0.2em;
	font-size: 80%;
}

ul.st-revision-menu li {
	float: left;
	padding: 0 0.4em 0 0.4em;
	border-right: thin solid #000000;
}

ul.st-revision-menu li.st-last {
	border-right: none;
}

#st-restore-revision-button {
	font-size: 80%;
}

/*

=head2 Revision Compare Display

When comparing two revisions of a page, these styles apply.

*/

#st-revision-compare-table {
	background-color: #f0f0f0;
}

#st-revision-compare-table td {
	background-color: white;
}

.st-revision-compare-old {
	background-color: #fdd;
	text-decoration: line-through;
}
.st-revision-compare-new {
	background-color: #dfd;
	font-weight: bold;
}

/* Weblog View */

#st-weblog {
	padding: 0;
}

#st-content-weblog-display-width-controller {
}
#st-content-weblog-display-width-controller-nav {
	width: 230px;
	margin-left: 15px;
	border-left: 5px solid #ddd;
	margin-top: -1px;
}

#st-weblog-content {
	font-family: Verdana, Helvetica, sans-serif;
	margin-top: -1px;
	margin-bottom: -1px;
	border-top: 1px solid #80a9f3;
	border-bottom: 1px solid #80a9f3;
}

#st-weblog-title {
	font-family: 'Trebuchet MS', Verdana, Helvetica, sans-serif;
	font-family: 'Times New Roman', serif;
	background-color: #80a9f3;
	color: #fff;
	font-size: 150%;
	font-weight: bold;
	padding: 0.2em;
	padding-left: 1em;
}

#st-weblog-wikititle {
	font-family: Helvetica, Verdana, sans-serif;
	font-style: italic;
	font-size: 40%;
	color: #fff;
	margin-bottom: 0.2em;
	margin-top: 0.1em;
	padding-top: 0;
}

#st-weblog-titletext {
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	color: #fff;
}

div.st-weblog-entry {
	margin-top: 0.2em;
	margin-bottom: 4.8em;
	padding: 0 1.5em 0 1.5em;
}

.st-page-title {
	clear: both;
}

div.st-weblog-entrytitle span.text {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 150%;
	font-weight: bold;
	color: #000;
}

.st-weblog-entrycontent {
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 90%;
	border-bottom: 1px solid #888;
}

.st-weblog-byline {
	float: left;
	text-align: left;
	font-style: italic;
	font-size: 70%;
	font-family: Verdana, Helvetica, sans-serif;
}

.st-weblog-post-links {
	float: right;
	text-align: right;
	font-size: 70%;
	font-family: Verdana, Helvetica, sans-serif;
}

#st-weblog-archives, #st-weblog-navigation {
	position: relative;
	float: right;
	width: 230px;
}

#st-weblog-archives {
	margin-top: 15px;
	clear: right;
}

#st-weblog-archives-title, #st-weblog-navigation-title {
	margin-left: 15px;
	font-family: Helvetica, sans-serif;
	font-size: 95%;
	font-weight: bold;
	color: #999;
	border-bottom: 2px solid #f99;
	padding-bottom: 5px;
	padding-top: 5px;
	margin-bottom: 5px;
}

#st-weblog-navigation-content {
	margin-left: 15px;
	font-size: 80%;
}

#st-weblog-archives ul {
	margin: 0;
	padding: 0;
}

#st-weblog-archives ul li {
	/* list-type: none; */
	display: block;
	font-size: 80%;
	font-family: Helvetica, sans-serif;
	padding-left: 15px;
}

#st-weblog-newpost {
	padding: 0.5em 0.7em 0.3em 0.3em;
}

#st-weblog-newpost-button {
}

#st-weblog-actionbar-chooseweblog {
	float: right;
}

#st-weblog-postbyemail {
	font-size: 70%;
	font-family: Verdana, Helvetica, sans-serif;
	color: #def;
	padding-top: 0.4em;
}

#st-weblog-postbyemail-link {
	color: #00c;
}

.st-weblog-chooseprompt {
	font-size: 90%;
	font-family: Verdana, Helvetica, sans-serif;
	padding-right: 0.2em;
	color: #000;
}

.st-spacer {
	padding-right: 0.1em;
	padding-left: 0.1em;
}

.st-weblog-preventries {
	padding-bottom: 20px;
	clear: both;
}
.st-weblog-nextentries {
	clear: both;
}

div.st-weblog-entrynav {
	margin-top: 0.2em;
	margin-bottom: 1.8em;
	padding: 0;
}

span.st-weblog-previousentries, span.st-weblog-nextentries {
	font-size: 90%;
	font-family: Verdana, Helvetica, sans-serif;
	padding-left: 1em;
}

/* ******* Page Stats ******** */

#st-usagereport-navbar {
	font-size: 80%;
	padding: 0;
	margin: 0;
}

#st-usagereport-date {
	font-weight: bold;
	margin-top: 1em;
}

#st-page-usagereport h1 {
	font-size: 1.3em;
	font-weight: bold;
	margin-top: 1.2em;
	margin-bottom: 0.3em;
}

#st-page-usagereport h2 {
	font-size: 1.1em;
	font-weight: bold;
	margin-top: 0.8em;
	margin-bottom: 0.3em;
}

/* New Page */
#st-newpage-save, #st-newpage-duplicate {
	display: none;
	position: fixed;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	background: url('../../images/st/popup/bg.png'); /* Don't forget IE hack for ship! */
	z-index: 2000;
}

#st-newpage-save-interface {
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 0.5em;
	width: 450px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position:absolute;
	top:0px;
	z-index:2003;
}

#st-newpage-duplicate-interface {
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 0.5em;
	width: 530px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position:absolute;
	top:0px;
	z-index:2003;
}

#st-newpage-save-title, #st-newpage-duplicate-title {
	margin: 0;
	padding: 0;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	font-size: 100%;
}

#st-newpage-save-prompt, #st-newpage-duplicate-prompt {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	margin-bottom: 0.4em;
}

#st-newpage-save-buttons, #st-newpage-duplicate-buttons {
	margin-top: 0.8em;
	text-align: right;
}

.st-newpage-duplicate-option {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	margin: 0;
	padding: 0;
}

#st-newpage-duplicate-pagename {
	font-size: 90%;
}

.st-newpage-duplicate-emphasis {
	background-color: #FFFF00;
	font-weight: bold;
}

#st-newpage-save-field-pagename {
	margin-bottom: 0;
	margin-top: 0.2em;
	padding-bottom: 0;
	font-size: 90%;
}

#st-newpage-save-tip {
	margin-bottom: 0;
	margin-top: 1.2em;
	padding-bottom: 0;
	font-size: 75%;
	color: #888;
}

/* Wikitext Styling */

.wiki {
}

.wiki hr {
	margin-top: .4em;
	margin-bottom: .4em;
}

.wiki .short-rule {
	width: 25%;
}

.wiki .medium-rule {
	width: 50%
}

.wiki ul,
.wiki ol,
.wiki blockquote {
	margin-left: 2em;
	padding-left: 0em;
}

.wiki table {
	border-collapse: collapse;
}

.wiki td {
	border: 1px;
	border-style: solid;
	padding: .2em;
	vertical-align: top;
}

.wiki h1,
.wiki h2,
.wiki h3,
.wiki h4,
.wiki h5,
.wiki h6 {
	font-weight: bold;
	font-style: normal;
	margin-top: 0.1em;
	margin-bottom: 8px;
}

.wiki h1 {font-size: 200%;}
.wiki h2 {font-size: 170%;}
.wiki h3 {font-size: 145%;}
.wiki h4 {font-size: 125%;}
.wiki h5 {font-size: 110%;}
.wiki h6 {font-size: 100%;}

.wiki pre {
	background-color: #eee; /* XXX */
	margin-left: 1em;
	margin-right: 1em;
	padding: .2em;
}

.wiki .incipient {
	text-decoration: none;
	border-bottom: 1px dashed;
}

.wiki-include-title {
	background-color: #ccccff;
}

.wiki .wiki {
	position: relative;
	background-color: #ddddff;
	border: 1px solid #ccccff;
	padding: 3px;
}

.wafl_existence_error {
	color: rgb(200,0,0);
	border-bottom: 0.2em dashed rgb(200,0,0);
}

#st-edit-mode-container {
}

#st-edit-mode-view {
}

#st-page-editing-uploadbutton {
	z-index: 1500;
	float: left;
}

/* Comment UI */


body#st-commentui {
	background: #ffffff;
}

#st-commentui-container {
}

#st-commentui-container a:visited,
#st-commentui-container a:active {
	color: #00f;
}

#st-commentui-notetop {
}

#st-commentui-controls {
}

#st-commentui-savelink {
	background-color: #fffebd;
}

#st-commentui-cancellink {
}

#st-commentui-customfield {
}

#st-commentui-customfield .customfield-label {
}

#st-commentui-customfield .customfield-input {
}

#st-commentui-textarea {
	padding: 0;
	border-style: inset;
	border-width: thin;
	background-color: #ffd;
	color: black;
	width: 99%;
	height: 150px;
}

/*

=head2 Send Page by Email

Styles for the 'Send Page by Email' popup, accessed from the 'Email' dropdown
menu on the page bar.

*/

#email-page {
	background: #ffffff;
	font-size: 80%;
}

.email-page-row {
	clear: both;
}

.email-page-row-label {
	font-weight: bold;
	float: left;
	width: 5em;
	margin-left: 1.2em;
	margin-right: 1.2em;
	text-align: right;
}

.email-page-row-content {
	float: left;
	padding-bottom: 1.2em;
}

.email-page-user-select-column {
	float: left;
	padding-right: 1.2em;
	width: 14em;
}

#email-page-user-select-column-center {
	width: 10em;
}

.email-page-user-select-label {
	text-align: center;
}

#email-page-user-select-add-label {
	padding-top: 1em;
}

.email-page-user-select-button-group {
	padding-bottom: 2em;
}

.email-page-input {
	width: 120px;
	clear: both;
	display: block;
}


.email-page-select {
	width: 175px;
	font-size: x-small;
}

#email-page-error-message {
	text-align: center;
}

#email-page-buttons-container {
	clear: both;
}

#email-page-buttons {
	text-align: center;
}

.email-page-input-new {
	width: 175px;
}

/* System Status, Red with icon */

#st-system-status-alert {
	clear: both;
	width: 50%;
	margin-left: 25%;
	margin-top: 10px;
	padding: 5px;
	color: #c00;
	font-weight: bold;
	font-size: 80%;
	background: transparent url('../../images/st/system-message/important-note.gif') no-repeat 5px center;
	padding-left: 60px;
	min-height: 38px;
}
* html #st-system-status-alert {
	height: 38px;
}

/* System Status, Green */

#st-system-status {
	clear: both;
	text-align:center;
	width: 80%;
	margin-left: 10%;
	padding: 8px 0 3px 0;
	color: #0a0;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 80%;
}

.socialtextLogo {
	text-align: center;
}
/*}}}*/
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
This is the home page for Dobrica Pavlinušić's random unstructured stuff.

Welcome to my new unsorted stuff site. If you are here to "learn about rot13"<http://en.wikipedia.org/wiki/ROT13> this might not be the right place.

If you are, however looking latest and/or unsorted snippets which didn't made to "my homepage"<http://www.rot13.org/~dpavlin/> or "blog"<http://blog.rot13.org/> you might be on right place.

| {search: category: projects} | {search: category: howto} | {recent_changes: rot13} |

{fetchrss: http://blog.rot13.org/index.xml}
* serial programming https://balau82.wordpress.com/2010/06/13/emulating-8051-serial-port-communication-on-linux/

^ vendors

* [STC]
* [STM8]
{toc: }

^ ZFS

^^ MySQL

* http://www.mysqlconf.com/mysql2009/public/schedule/detail/7121
* http://assets.en.oreilly.com/1/event/21/Optimizing%20MySQL%20Performance%20with%20ZFS%20Presentation.pdf
* http://www.youtube.com/watch?v=a31NhwzlAxs

^^^ cache only metadata for Innodb

.pre
zfs set primarycache=metadata tank/db
.pre

^^^ match recordsize to block size

before creating database

.pre
zfs set recordsize=16k tank/db
.pre


^ root filesystem on zfs

based on https://github.com/zfsonlinux/zfs/wiki/HOWTO-install-Debian-GNU-Linux-to-a-Native-ZFS-Root-Filesystem

.pre
root@lib10:~# apt-get install zfs-initramfs

root@lib10:~# zfs create -o mountpoint=none lib10/ROOT

root@lib10:~# zfs create -o mountpoint=/ lib10/ROOT/debian-1
cannot mount '/': directory is not empty
filesystem successfully created, but not mounted

root@lib10:~# zpool set bootfs=lib10/ROOT/debian-1 lib10

root@lib10:~# mkdir /tmp/root
root@lib10:~# mount --bind / /tmp/root/

root@lib10:~# mkdir /tmp/zfs-root
root@lib10:~# zfs set mountpoint=/tmp/zfs-root lib10/ROOT/debian-1
root@lib10:~# zfs mount lib10/ROOT/debian-1
root@lib10:~# zfs set compression=lz4 lib10/ROOT
root@lib10:~# rsync -ravH --numeric-ids /tmp/root/ /tmp/zfs-root/

# duh, source btrfs had snapshot on it

root@lib10:~# rsync -ravH --numeric-ids --exclude '/.snapshot' --exclude '/tmp' --delete /tmp/root/ /tmp/zfs-root/

root@lib10:~# zfs umount lib10/ROOT/debian-1

root@lib10:~# cd /tmp/zfs-root/

root@lib10:~# cd /tmp/zfs-root/
root@lib10:/tmp/zfs-root# mount --bind /dev dev/
root@lib10:/tmp/zfs-root# mount --bind /sys sys/
root@lib10:/tmp/zfs-root# mount --bind /proc/ proc/
root@lib10:/tmp/zfs-root# chroot .
root@lib10:/# 

root@lib10:~# df
Filesystem          1K-blocks    Used Available Use% Mounted on
lib10/ROOT/debian-1 195788544 1149184 194639360   1% /
udev                 10270376       0  10270376   0% /dev
root@lib10:~# mount /boot/
root@lib10:~# df
Filesystem          1K-blocks    Used Available Use% Mounted on
lib10/ROOT/debian-1 195787904 1149184 194638720   1% /
udev                 10270376       0  10270376   0% /dev
/dev/sdg1              198337   62072    136265  32% /boot

root@lib10:~# grep zfs /etc/default/grub 
GRUB_CMDLINE_LINUX_DEFAULT="boot=zfs rpool=lib10 bootfs=lib10/ROOT/debian-1"

root@lib10:~# update-grub

root@lib10:~# grep zfs /boot/grub/grub.cfg 
insmod zfs
        linux   /vmlinuz-4.8.0-2-amd64 root=ZFS=lib10/ROOT/debian-1 ro  boot=zfs rpool=lib10 bootfs=lib10/ROOT/debian-1
                linux   /vmlinuz-4.8.0-2-amd64 root=ZFS=lib10/ROOT/debian-1 ro  boot=zfs rpool=lib10 bootfs=lib10/ROOT/debian-1
                linux   /vmlinuz-4.8.0-1-amd64 root=ZFS=lib10/ROOT/debian-1 ro  boot=zfs rpool=lib10 bootfs=lib10/ROOT/debian-1


root@lib10:~# update-initramfs -v -k all -u

root@lib10:~# umount /boot/
root@lib10:~# exit


root@lib10:~# umount /tmp/zfs-root/dev/
root@lib10:~# umount /tmp/zfs-root/proc/
root@lib10:~# umount /tmp/zfs-root/sys/

root@lib10:~# zfs umount lib10/ROOT/debian-1

root@lib10:~# zfs set mountpoint=/ lib10/ROOT/debian-1



.pre
^ dumps

.pre
dpavlin@x200:~$ lsusb -d 045e:
Bus 008 Device 007: ID 045e:02ae Microsoft Corp. Xbox NUI Camera
Bus 008 Device 005: ID 045e:02b0 Microsoft Corp. Xbox NUI Motor
Bus 008 Device 006: ID 045e:02ad Microsoft Corp. Xbox NUI Audio

sudo apt-get install freenect libfreenect-dev libfreenect-demos

[14766.239235] usb 8-1: USB disconnect, device number 4
[14766.239241] usb 8-1.1: USB disconnect, device number 6
[14766.239488] usb 8-1.2: USB disconnect, device number 5
[14766.239604] usb 8-1.3: USB disconnect, device number 7
[14772.208169] usb 8-1: new high-speed USB device number 8 using ehci-pci
[14772.340484] usb 8-1: New USB device found, idVendor=0409, idProduct=005a
[14772.340492] usb 8-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[14772.341073] hub 8-1:1.0: USB hub found
[14772.341203] hub 8-1:1.0: 3 ports detected
[14773.024210] usb 8-1.2: new full-speed USB device number 9 using ehci-pci
[14773.141698] usb 8-1.2: New USB device found, idVendor=045e, idProduct=02b0
[14773.141702] usb 8-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[14773.141705] usb 8-1.2: Product: Xbox NUI Motor
[14773.141708] usb 8-1.2: Manufacturer: Microsoft
[14774.596222] usb 8-1.1: new high-speed USB device number 10 using ehci-pci
[14774.706477] usb 8-1.1: New USB device found, idVendor=045e, idProduct=02ad
[14774.706486] usb 8-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[14774.706492] usb 8-1.1: Product: Xbox Kinect Audio, \xffffffc2\xffffffa9\xffffffa9 2011 Microsoft Corporation. All rights reserved.
[14774.706497] usb 8-1.1: Manufacturer: Microsoft
[14774.706502] usb 8-1.1: SerialNumber: A44885W08919042A
[14776.132398] usb 8-1.3: new high-speed USB device number 11 using ehci-pci
[14776.247573] usb 8-1.3: New USB device found, idVendor=045e, idProduct=02ae
[14776.247577] usb 8-1.3: New USB device strings: Mfr=2, Product=1, SerialNumber=3
[14776.247580] usb 8-1.3: Product: Xbox NUI Camera
[14776.247582] usb 8-1.3: Manufacturer: Microsoft
[14776.247584] usb 8-1.3: SerialNumber: A00361813208043A
[14776.248029] gspca_main: kinect-2.14.0 probing 045e:02ae


.pre
{file: PrintrBot_Plus_LC.diff}

Old 3D printer which never worked well.

DXF files: https://www.youmagine.com/designs/printrbot-lc-1302

https://web.archive.org/web/20130115210644/http://printrbot.com/shop/plus/

{toc: }

^ PrintrBot Plus LC

The Printrbot PLUS is the larger printrbot kit–containing an 8x8x8 build volume, laser cut birch construction, an assembled Ubis hot end, and 12mm Z-axis rods in an all-in-one kit. This kit also includes 1 lb of ABS filament.

This kit includes everything you need to build the printrbot PLUS:

* printrboard: all-in-one assembled electronics with integrated SD card slot (no soldering required)
* 5 NEMA 17 stepper motors complete with cable ends attached
* laser cut birch construction
* a few printed plastic parts (gears, etc)
* WOOD Extruder Kit
* hardware (8mm smooth rods, threaded rods, and bearings
** Z axis is 12mm smooth rods and 12 mm linear bearings )
* assembled Ubis hot end
* nuts, bolts, washers, zip ties
* laser cut print bed
* 8×8 heated bed
* misc assembled cables (no soldering required)
* 3 mechanical end stops (no soldering required)
* micro USB cable

^^ nozzle

The Getting Started Guide says that all Printrbots currently ship with 0.4mm nozzles.
The convention for identifying nozzles is based on notches (or "rings") cut into the sides (vertices) of the hexagonal brass "nut".
No notch = 0.5mm
1 notch = 0.4mm
2 notches = 0.35mm

^ info

Most of information about it vanished from internet so here is some overview:

* http://reprap.org/wiki/Printrbot
* http://reprap.org/wiki/Printrboard

* https://github.com/Printrbot/printrboard

Rev.B https://github.com/Printrbot/printrboard/releases/tag/revB

^ PrintrBoard pinout

Annotated headers from http://blog.think3dprint3d.com/2012/07/panelolu-with-printrboard.html

{image: Printrboard Headers.JPG}

^ serial

.pre
[Sun Mar 18 08:23:50 2018] usb 2-4.4: new full-speed USB device number 61 using xhci_hcd
[Sun Mar 18 08:23:50 2018] usb 2-4.4: New USB device found, idVendor=16c0, idProduct=0483
[Sun Mar 18 08:23:50 2018] usb 2-4.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[Sun Mar 18 08:23:50 2018] usb 2-4.4: Product: USB Serial
[Sun Mar 18 08:23:50 2018] usb 2-4.4: Manufacturer: Teensyduino
[Sun Mar 18 08:23:50 2018] usb 2-4.4: SerialNumber: 12345
[Sun Mar 18 08:23:50 2018] cdc_acm 2-4.4:1.0: ttyACM0: USB ACM device

dpavlin@nuc:~$ microcom p /dev/ttyACM0 
connected to /dev/ttyACM0
Escape character: Ctrl\
Type the escape character to get to the prompt.


start
echo:PowerUp
 Brown out Reset
Marlin: 1.0.0 RC2
echo: Last Updated: 2012-02-25 | Author: erik
echo: Free Memory: 4907  Pla




echo:SD init fail
workDir open failed
echo:Unknown command:"echo"
ok
echo:Unknown command:"SD init fail"
ok
echo:Unknown command:"workDir open failed"
ok
.pre

^ settings

https://github.com/Printrbot/Marlin

.pre
M501
echo:Stored settings retreived:
echo:Steps per unit:
echo:  M92 X62.11 Y64.67 Z2272.72 E536.00
echo:Maximum feedrates (mm/s):
echo:  M203 X60.00 Y60.00 Z2.00 E14.00
echo:Maximum Acceleration (mm/s2):
echo:  M201 X2000 Y2000 Z30 E10000
echo:Acceleration: S=acceleration, T=retract acceleration
echo:  M204 S3000.00 T3000.00
echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s),  Z=maximum Z jerk (mm/s)
echo:  M205 S0.00 T0.00 B20000 X20.00 Z0.40 E5.00
echo:PID settings:
echo:   M301 P22.20 I1.08 D114.00

M115
FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1

.pre

If this doesn't work, you can try `M503` which should display all settings without loading them from flash.

^ software bed leveler

* https://github.com/emard/zleveler

^ schematics

{file: Printrboard_RevB_Schematic150.png}

{file: Printrboard-schematics.pdf}

^ Marlin

* https://github.com/MarlinFirmware/Marlin
* http://marlinfw.org/meta/gcode/

.pre
dpavlin@nuc:/nuc/PrintrBot$ git clone https://github.com/dpavlin/Marlin

dpavlin@nuc:/nuc/PrintrBot$ cd Marlin/
.pre

^^ compile Marlin 1.1.8

https://github.com/dpavlin/Marlin/tree/PrintrBot_Plus_LC-1.1.8

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ git checkout PrintrBot_Plus_LC-1.1.8 

dpavlin@nuc:/nuc/PrintrBot/Marlin$ platformio run -e printrboard
Warning! Ignore unknown `envs_dir` option in `[platformio]` section

Processing printrboard (platform: teensy; board: teensy20pp; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
PLATFORM: Teensy > Teensy++ 2.0
SYSTEM: AT90USB1286 16MHz 8KB RAM (127KB Flash)
.pre

^^ compile Marlin 1.1.9

different enviroment compared to 1.1.8?

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ git checkout PrintrBot_Plus_LC-1.1.9 

dpavlin@nuc:/nuc/PrintrBot/Marlin$ platformio run -e teensy20
.pre

^^ flashing

open boot jumper, press button

.pre
[Sun Apr 15 12:20:34 2018] usb 1-1.1: new full-speed USB device number 30 using xhci_hcd
[Sun Apr 15 12:20:34 2018] usb 1-1.1: unable to get BOS descriptor
[Sun Apr 15 12:20:34 2018] usb 1-1.1: New USB device found, idVendor=03eb, idProduct=2ffb
[Sun Apr 15 12:20:34 2018] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[Sun Apr 15 12:20:34 2018] usb 1-1.1: Product: AT90USB128 DFU
[Sun Apr 15 12:20:34 2018] usb 1-1.1: Manufacturer: ATMEL
[Sun Apr 15 12:20:34 2018] usb 1-1.1: SerialNumber: 1.0.0


root@nuc:/nuc/PrintrBot/Marlin# apt-get install dfu-programmer


root@nuc:/nuc/PrintrBot/Marlin# dfu-programmer --targets 2>&1 | grep at90usb128
    at89c5132          at90usb1287        at90usb1286        at90usb1287-4k
    at90usb1286-4k     at90usb647         at90usb646         at90usb162

root@nuc:/nuc/PrintrBot/Marlin# dfu-programmer at90usb1286 dump --debug 99
     target: at90usb1286
    chip_id: 0x2ffb
  vendor_id: 0x03eb
    command: dump
      quiet: false
      debug: 99
device_type: AVR
------ command specific below ------

commands.c:625: dump 122880 bytes
atmel.c:579: atmel_read_flash( 0x7ffe83facaf0, 0x00000000, 0x0001e000, 0x564ef5df7000, 122880, false )
atmel.c:847: atmel_select_page( 0x7ffe83facaf0, 0 )
atmel.c:510: __atmel_read_page( 0x7ffe83facaf0, 0, 65536, 0x564ef5df7000, false )
atmel.c:537: result: -9
Unknown error.  Try enabling debug.
Failed to read 122880 bytes from device.



.pre

other useful debug levels are 100, 200, 300 - https://www.avrfreaks.net/forum/how-use-dfu-programmer

hmmm... can't backup firmware?

^^ flash firmware

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ dfu-programmer at90usb1286 erase
dpavlin@nuc:/nuc/PrintrBot/Marlin$ dfu-programmer at90usb1286 flash .pioenvs/printrboard/firmware.hex
Validating...
Flash did not validate. Did you erase first?

dpavlin@nuc:/nuc/PrintrBot/Marlin$ dfu-programmer at90usb1286 erase --debug 100
     target: at90usb1286
    chip_id: 0x2ffb
  vendor_id: 0x03eb
    command: erase
      quiet: false
      debug: 100
device_type: AVR
------ command specific below ------
   validate: true

commands.c:69: erase 122879 bytes
atmel.c:281: atmel_erase_flash( 0x7ffc5df9bff0, 4 )
atmel.c:671: atmel_blank_check( 0x7ffc5df9bff0, 0x00000000, 0x0001dfff )
atmel.c:847: atmel_select_page( 0x7ffc5df9bff0, 0 )
atmel.c:647: __atmel_blank_check_internal( 0x7ffc5df9bff0, 0x00000000, 0x0000ffff )
atmel.c:847: atmel_select_page( 0x7ffc5df9bff0, 1 )
atmel.c:647: __atmel_blank_check_internal( 0x7ffc5df9bff0, 0x00000000, 0x0000dfff )

.pre

^^ teensy setup pjrc

udev rule: https://www.pjrc.com/teensy/49-teensy.rules
loader: https://github.com/PaulStoffregen/teensy_loader_cli

^^ unlock chip using flip

It seems that chip is protected. However, trying to erase and program it did destry data in it (expect bootloader) for some reason, and it seem that dfu-programmer doesn't know how to work with protection features.

So, next step is to try atmel's flip under linux but this also doesn't work well.

* patch path to /dev/bus/usb/ - https://www.avrfreaks.net/forum/instructions-get-batchisp-working-ubuntu-lucid-1004?name=PNphpBB2&file=viewtopic&t=97673

.pre
root@nuc:/nuc/PrintrBot/flip.3.2.1# cat debian-install.sh 
sudo apt-get install openjdk-9-jre:i386 libusb-0.1-4:i386

root@nuc:/nuc/PrintrBot/flip.3.2.1# cat env.sh 
export JAVA_HOME=/usr/lib/jvm/java-9-openjdk-i386/
export FLIP_HOME=/nuc/PrintrBot/flip.3.2.1/bin/


root@nuc:/nuc/PrintrBot/flip.3.2.1# cd bin/
root@nuc:/nuc/PrintrBot/flip.3.2.1/bin# cp -apv libatlibusbdfu.so libatlibusbdfu.so.orig
root@nuc:/nuc/PrintrBot/flip.3.2.1/bin# sed 's/\/sys\/bus\/usb/\/dev\/bus\/usb/g' libatlibusbdfu.so.orig > libatlibusbdfu.so


# run from bin directory or it won't work (?!)

root@nuc:/nuc/PrintrBot/flip.3.2.1/bin# ./flip.sh

.pre

^ avrdude

made cable to convert 10 pin ICSP on usbasp to 6 pin ICSP on printrboard

http://reprap.org/wiki/Printrboard#Bootloaders

Pin 1 (not red wire on my harness because of re-wiring) is closest to the SD card slot.

.pre
root@nuc:/nuc/PrintrBot# avrdude -p usb1286 -c usbasp 

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)

avrdude: safemode: Fuses OK (E:F3, H:99, L:5E)

avrdude done.  Thank you.
.pre

ok, factory bootloader

^^ fuses

.pre
# disable jtag
avrdude -c usbtiny -p at90usb1286 -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf0:m

# enabled jtag
avrdude -c usbtiny -p at90usb1286 -U lfuse:w:0xDE:m -U hfuse:w:0x9B:m -U efuse:w:0xF0:m

root@nuc:/nuc/PrintrBot# avrdude -c usbtiny -p at90usb1286 -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf0:m
avrdude: Error: Could not find USBtiny device (0x1781/0xc9f)

avrdude done.  Thank you.

root@nuc:/nuc/PrintrBot# avrdude -c usbasp -p at90usb1286 -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf0:m

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)
avrdude: reading input file "0xde"
avrdude: writing lfuse (1 bytes):

Writing |                                                    | 0% 0.00s ***failed;
Writing | ################################################## | 100% 0.06s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xde:
avrdude: load data lfuse data from input file 0xde:
avrdude: input file 0xde contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x5e != 0xde
avrdude: verification error; content mismatch

avrdude: safemode: lfuse changed! Was de, and is now 5e
[Tue Apr 17 07:12:19 2018] usb 1-1.4: USB disconnect, device number 20
[Tue Apr 17 07:12:19 2018] usb 1-1.4: USB disconnect, device number 20
Would you like this fuse to be changed back? [y/n]
Would you like this fuse to be changed back? [y/n] n
avrdude: safemode: Fuses OK (E:F3, H:99, L:DE)

avrdude done.  Thank you.


root@nuc:/nuc/PrintrBot# avrdude -p usb1286 -c usbasp 

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)

avrdude: safemode: Fuses OK (E:F3, H:99, L:5E)

avrdude done.  Thank you.

.pre

^^ flash bootloader

huh, hum, program bootloader anyway from http://blog.lincomatic.com/?p=548

.pre
root@nuc:/nuc/PrintrBot# avrdude -p usb1286 -c usbasp -U flash:w:BootloaderDFU.hex
.pre

power cycle, return jumper re-try programming fuses

.pre
root@nuc:/nuc/PrintrBot# avrdude -c usbasp -p at90usb1286 -U lfuse:w:0xDE:m -U hfuse:w:0x9B:m -U efuse:w:0xF0:m
.pre

^^ dfu programming works

re-try dfu programming

.pre
root@nuc:/nuc/PrintrBot# dfu-programmer at90usb1286 erase
root@nuc:/nuc/PrintrBot# dfu-programmer at90usb1286 flash Marlin/.pioenvs/printrboard/firmware.hex
Validating...
61322 bytes used (49.90%)


.pre

^^ avrdude programming

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ avrdude -c usbasp -p usb1286 -U flash:w:.pioenvs/printrboard/firmware.hex

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file ".pioenvs/printrboard/firmware.hex"
avrdude: input file .pioenvs/printrboard/firmware.hex auto detected as Intel Hex
avrdude: writing flash (87280 bytes):

Writing | ################################################## | 100% 58.04s

avrdude: 87280 bytes of flash written
avrdude: verifying flash memory against .pioenvs/printrboard/firmware.hex:
avrdude: load data flash data from input file .pioenvs/printrboard/firmware.hex:
avrdude: input file .pioenvs/printrboard/firmware.hex auto detected as Intel Hex
avrdude: input file .pioenvs/printrboard/firmware.hex contains 87280 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 38.49s

avrdude: verifying ...
avrdude: 87280 bytes of flash verified

avrdude: safemode: Fuses OK (E:F0, H:9B, L:DE)

avrdude done.  Thank you.
.pre

^ RepRapDiscount Full Graphic Smart Controller

* http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller

^^ pinouts

{file: printrboard-lcd-pinout.png}

{image: printrboard-lcd-pinout-800px.png}

^^ Marlin pinout

.pre
diff --git a/Marlin/pins_PRINTRBOARD.h b/Marlin/pins_PRINTRBOARD.h
index 42632d174..8146505a3 100644
--- a/Marlin/pins_PRINTRBOARD.h
+++ b/Marlin/pins_PRINTRBOARD.h
@@ -166,3 +166,19 @@
   #endif
 
 #endif // ULTRA_LCD && NEWPANEL
+
+// XXX dpavlin -- my pinout
+#define LCD_PINS_RS       9   // E1       JP11-11
+#define LCD_PINS_ENABLE   8   // E0       JP11-10
+#define LCD_PINS_D4       7   // D7       JP11-8
+#define LCD_PINS_D5       6   // D6       JP11-7
+#define LCD_PINS_D6       5   // D5       JP11-6
+#define LCD_PINS_D7       4   // D4       JP11-5
+
+#define BTN_EN1        10   // C0       JP11-12
+#define BTN_EN2        11   // C1       JP11-13
+#define BTN_ENC        12   // C2       JP11-14
+
+// display delays are added to
+// Marlin/ultralcd_st7920_u8glib_rrd.h
+
diff --git a/Marlin/ultralcd_st7920_u8glib_rrd.h b/Marlin/ultralcd_st7920_u8glib_rrd.h
index db6224e47..8474bef24 100644
--- a/Marlin/ultralcd_st7920_u8glib_rrd.h
+++ b/Marlin/ultralcd_st7920_u8glib_rrd.h
@@ -49,7 +49,7 @@
   #define CPU_ST7920_DELAY_1 DELAY_NS(0)
   #define CPU_ST7920_DELAY_2 DELAY_NS(0)
   #define CPU_ST7920_DELAY_3 DELAY_NS(50)
-#elif MB(3DRAG) || MB(K8200) || MB(K8400) || MB(SILVER_GATE)
+#elif MB(3DRAG) || MB(K8200) || MB(K8400) || MB(SILVER_GATE) || MB(PRINTRBOARD)
   #define CPU_ST7920_DELAY_1 DELAY_NS(0)
   #define CPU_ST7920_DELAY_2 DELAY_NS(188)
   #define CPU_ST7920_DELAY_3 DELAY_NS(0)
.pre

^ Hardware upgrade

^^ RAMPS1.4 LCD 12864

* RAMPS1.4 LCD 12864 Control Panel 3D Printer Smart Controller LCD Display $10
** https://www.aliexpress.com/item/1-pcs-RAMPS1-4-LCD-12864-Control-Panel-3D-Printer-Smart-Controller-LCD-Display-Free-Shipping/32312042967.html
** $10 - works well, needs custom cable, well worth it from usability perspective

^^ LM8UU

* 10pcs/lot LM8UU Ball Bearings 8mm Bushing For CNC 3D Printers Parts Rail Linear Long Rod Shaft Part 8mm*15mm*24mm Aluminum Bush
** https://www.aliexpress.com/item/10pcs-lot-LM8UU-Ball-Bearings-8mm-Bushing-For-CNC-3D-Printers-Parts-Rail-Linear-Long-Rod/32834729285.html
** $4.24 - NOT recomended, worse that original VXB.com -- seller specified brand as FYSETC, parts don't have any markings

^^ Y axis coupler

* 3D Printer Parts Accessory Stepper Motor Aluminum Alloy Z Axis Flexible Coupling Coupler Shaft Couplings 5mm*8mm*25mm
** https://www.aliexpress.com/item/10pcs-lot-LM8UU-Ball-Bearings-8mm-Bushing-For-CNC-3D-Printers-Parts-Rail-Linear-Long-Rod/32834729285.html
** $0.75 - NOT for Y axis, since they are flexible
* 3D Printer Blue Aluminum Alloy Coupler for 5 x 5mm/5 x 8mm Shaft for Stepper Motor Shaft
** https://www.aliexpress.com/item/3D-Printer-Blue-Aluminum-Alloy-Coupler-for-5-x-5mm-5-x-8mm-Shaft-for-Stepper/32854452012.html
** $0.71 - great, much better than 3d printed part

^^ belts and pulleys

* 2pcs GT2 20teeth 20 Teeth Bore 5mm/8mm Timing Alumium Pulley + 2Meters Rubber GT2-6mm Open Timing Belt Width 6mm for 3D Printer
** https://www.aliexpress.com/item/2Pcs-GT2-20teeth-20-Teeth-Bore-5mm-8mm-Timing-Alumium-Pulley-2Meters-Rubber-GT2-6mm-Open/32711078503.html
** $1.90 - great, pully nut doesn't interfere with clip which is holding glass since nut is flush as opposed to 3d printed part

^^ Y axes rod

* T8 Lead Screw OD 8mm Pitch 2mm Lead 2mm 150mm 200mm 250mm 300mm 350mm 400mm 500mm with Brass Nut for Reprap 3D Printer Z Axis
** 250mm with Nut
** https://www.aliexpress.com/item/T8-Lead-Screw-Rod-OD-8mm-Pitch-2mm-Lead-2mm-Length-150mm-500mm-Threaded-Rods-with/32760102869.html
** $5.14 x 2 - great, our rods where bent from out of box

Needs 3d printed adapter for nut to fit: https://www.thingiverse.com/thing:2963508

Nut is friction fit which I consider somewhat as safety feature, if I found problems with it, I will probably add a bit of ABS goo in holes to fix it in place

^^ bed leveling

self-made sensor from RFID card, paper clip and case intrusion switch, connected in parallel with z-axis switch (it has to be normally closed, so that trigger interrupts signal)

^ BL touch

* 1 Set Newest BL Touch Auto Bed Leveling Sensor 3D Touch Auto Leveling Sensor For Anet A8 3D Printer Improve Printing Precision
** https://www.aliexpress.com/store/product/1-Set-Newest-BL-Touch-Auto-Bed-Leveling-Sensor-3D-Touch-for-3D-Printer-Improve-Printing/3108017_32837521614.html

http://www.geeetech.com/wiki/index.php/3DTouch_Auto_Leveling_Sensor

pinout, right to left

| pin | wire color | board label |
| 5 | green | G |
| 4 | red | 5V |
| 3 | yellow | S |
| 2 | black | G |
| 1 | white | Z- |

Needs additional pin for servo control (S - servo)

^^ Marlin configuration

.pre
commit 18396a8cd25585d5d562d4345ed851b91fb58821 (HEAD -> PrintrBot_Plus_LC-1.1.9)
Author: Dobrica Pavlinusic <dpavlin@rot13.org>
Date:   Sat Sep 8 11:05:54 2018 +0200

    probe offset from extruder

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 438494220..aeed322a7 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -770,8 +770,8 @@
  *      O-- FRONT --+
  *    (0,0)
  */
-#define X_PROBE_OFFSET_FROM_EXTRUDER 10  // X offset: -left  +right  [of the nozzle]
-#define Y_PROBE_OFFSET_FROM_EXTRUDER 10  // Y offset: -front +behind [the nozzle]
+#define X_PROBE_OFFSET_FROM_EXTRUDER 35  // X offset: -left  +right  [of the nozzle]
+#define Y_PROBE_OFFSET_FROM_EXTRUDER 5   // Y offset: -front +behind [the nozzle]
 #define Z_PROBE_OFFSET_FROM_EXTRUDER 0   // Z offset: -below +above  [the nozzle]
 
 // Certain types of probes need to stay away from edges

commit 2329e561e0f2997e78495c249706e9ce62608293
Author: Dobrica Pavlinusic <dpavlin@rot13.org>
Date:   Sat Sep 8 10:51:07 2018 +0200

    enable bed leveling
    
    AUTO_BED_LEVELING_UBL doesn't seem to compile for me ATM

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 38e0c343b..438494220 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -969,7 +969,7 @@
  */
 //#define AUTO_BED_LEVELING_3POINT
 //#define AUTO_BED_LEVELING_LINEAR
-//#define AUTO_BED_LEVELING_BILINEAR
+#define AUTO_BED_LEVELING_BILINEAR
 //#define AUTO_BED_LEVELING_UBL
 //#define MESH_BED_LEVELING
 
@@ -1023,6 +1023,8 @@
   //#define FRONT_PROBE_BED_POSITION MIN_PROBE_EDGE
   //#define BACK_PROBE_BED_POSITION (Y_BED_SIZE - MIN_PROBE_EDGE)
 
+  #define RIGHT_PROBE_BED_POSITION 190 // dpavlin -- probe overhangs on the right
+
   // Probe along the Y axis, advancing X after each column
   //#define PROBE_Y_FIRST
 

commit b867a948cd3b64d69e900b99a1306631d62753df
Author: Dobrica Pavlinusic <dpavlin@rot13.org>
Date:   Sun Sep 2 08:40:52 2018 +0200

    added bltouch config and pin on e-stop

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index fd8463456..38e0c343b 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -721,7 +721,7 @@
 /**
  * The BLTouch probe uses a Hall effect sensor and emulates a servo.
  */
-//#define BLTOUCH
+#define BLTOUCH
 #if ENABLED(BLTOUCH)
   //#define BLTOUCH_DELAY 375   // (ms) Enable and increase if needed
 #endif
@@ -1909,7 +1909,7 @@
  * Set this manually if there are extra servos needing manual control.
  * Leave undefined or set to 0 to entirely disable the servo subsystem.
  */
-//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
+#define NUM_SERVOS 1 // Servo index starts with 0 for M280 command
 
 // Delay (in milliseconds) before the next move will start, to give the servo time to reach its target angle.
 // 300ms is a good value but you can try less delay.
diff --git a/Marlin/pins_PRINTRBOARD.h b/Marlin/pins_PRINTRBOARD.h
index 8146505a3..a68802725 100644
--- a/Marlin/pins_PRINTRBOARD.h
+++ b/Marlin/pins_PRINTRBOARD.h
@@ -182,3 +182,9 @@
 // display delays are added to
 // Marlin/ultralcd_st7920_u8glib_rrd.h
 
+// bltouch - use e-stop for servo
+// dpavlin@nuc:/nuc/PrintrBot/Marlin$ grep E5 m43-pins.txt 
+// PIN:  37   Port: E5        <unused/unknown>            Input  = 1
+//
+#define SERVO0_PIN	37	// E5 E-STOP
+
.pre

^^ gcode for bl-touch

M280 P0 S10 ; pushes the pin down

M280 P0 S90 ; pulls the pin up

M280 P0 S120 ; Self test – keeps going until you do pin up/down or release alarm

M280 P0 S160 ; Release alarm

M420 V ; display bed leveling

.pre
Bilinear Leveling Grid:
      0      1      2
 0 +0.445 +0.402 +0.284
 1 -0.083 +0.013 +0.023
 2 -0.678 -0.432 -0.264

echo:Bed Leveling On 
echo:Fade Height Off
.pre

----

^ Notes for Ender 3 V1.1.3

* install sanguino board support in ardunino ide https://github.com/Lauszus/Sanguino
* turn on power supply when flashing if you didn't disconnect steppers or it won't get enough power
* burn boot loader using usbasp programmer from arduino ide to make arudino ide work for upload
{toc: }

^ MongoDB

^^ Checkout source

.pre
dpavlin@t61p:/rest/cvs$ git clone git://github.com/mongodb/mongo.git
Initialized empty Git repository in /rest/cvs/mongo/.git/
remote: Counting objects: 32011, done.
remote: Compressing objects: 100% (9340/9340), done.
remote: Total 32011 (delta 22724), reused 31556 (delta 22412)
Receiving objects: 100% (32011/32011), 20.57 MiB | 1.12 MiB/s, done.
Resolving deltas: 100% (22724/22724), done.
.pre

^^ Install build dependencies

.pre
dpavlin@t61p:/rest/cvs/mongo$ sudo apt-get install \
 libboost-dev libboost-thread-dev libboost-filesystem-dev libboost-program-options-dev libboost-date-time-dev \
 libpcre3-dev xulrunner-dev libreadline-dev
.pre

^^ Build Debian package

`debian/control` file needs modification for unstable: http://svn.rot13.org/index.cgi/pxelator/view/mongodb/mongo-debian-control-xulrunner.diff

.pre
dpavlin@t61p:/rest/cvs$ cd mongo/

# patch source
dpavlin@klin:/rest/cvs/mongo$ patch -p1 < /srv/pxelator/mongodb/mongo-debian-control-xulrunner.diff 
patching file debian/control

# clean before new build
dpavlin@t61p:/rest/cvs/mongo$ sudo rm -Rf debian/mongodb

dpavlin@t61p:/rest/cvs/mongo$ time dpkg-buildpackage -rfakeroot -b

...

real    6m16.744s
user    5m41.701s
sys     0m19.393s
.pre

^ Perl driver

.pre
dpavlin@t61p:/rest/cvs$ git clone git://github.com/mongodb/mongo-perl-driver.git
Initialized empty Git repository in /rest/cvs/mongo-perl-driver/.git/
remote: Counting objects: 1782, done.
remote: Compressing objects: 100% (1673/1673), done.
remote: Total 1782 (delta 1122), reused 0 (delta 0)
Receiving objects: 100% (1782/1782), 1.45 MiB | 747 KiB/s, done.
Resolving deltas: 100% (1122/1122), done.

sudo apt-get install libany-moose-perl libdata-types-perl

dpavlin@t61p:/rest/cvs$ cd mongo-perl-driver/

perl Makefile.PL
make test
sudo dh-make-perl
.pre

^ Binaries

* http://debian.rot13.org/

^ Queries

^^ PXElator audit examples

.pre
> use pexlator

> db.audit.group({ key:{ 'package.name':true }, initial:{ count: 0 }, reduce:function(o,p) { p.count++ } });

> show profile

11052ms Sun Jan 31 2010 13:24:47
query pxelator.$cmd ntoreturn:1 reslen:690 nscanned:0  
query: { group: { key: { package.name: true }, initial: { count: 0.0 }, ns: "audit", $reduce: function (o, p) {
    p.count++;
} } }  nreturned:1 bytes:674 11052ms

> db.audit.ensureIndex({ 'package.name':true })

> db.audit.group({ key:{ 'package.name':true }, initial:{ count: 0 }, reduce:function(o,p) { p.count++ } });
.pre

no visible speed impact.

We are really interested only in daemons which aren't null:

.pre
> db.audit.ensureIndex( { daemon: true } )
> db.audit.group({
 key: { daemon:true }
,cond: { daemon: { $exists: true } }
,initial: { count: 0 }
,reduce: function(o,p) { p.count++ }
});
.pre

dhcp count usage by ip

.pre
> db.audit.ensureIndex( { "package.name": true } )

> db.audit.group({ key:{ ip:true }, cond: { "package.name": "dhcpd" }, initial: { count: 0 }, reduce: function(o,p) { p.count++ } });
.pre

package usage

.pre
> db.setProfilingLevel(2,1000);

> db.audit.group({ key:{ "package.name":true }, initial:{ count:0 }, reduce:function(o,p){ p.count++ } })

> db.system.profile.find().sort({$natural:-1}).limit(10)

{ "ts" : "Sun Jan 24 2010 15:07:53 GMT+0100 (CET)", "info" : "query pxelator.$cmd ntoreturn:1 reslen:642 nscanned:0  
query: { group: { key: { package.name: true }, initial: { count: 0.0 }, ns: \"audit\", $reduce: function (o, p) {
    p.count++;
} } }  nreturned:1 bytes:626 13887ms", "millis" : 13887 }

> db.audit.ensureIndex({ "package.name":true })

> db.audit.group({ key:{ "package.name":true }, initial:{ count:0 }, reduce:function(o,p){ p.count++ } })
.pre

doesn't help much, because we don't have `cond` in query.

^^ Profile

.pre
> db.setProfilingLevel(2,1000);
{ "was" : 2, "ok" : 1 }
> db.system.profile.find()
.pre

^ Indexes

.pre
> db.system.indexes.find()
{ "name" : "_id_", "ns" : "pxelator.audit", "key" : { "_id" : ObjectId("000000000000000000000000") } }
{ "ns" : "pxelator.audit", "key" : { "daemon" : true }, "name" : "daemon_" }
{ "ns" : "pxelator.audit", "key" : { "key" : "package.time" }, "name" : "key_" }
{ "ns" : "pxelator.audit", "key" : { "package.name" : true }, "name" : "package.name_" }
.pre

^ Comparison with CouchDB

Migrate from CouchDB to MongoDB using http://svn.rot13.org/index.cgi/pxelator/view/bin/couchdb2mongodb.pl

^^ Disk usage

.pre
root@opr:~# du -hc /var/lib/couchdb/0.9.0/.pxelator* /var/lib/couchdb/0.9.0/pxelator.couch
655M    /var/lib/couchdb/0.9.0/.pxelator_design
23M     /var/lib/couchdb/0.9.0/.pxelator_temp
7.8G    /var/lib/couchdb/0.9.0/pxelator.couch
8.4G    total

root@opr:~# du -hc /var/lib/mongodb/pxelator.*
65M     /var/lib/mongodb/pxelator.0
129M    /var/lib/mongodb/pxelator.1
257M    /var/lib/mongodb/pxelator.2
513M    /var/lib/mongodb/pxelator.3
513M    /var/lib/mongodb/pxelator.4
513M    /var/lib/mongodb/pxelator.5
17M     /var/lib/mongodb/pxelator.ns
2.0G    total
.pre

^^ Map/Reduce differences

CouchDB

.pre
# map
function(doc) {
  if ( doc.package.name == 'dnsd' )
   emit(doc.peerhost,1);
}

# reduce
function (k,v) {
 return sum(v);
}
.pre

MongoDB

.pre
> m = function() { emit(this.peerhost,1) }

> r = function(k,vals) { var sum = 0; for (var i in vals) sum += vals[i]; return sum; }

> res = db.audit.mapReduce(m, r, { query:{"package.name":"dnsd"} } )
{
        "result" : "tmp.mr.mapreduce_1264448081_3",
        "timeMillis" : 6040,
        "counts" : {
                "input" : {
                        "top" : 0,
                        "bottom" : 204293
                },
                "emit" : {
                        "top" : 0,
                        "bottom" : 204293
                },
                "output" : {
                        "top" : 0,
                        "bottom" : 22
                }
        },
        "ok" : 1,
}

> db[res.result].find().limit(10)
.pre

Comparison with ad-hoc query

.pre
> db.setProfilingLevel(2,1000);

> db.audit.group({ key:{ "peerhost":true }, cond:{ "package.name":"dnsd" },
 initial:{ count:0 }, reduce:function(o,p){ p.count++ } })

> db.system.profile.find().sort({$natural:-1}).limit(10)

{ "ts" : "Mon Jan 25 2010 21:21:11 GMT+0100 (CET)", "info" : "query pxelator.$cmd ntoreturn:1 reslen:1148 nscanned:0  
query: { group: { key: { peerhost: true }, cond: { package.name: \"dnsd\" }, initial: { count: 0.0 }, ns: \"audit\", $reduce: function (o, p) {
    p.count++;
} } }  nreturned:1 bytes:1132 2161ms", "millis" : 2161 }
.pre

So, going through server-side JavaScript is *3x performance penalty*

^ Blog posts

{fetchrss: http://blog.rot13.org/mt/mt-search.cgi?tag=MongoDB&Template=feed&IncludeBlogs=1}

^ Debian amd64 version

^^ build

.pre
root@klin:~/rest/virtual# debootstrap --arch amd64 squeeze ./mongodb-amd64 http://10.60.0.91:3142/debian

root@klin:~/rest/virtual# chroot mongodb-amd64/

root@klin:/# apt-get install \
 git-core locales dpkg-dev debhelper scons \
 libboost-dev libboost-thread-dev libboost-filesystem-dev libboost-program-options-dev libboost-date-time-dev \
 libpcre3-dev xulrunner-dev libreadline-dev

root@klin:/# cd /srv/
root@klin:/srv# git clone git://github.com/mongodb/mongo.git

root@klin:/srv# cd mongo/
root@klin:/srv/mongo# time dpkg-buildpackage -rfakeroot -b
.pre

^^ run

.pre
dpavlin@klin:~$ sudo chroot /virtual/mongodb-amd64/  su -c '/usr/bin/mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb/MongoDB.log run' mongodb
.pre
{toc: }

STM32F100RBT6B

* different from http://pulkomandy.tk/_/_Electronique/_Discovering%20the%20STM32F3%20Discovery

.pre
dpavlin@blue:~$ lsusb | grep ST
Bus 003 Device 006: ID 0483:3744 SGS Thomson Microelectronics STLINK Pseudo disk
.pre

^ Install toolchain

.pre
dpkg --add-architecture i386
apt-get install libc6-i386
#wget https://launchpad.net/gcc-arm-embedded/4.7/4.7-2012-q4-major/+download/gcc-arm-none-eabi-4_7-2012q4-20121208-linux.tar.bz2
wget https://sourcery.mentor.com/GNUToolchain/package4463/public/arm-none-eabi/arm-2009q1-161-arm-none-eabi-i686-pc-linux-gnu.tar.bz2

.pre

^ Install openocd

.pre
dpavlin@blue:~$ sudo apt-get install openocd
dpavlin@blue:~$ dpkg -l openocd
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                    Version          Architecture     Description
+++-=======================-================-================-====================================================
ii  openocd                 0.6.1-1          amd64            Open on-chip JTAG debug solution for ARM and MIPS sy
.pre

^^ start openocd

Disable STLINKv1 SCSI emulation, see https://github.com/texane/stlink

.pre
root@blue:~# modprobe -r usb-storage && modprobe usb-storage quirks=483:3744:i

root@blue:~# sudo openocd -f /usr/share/openocd/scripts/board/stm32vldiscovery.cfg
Open On-Chip Debugger 0.6.1 (2012-12-05-01:32)
Licensed under GNU GPL v2
For bug reports, read
       http://openocd.sourceforge.net/doc/doxygen/bugs.html
adapter speed: 1000 kHz
Info : clock speed 1000 kHz
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
.pre

Open another window and connect with telnet:

.pre
dpavlin@blue:~$ telnet localhost 4444
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> reset init
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000b4c msp: 0x20000400
.pre

^ summon toolchain

* https://github.com/esden/summon-arm-toolchain

^^ openocd

.pre
dpavlin@blue:~/sat$ sudo openocd -f /usr/share/openocd/scripts/board/stm32vldiscovery.cfg
[sudo] password for dpavlin: 
Open On-Chip Debugger 0.6.1 (2012-12-05-01:32)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html
adapter speed: 1000 kHz
Info : clock speed 1000 kHz
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'telnet' connection from 4444
Warn : target was in unknown state when halt was requested
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x21000000 pc: 0x080001ce msp: 0x20001ff0
.pre

From different terminal

.pre
dpavlin@blue:~/sat$ telnet localhost 4444
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
target was in unknown state when halt was requested
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x21000000 pc: 0x080001ce msp: 0x20001ff0
> 

> flash write_image erase /virtual/stm32discovery/libopencm3/examples/stm32/f1/stm32vl-discovery/fancyblink/fancyblink.hex
auto erase enabled
device id = 0x10016420
flash size = 128kbytes
target state: halted
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20001ff0
wrote 2048 bytes from file /virtual/stm32discovery/libopencm3/examples/stm32/f1/stm32vl-discovery/fancyblink/fancyblink.hex in 0.192207s (10.405 KiB/s)

.pre

^ Using Arduino IDE

http://forums.leaflabs.com/topic.php?id=630
{toc: }

^ Teardown

* http://fabiobaltieri.com/2013/07/10/inside-a-hantek-dso-2090-usb-oscilloscope/

^ openhantek

* http://www.openhantek.org/

^ sigrok

* http://sigrok.org/wiki/Hantek_DSO-2090

Doesn't work for me as of 2014-01-15

^ Hantek DSO

http://sourceforge.net/p/hantekdso/

Requires KDE 3 libraries

.pre
dpavlin@blue:/blue-zfs/hantek$ git svn clone --prefix=origin/ svn://svn.code.sf.net/p/hantekdso/code/ hantekdso
.pre

^ Digital Soda

http://sourceforge.net/projects/dsoda/

.pre
dpavlin@blue:/blue-zfs/hantek/dsoda$ sudo apt-get install libgtkglext1-dev
dpavlin@blue:/blue-zfs/hantek/dsoda$ ./configure ; make
.pre

^ Oscope 2100

.pre
dpavlin@blue:/blue-zfs/hantek$ mkdir oscope2100
dpavlin@blue:/blue-zfs/hantek$ cd oscope2100/
dpavlin@blue:/blue-zfs/hantek/oscope2100$ tar xf ../oscope2100-1.1.0.tar.gz 


.pre
^ Serial

http://www.ebay.com/itm/SLBoat-The-TL-WR703N-Mod-64Mbyte-RAM-16Mbyte-Flash-And-TTLout-Inside-MicroUSB/181078954797
"OpenVZ"<http://www.openvz.org/> is nice name-space virtualization, creating chroot jails on steroids, similar in spirit to Solaris zones. It ideal if you want to run single kernel and allocate resources using bean counters as opposed to hard-limits (20% of CPU as opposed to one core). Each slice is called `VE`.

{toc: }

^ Disk speed

.pre
dpavlin@zut:~$ sudo hdparm -tT /dev/cciss/c1d0 /dev/sda

/dev/cciss/c1d0:
 Timing cached reads:   2184 MB in  2.00 seconds = 1092.39 MB/sec
 Timing buffered disk reads:  324 MB in  3.02 seconds = 107.40 MB/sec

/dev/sda:
 Timing cached reads:   2144 MB in  2.00 seconds = 1071.89 MB/sec
 Timing buffered disk reads:  136 MB in  3.02 seconds =  45.02 MB/sec
.pre

Insert joke about "enterprise storage"<http://images.google.com/images?hl=en&q=enterprise+storage>

^ Add disk space to VE

We are using normal Linux LVM with single logical volume for all VEs.

First, resize logical volume:

.pre
root@koha-hw:~# vgextend -L +80G /dev/vg/vz
vgextend: invalid option -- L
  Error during parsing of command line.

root@koha-hw:~# lvextend -L +80G /dev/vg/vz
  Extending logical volume vz to 100.00 GB
  Logical volume vz successfully resized

root@koha-hw:~# resize2fs /dev/vg/vz 
resize2fs 1.40-WIP (14-Nov-2006)
Filesystem at /dev/vg/vz is mounted on /vz; on-line resizing required
old desc_blocks = 2, new_desc_blocks = 7
Performing an on-line resize of /dev/vg/vz to 26214400 (4k) blocks.
The filesystem on /dev/vg/vz is now 26214400 blocks long.

root@koha-hw:~# df -h /vz/
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg-vz      99G   20G   79G  21% /vz
.pre

Then, take a look how much space does VEs take:

.pre
root@koha-hw:~# vzlist -o veid,diskspace,diskspace.s,diskspace.h,diskinodes,diskinodes.s,diskspace.h
      VEID   DQBLOCKS DQBLOCKS.S DQBLOCKS.H   DQINODES DQINODES.S DQBLOCKS.H
    212052   11717220   15728640   20971520      61001     286527   20971520
    212226    6407804   10485760   12582912      69011     435472   12582912
.pre

alternativly, you can also execute df inside VEs:

.pre
root@koha-hw:~# vzlist -o veid -H | xargs -i sh -c "echo --{}-- ; vzctl exec {} df -h"
--212052--
Filesystem            Size  Used Avail Use% Mounted on
simfs                  15G   12G  3.9G  75% /
tmpfs                 2.0G     0  2.0G   0% /lib/init/rw
tmpfs                 2.0G     0  2.0G   0% /dev/shm
--212226--
Filesystem            Size  Used Avail Use% Mounted on
simfs                  10G  6.2G  3.9G  62% /
tmpfs                 2.0G     0  2.0G   0% /lib/init/rw
tmpfs                 2.0G     0  2.0G   0% /dev/shm
.pre

next, we will set diskpace on both VEs (becase we want them to share all available resources) to new logical volume size:

.pre
root@koha-hw:~# vzlist -o veid -H | xargs -i vzctl set {} --diskspace 100G:100G --save
Saved parameters for VE 212052
Saved parameters for VE 212226
.pre

This VEs are not in production, and one is development version of another. When we move to production, we want to enforce more strict limit on disk usage, to protect production machine from running out of disk space in case the development one goes wild.

^ VE management

We usually want to do some operations on bunch of VEs at once. This can be done using `vzctl exec` in one sweep like this:

^^ Update Debian

.pre
vzlist -H -o veid | xargs -i vzctl exec {} 'apt-get update && apt-get -y upgrade' 2>&1 | tee ~/log
.pre

^^ Quick reporting

You can read more about "groupby.pl and sum.pl on my blog"<http://blog.rot13.org/2008/05/group_by_data_in_shell_pipes.html>.

.pre
# install dependencies which are not part of standard lenny (sorry!)
cpanp i IPC::System::Simple

dpavlin@mjesec:~$ vzps -E axv --no-headers \
  | groupby.pl 'sum:($7+$8+$9*1024),1,count:1' --join 'sudo vzlist -H -o veid,hostname' --on 2 \
  | sort -rn | align | sum.pl -h
webgui.rot13.org  23      1026M OOOOOOOOOOOO                              1026M
0                385       855M OOOOOOOOOO------------                    1882M
saturn.ffzg.hr    32       544M OOOOOO-----------------------             2427M
eprints.ffzg.hr   18       351M OOOO-----------------------------         2778M
arh.rot13.org     20       224M OO----------------------------------      3003M
.pre

^^ find getty processes

.pre
root@mljac:~# ps ax | grep getty | cut -c-5 | xargs vzpid
Pid     VEID    Name
5668    0       getty
5670    0       getty
5672    0       getty
5673    0       getty
5674    0       getty
5675    0       getty
9503    207016  getty
9504    207013  getty
9505    207013  getty
9534    207016  getty
9535    207015  getty
9536    207013  getty
9537    207013  getty
9538    207015  getty
9539    207015  getty
9540    207015  getty
9541    207016  getty
9542    207015  getty
9543    207016  getty
9545    207013  getty
9546    207013  getty
9547    207015  getty
9548    207016  getty
.pre

^ devices inside VE

For example, "fuse"<http://wiki.openvz.org/FUSE>

.pre
dpavlin@brr:/dev$ vzctl set 100 --devices c:10:229:rw --save
.pre

^ Links

* "Recent Advances in the Linux Kernel resource management"<http://community.livejournal.com/openvz/27178.html>

^ vz-tools

{include: [vz-tools]}

^ Related posts on my blog

{fetchrss: http://blog.rot13.org/mt/mt-search.cgi?search=openvz&Template=feed&IncludeBlogs=1 full}
Helpful notes from chat about [ULX3S]

{toc: }

^ i2c

https://gitter.im/ulx3s/Lobby?at=5dfcf29acf771f7708ff69e9

It should not be that hard. I have i2c in SaxonSoc in other projects such as https://github.com/SpinalHDL/SaxonSoc/blob/dev/hardware/scala/saxon/board/blackice/BlackiceSocArduino.scala#L25

The generated board support packages include a generated dts, but it is not used yet and the simple i2c generator that I wrote does not generate the dts.

There is a problem building SaxonSoc Linux, that some build randomly do not work. It seems to be something to do with SDRAM access.

@Dolu1990 is about to redo the SDRAM access for the Ulx3s, which should make it more reliable and faster, as he plans to support double frequency access.

There is a lot of information on the development of the u-boot version here , which might be useful to you - SpinalHDL/SaxonSoc#7

https://github.com/SpinalHDL/SaxonSoc/pull/7

I2c Linux support will also need a spinal.lib driver here - https://github.com/SpinalHDL/linux/tree/linux-5.0.y/drivers/i2c

The terasic De1Soc version of SaxonSoc Linux has a dts entry for an led for disk access - https://github.com/SpinalHDL/buildroot/blob/saxon/board/spinal/saxon_default/spinal_saxon_default_de1_soc.dts#L194

We really need a better GPIO mapping for the Ulx3s. That might involve including adding a second gpio peripheral to the hardware (gpioB) and doing a better lpf file mapping to pins. It might mean increasing the niumbers of pins that support interrupts. It would be good to include access to the buttons and switches and to make it easy to add Pmods that need interrupt support like the enc28j60 one.

^ ecp5pll

> Mario Hoffmann @hoffma_gitlab Aug 05 16:11

Hello, I wanted to have a 90 degree shifted clock. I was trying out the ecp5pll from @emard. I get it running and the clock adjustment seems to work, but somehow it does not get shifted for me. Is this currently not working with yosys and so forth, is there anything I have to take care of, or might it just be a bug on my side? Tried to search this chat a bit and just searched a bit on the internet but the things I found about it were quite old and not necessarily about my problem. Any ideas? I am using the vhdl version btw

> emard @emard Aug 05 16:59

There's some order of signals and small delays between them for dynamic shifting to work. https://github.com/emard/ulx3s-misc/blob/master/examples/sdram/memtest_mister/hdl/top/top_memtest.v#L73 here is module to control phase shifts by pressing of BTN for testing of SDRAM with variable phase shift of the clock to chip

> Mario Hoffmann @hoffma_gitlab Aug 05 17:01

alright, ill look at that. thanks

> Mario Hoffmann @hoffma_gitlab Aug 05 17:53

Oh nice it works. My thinking was just a bit wrong and there was a little bug too. Thanks

> emard @emard Aug 05 18:07

ecp5pll has possibility for fine-precision phase adjustment but this simple BTN module doesn't generate proper phaseloadreg signal https://github.com/emard/ulx3s-misc/blob/master/examples/sdram/memtest_mister/hdl/btn_ecp5pll_phase.v#L51

^ display

https://gitter.im/ulx3s/Lobby?at=5f3b7df7ee58011680b36cb0

> emard @emard Aug 18 09:06

SSD1331 96x64 is full featured OLED beautiful contrast, but currently best buy is ST7789 1.3" 240x240 LCD less contrast but more pix and less $. Do not solder directly the display. Solder female 7-pin header and plug the display. Mechanical stabilization can be 3D printed https://github.com/emard/ulx3s/tree/master/box it will "work" properly only if whole box is printed. There is no problem with heat normally to FPGA but SSD1331 with wrong software commands can become hot to fry fingers and smoke, it happened to me once, colors faded and I just replaced display. Onboard USB-SERIAL can provide 2nd JTAG channel for openocd debugger of RISCV processor it will work but it will be VERY slow (for debug single step ok, but for transferring Mbps no).

^ rtc

https://gitter.im/ulx3s/Lobby?at=5f3b86a1a8c178017657caf6

> emard @emard Aug 18 09:43

Yes for RTC I first saw it "works" but after few reboots I found out that it resets to compile time or something. Core could consult onboard RTC using i2c and then set unix time integer counter which will continue ticking afterwards. For setting RTC we have esp32 and other options. Btw import ntptime; ntptime.settime() will set ESP32 localtime() from a pool of network NTP servers and then esp32 can initialize onboard RTC here I have played with this https://github.com/emard/ulx3s-misc/tree/master/examples/rtc/micropython-mcp7940n/esp32

https://gitter.im/ulx3s/Lobby?at=5f3dbb34750a2741302ea427

> emard @emard Aug 20 01:52

@pnru_gitlab here is 8-bit master interface. I haven't tested it very simple by reading seconds and seems ok https://github.com/emard/ulx3s-misc/blob/master/examples/rtc/i2c_master/proj/hdl/i2c_master_8bit.v

https://gitter.im/ulx3s/Lobby?at=5f3e2d1c07c30d132a9c4f58

> emard @emard Aug 20 09:58

when we are at verilog, I have found on the net several i2c bidirectional bridges. Only one code worked at our board but it works only if compiled by diamond. trellis compiles but doesn't work. Can someone take a look what I have missed: bridge: https://github.com/emard/ulx3s-misc/blob/master/examples/rtc/micropython-mcp7940n/proj/hdl/i2c_bridge.v toplevel usage: https://github.com/emard/ulx3s-misc/blob/master/examples/rtc/micropython-mcp7940n/proj/top/top_i2c_bridge.v

> emard @emard Aug 20 22:04

for me it works for any gpdi_scl/sda PULLMODE=UP, DOWN, or NONE so it's not pull setting. I can prepare a bitstream and micropython to ulx3s-bin example that initializes the clock setting time from NTP

> emard @emard Aug 20 22:18

https://github.com/emard/ulx3s-bin/tree/master/esp32/micropython/rtc can you try this RTC esp32 example for NTP setting? >>> rtcdemo.mcp.time should advance seconds

> emard @emard Aug 21 00:04

RTC traffic also appears at GPDI connector (if there's i2c chip 3.3V->5V adapter soldered on board PCA9306D). Some monitors may hold i2c lines. Also gpdi connector can be used to monitor traffic if e.g. you have hdmi breakout board
If you don't have battery, RTC will keep setting until board is powered off
If you have 2 ULX3S boards and mini-display OLED/LCD, you can connect 2 ULX3S together and on one run scopeio, which will monitor the other i2c traffic
I can prepare scope stuff for such setup because scopeio is vhdl, advanced so much that ghdl won't have chance in near future to compile it

> emard @emard Aug 21 00:09

UPS but we have problem there will be 2 RTC chips colliding address :)
about i2c master 8bit. First write highest bytes 3,2,1 (order not important) and last write byte 0, this should initiate i2c transaction. byte 3=0x80 is READ, byte 3=0x00 is write
If you write 0x00 to register 0x00 (seconds) it will stop RTC. To start, it needs 0x80 written to 0x00 (MSB bit must be set) then the RTC should start "ticking"

> emard @emard Aug 21 18:14

I fixed i2c_bridge.v to work with both trellis and diamond.

> Paul Ruiz @pnru_gitlab Aug 21 23:35

Which way does the battery go? I think with the + side (cap) up and the - side (ribbed) to the PCB?
@emard: thanks for all the links, but your code already appears to work. The long one is interesting, it uses the same two level state machine idea that my non-working i2c controller uses.

> emard @emard Aug 21 23:59

Battery goes + up (larger part of battery should be in contact with metallic holder soldered) - down (smaller part of battery in contact to big circular pad on the PCB
Glad to hear good news that my code works - it hasn't been tested on real CPU but I made some BTNs toplevel and a read and write to register 0 worked

^ scopeio

https://gitter.im/ulx3s/Lobby?at=5f3c27ffa05e464346d2f6ea

> emard @emard Aug 18 21:11

@gkankanh MAX11125 is 1Msa/s total so e.g. if you use 4ch then each channel will be 0.25MSa/s per channel. For oscilloscope it, we have ready solution at hdl4fpga/ULX3S/scopeio you will see traces on monitor. For analysis, onboard USB-serial can do 3Mbps so it could be nearly useable. For faster ADC, yes 100 Mbit ethernet ETH8720 from ebay, module for 2.2$ and for example ebay's AN108 AD/DA module 32MSa/s input, 125MSa/s output https://www.ebay.com/itm/ADDA-Module-Data-Signal-Acquisition-High-speed-Directly-pluggable-connector-/253556250998 also scopeio supports it

^ how to solder headers

https://gitter.im/ulx3s/Lobby?at=5f3cd88378f4a801801336cb

> emard @emard Aug 19 09:45

To have GP/GN not be swapped from "default" design, Either solder 90° FEMALE headers on top side of board (nice for PMODs directly) or straight 0° MALE pins down on bottom side of board. PMODs can also plug to other end of flat cable and pinout will be identical as if 90° was soldered onboard.

^ nmingen

https://gitter.im/ulx3s/Lobby?at=5f3cfbce8b8d4f633effcea7

> Lawrie Griffiths @lawrie Aug 19 12:15

I am using Ubuntu 20.04, so I need to use pip3 not pip. (You can't get python2 pip on 20.04 easily).
The installation instructions for nmgen-boards says "Todo", so I installed it like the m_labs version said.
I changed the blinky example to use ULX3S_85F_Platform and ran that. It complained that tool {} was missing.
It seemed that it needed OpenFpgaLoader for upload, so I installed that, and then the blinky worked.

.pre
from nmigen import *
from nmigen_boards.ulx3s import *


class Blinky(Elaboratable):
    def elaborate(self, platform):
        led   = platform.request("led", 0)
        timer = Signal(26)

        m = Module()
        m.d.sync += timer.eq(timer + 1)
        m.d.comb += led.o.eq(timer[-1])
        return m


if __name__ == "__main__":
    platform = ULX3S_85F_Platform()
    platform.build(Blinky(), do_program=True)
.pre

https://github.com/GuzTech/ulx3s-nmigen-examples

https://github.com/greatscottgadgets/luna

^ SDRAM memtest

https://gitter.im/ulx3s/Lobby?at=5f4ea96249a1df0a12c0d83e

> Lawrie Griffiths @lawrie Sep 01 22:04

@pnru_gitlab @Dolu1990 asked these questions about using the SDRAM, which I thought you might know something about from all your recent work on SDRAM drivers:
I'm thinking about the SDRAM
currently, the soc is at 50 mhz, and the sdram run at 100 Mhz using DDR io
but maybe we should quad pump the SDRAM, and doing some bootloader calibration to ajust read delays
i'm just currently not sure what is the critical path of the SDRAM chip themself
in other words "why they are specified to X frequancy and not more"

> Dolu1990 @Dolu1990 Sep 01 22:05

Moaaaar powaaaaaaaa

> emard @emard Sep 01 22:36

oooh yeea :)) if you want to push SDRAM near the edge and give it some heat, on selected designs it can push 133MHz chips to 180-200 MHz, fmax depends on each board. 12F performs better than 85F. Here's memtest https://github.com/emard/ulx3s-misc/tree/master/examples/sdram/memtest_mister shows results on DVI monitor and with BTNs can adjust phase shift dynamically and watch for errors.

> Dolu1990 @Dolu1990 Sep 01 23:01

<3
Nice thanks :)
So this test controle the shift of the clock sent to the DRAM ?
(it doesn't use the programable input delay ?)

> emard @emard Sep 01 23:08

Yes this has a classic sdram driver that normally needs 90° phase offset to chip hardware, but as fmax is getting higher the actual phase shift which makes it really work moves. PLL is used to provide phase shift. Paul has made a better sdram driver with cool vendor-independent delay solution with a number of NOT gates.Only ns delay per NOT gate remains vendor dependent

> Dolu1990 @Dolu1990 Sep 01 23:09

ok :D

> Paul Ruiz @pnru_gitlab 00:02

@lawrie @Dolu1990 I am not sure I understand the SDRAM questions. In any case, my latest version is here: https://gitlab.com/pnru/cortex/-/blob/master/sdram.v
In particular note new lines 45-47 - I am not sure why, but this mod generally pushes Fmax up to about 200MHz (it depends a bit on the NextPNR seed).

I am not sure what you mean by "using DDR io" - does the SDRAM chip on the ULX3S support DDR? Maybe you mean by DDR that it runs at twice the speed of the CPU or that it uses burst size 2?

I don't know what the critical path in the SDRAM chip is, but I do have a hypothesis. When working with a CAS delay of 3 clocks, the data really arrives after 2 clocks plus 6-7ns (spending on the speed grade). If you clock a grade 6 chip (PC166) faster, a clock cycle will take less than 6ns and the data will only arrive after the third rising clock edge. My guess is that the 6-7ns is related to the speed of the sense amplifiers or something like that.

^ resource utilization

https://gitter.im/ulx3s/Lobby?at=5f4f8c30d4f0f55ebbf93007

> Dolu1990 @Dolu1990 Sep 02 14:12

Is somebody aware of a way to get hearchical ressource utilisation report out from yosys/next-pnr for ECP5 ?
Basicaly, trying to nail down the ressource usage

> David Shah @daveshah1 Sep 02 14:18

You can get a hierarchical report with Yosys by passing -noflatten to synth_ecp5

^ ps2 keyboard

https://gitter.im/ulx3s/Lobby?at=5f57e59c59ac794e02f71d14

> Kid CUDA @KidCUDA_gitlab Sep 08 22:12

anyone used a PS2 keyboard with ULX3S?
like a proper PS2 keyboard with the pins adapted to USB?
is a level shifter needed or is the USB port 5V-data-tolerant?
from the schematic it doesn't look 5V tolerant but I'm not sure how else it would work with just a pure PS2 adapter as suggested in the docs

> emard @emard Sep 08 22:52

@KidCUDA_gitlab US2 pins are 5V tolerant, limited by R and Zener diodes. Still some PS/2 keyboards don't accept 3.3V levels. Best is to obtain combo PS/2+USB they usually work in both modes for ULX3S
PS/2 is normally used over OTG connector for most of our retro-computing cores, apple1-2, ti99, zx, vic20, QL just to name a few

^ cortex

source: https://gitlab.com/pnru/cortex

https://gitter.im/ulx3s/Lobby?at=5f500a7eec534f584fdbeb15

> Paul Ruiz @pnru_gitlab Sep 02 23:11

    8s is super-comfortable! Btw I wonder how did cortex start, before it ever booted they need some filesystem to hold files. Is cortex filesystem mountable by modern linux? How did they made it in early times?

The Cortex was a traditional home computer with Basic in its day. Running Unix on it was my project some 6-7 years ago. It was a long journey: porting a C compiler and tool chain, building simple kernels with a linked in user program (downloaded to the H/W via something similar to S-records), etc. When the time for disk access came, I used a tool to create & manage disk images.

For the original Unix, the file system was almost the first thing that was built, after the assembler (that is how a.out got its name: assembler output). An empty disk image was written by a custom format program. Files were then loaded from paper tape. Some 1969/1970 Unix code can be found here:
https://www.tuhs.org/cgi-bin/utree.pl
In its first incarnations it was all assembler, but many of the core ideas were already there. Some more background is here:
https://www.bell-labs.com/usr/dmr/www/hist.html

> emard @emard Sep 02 23:14

Ahaaaa so unix was not all the time available on cortex hardware. Still I'd wanted to know how did you initially start with populated filesystem. Normally e.g. if we have linux on riscv, we can mount the same partition on x86 PC, copy files and and it will work on riscv, but how was this done on cortex?

So If I understood, you have a tool that from a directory creates disk image, but there's currently no support to actually mount cortex fs on linux for example. linux has some possibility to write a user-space fs driver like "fuse" but I ghess thats difficult and fragile

> Paul Ruiz @pnru_gitlab Sep 02 23:29

You can follow my journey here, in 315 commits:
https://www.jslite.net/cgi-bin/9995/timeline?n=400&y=all&v=0

I use a program ("ufs") which creates a disk image from scratch and then adds files to it. The source code is here:
https://www.jslite.net/cgi-bin/9995/dir?ci=84b2a75947eb76db&name=fsutil

Even on the mini Cortex hardware, the CF Card uses FAT formatting and has an image file on it. I make sure the image is contiguous and the boot loader lets the Unix disk driver know in which sector the image starts. This way I can simply copy disk images to the CF card without needing to use special tools.

Actually, the card also has disk images for other OS's as well - MDEX and NOS, which are somewhat similar to CP/M and MS-DOS 3 respectively.

> emard @emard Sep 02 23:44

There has been a lot of concentrated effort! The idea to use contiguous file in FAT is very good, so the CF itself can be easily written from laptop.

> Paul Ruiz @pnru_gitlab Sep 02 23:53

Thank you. The ulx3s Cortex has it even easier: because of the ESP32, now I don't even have to worry about things being contiguous and I can ftp disk images without having to handle the SD card.

> emard @emard Sep 03 00:34

yeees it was a piece of luck that for esp32 appeared good micropython support with almost all important things working and that spi-jtag adventure turned out successful. I have ulx3s with SD in a box and once inserted SD I never move out, just ftp files. Things will be even better when WROVER-E prototype starts working, 4MB RAM, 16MB FLASH no more out of memory. Bitstreams could be unzipped on-the-fly, even larger FLASH chips supported with 64K and 256K erase blocks (esp32 must buffer data size of erase block and now we are struggling with 4K buffers)

^ saxonsoc audio

https://gitter.im/ulx3s/Lobby?at=5f6482c3603d0b37f43d3ec0

> Lawrie Griffiths @lawrie Sep 18 11:49

I have a 4-cpu 85F SaxonSoc version with music, working now.

It is now inSmp/bitstreams/ulx3s_85f_blue_4core_saxonsoc.bit
I renamed images as oldimages and the new one are in Smp/images.
You need dtb, uImage and you need to untar the new rootfs.tar.
You will also need:

.pre
root@buildroot:~# cat .asoundrc
pcm.!default {
    type            plug
    slave.pcm       "softvol"   #make use of softvol
}

pcm.softvol {
    type         softvol
    slave {
        pcm         "hw:0,0"      #redirect the output to dmix (instead of "hw:0,0")
    }
    control {
           name        "PCM"       #override the PCM slider to set the softvol volume level globally
        card     0
    }
}
.pre

To play music do: mpg123 -T -f 4096 -m file.mp3.
Or to play in the background nohup mpg123 -T -f 4096 -m file.mp3 &
It is set up for a 64MB blue 85f.

https://gitter.im/ulx3s/Lobby?at=5f648d8cf51808513b4f7db5

> olu1990 @Dolu1990 Sep 18 12:35

.asoundrc isn't necessary, it just add volume controles in alsamixer app
I would suggest to not add the .asoundrc for single core versions, as it add quite a bit of overhead
the -m of mpg123 is for mono, if the mp3 bit rate isn't to high, it might be fine in stereo
(for single core)

^ saxonsoc rtc

https://gitter.im/ulx3s/Lobby?at=5f69eb5d6a6e094525ac61f5

https://gitter.im/ulx3s/Lobby?at=5f69f087e1dd7c19548aad12

> Dolu1990 @Dolu1990 Sep 22 14:39

got the rtc to start counting seconds and read it via :

.pre
i2cset -y 0 0x6F 0x00 0x80
sleep 4
i2cget -y 0 0x6F 0x00
.pre

https://gitter.im/ulx3s/Lobby?at=5f6a4562e1dd7c19548b96f0

> Lawrie Griffiths @lawrie Sep 22 20:41

.pre
oot@buildroot:~# cat date.sh 
R6=`i2cget -y 0 0x6f 0x06`
R5=`i2cget -y 0 0x6f 0x05`
R4=`i2cget -y 0 0x6f 0x04`
R2=`i2cget -y 0 0x6f 0x02`
R1=`i2cget -y 0 0x6f 0x01`

YY="${R6:2:2}"
MON="$((${R5:2:2}-20))"
DD="${R4:2:2}"
HH="${R2:2:2}"
MM="${R1:2:2}"

echo "20$YY-$MON-$DD $HH:$MM"
root@buildroot:~# ./date.sh 
2020-9-22 19:40

date -s "`./date.sh`"
.pre

https://gitter.im/ulx3s/Lobby?at=5f6a69588fe6f11963554984

> emard @emard Sep 22 23:15

.pre
#include <stdio.h>
#include <stdlib.h>

#define I2C_SLAVE 0x703
#define O_RDWR 2

int i2c_rtc;

void rtc_open(int addr)
{
  i2c_rtc = open("/dev/i2c-0", O_RDWR);
  ioctl(i2c_rtc, I2C_SLAVE, addr);
}

void rtc_read(unsigned char *buf, int reg, int n)
{
  buf[0] = reg;
  write(i2c_rtc, buf, 1);
  read(i2c_rtc, buf, n);
}

void i2cdemo(void)
{
  int i;
  unsigned char buf[7];
  // mask for BCD          SEC   MIN   HOUR  WKDAY DAY   MONTH YEAR
  unsigned char mask[7] = {0x7F, 0x7F, 0x3F, 0x07, 0x3F, 0x1F, 0xFF};

  rtc_read(buf, 0, sizeof(buf));
  for(i = sizeof(buf)-1; i >= 0; i--)
    printf(" %02x", buf[i] & mask[i]);
  printf("\n");
}

int main(int argc, char *argv[])
{
  int i;
  rtc_open(0x6F);
  for(i = 0; i < 60; i++)
  {
    i2cdemo();
    sleep(1);
  }
  return 0;
}
root@buildroot:/home/root/rtc# ./a.out 
 20 09 22 02 21 14 27
 20 09 22 02 21 14 28
 20 09 22 02 21 14 29
 20 09 22 02 21 14 30
 20 09 22 02 21 14 31
.pre

^ saxonsoc jtag

https://gitter.im/ulx3s/Lobby?at=5f78c209dfe47e4d57464c10

> Lawrie Griffiths @lawrie Oct 03 20:25

The pins to connect to are these - https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.1/hardware/synthesis/radiona/ulx3s/smp/ulx3s_v20_linux_uboot.lpf#L342-L348

> emard @emard Oct 03 20:26

I tried to upload SVF file and it works, (fast). Yes, this pins connection is important. Is there a simple JTAG openocd scan command I can test it to make sure I connected all
Some command similar to

.pre
jtag newtap lfe5 tap -expected-id 0x21111043 -irlen 8 -irmask 0xFF -ircapture 0x5
.pre

> Dolu1990 @Dolu1990 Oct 03 20:29

hoo when openocd run it scan everything

> emard @emard Oct 03 20:29

yes yes I see it on above linked script

> Dolu1990 @Dolu1990 Oct 03 20:30

i'm not sur there a command to rescan, just rerun it ^^

> emard @emard Oct 03 20:31

OK I need to make a bit on the solder and pins to board, then I will test it and when I get vexrisc scanned by openocd jtag I will put it online for remote access

> Dolu1990 @Dolu1990 Oct 03 20:31

you should get a scan like 0x10001FFF

> Lawrie Griffiths @lawrie Oct 03 20:33

@Dolu1990 Doesn't @emard need to build your version of openocd - https://github.com/SpinalHDL/openocd_riscv

> Dolu1990 @Dolu1990 Oct 03 20:34

Yes
so :
You can source the source.sh, and then do a saxon_clone; saxon_openocd
this will build it
Then modify https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.1/bsp/radiona/ulx3s/smp/openocd/usb_connect.cfg#L2 to match the jtag you have installed, and then saxon_openocd_connect

> Dolu1990 @Dolu1990 Oct 03 21:02

sudo apt-get install libtool automake libusb-1.0.0-dev texinfo libusb-dev libyaml-dev pkg-config for the full depedency on debian

> emard @emard 00:00

.pre
Escape character is '^]'.
Open On-Chip Debugger
> init 
> scan_chain
   TapName             Enabled  IdCode     Expected   IrLen IrCap IrMask
-- ------------------- -------- ---------- ---------- ----- ----- ------
 0 fpga_spinal.bridge     Y     0x10001fff 0x10001fff     4 0x01  0x0f
.pre

Got openocd to connect

https://gitter.im/ulx3s/Lobby?at=5f7c33646e0eb844696af0a2

> Lawrie Griffiths @lawrie 11:05

You then need a usb JTAG device, preferably an FT2232 one, and you connect the pins to gn0 - gn3. I have not used openocd with SaxonSoc for a while, but @Dolu1990 uses it all the time.

^ micropython socks

https://gitter.im/ulx3s/Lobby/archives/2020/10/10?at=5f820bfb07361f0cc6430489

> kost @kost Oct 10 19:31 UTC

since you guys around SaxonSoc made such a great progress. I had to do my part of the promise.
Just released socks server for micropython at https://github.com/kost/micropython-socks
that means you can tunnel any SOCKS5 connection over ESP32
since micropython does not come with NAT support, that means you can go to the internet over ESP32 using SOCKS server.
Installation is simple if you have connected ESP32 already to the internet:
You have to run this on ulx3s repl shell:

.pre
import upip
upip.install('micropython-socks')
.pre

and then you can just simply say:

.pre
import socks
socks.start()
.pre

it will start listening on 0.0.0.0:1080 for SOCKS5 connections.
Then you can simply from SaxonSoc test it with the following (or any other host):

.pre
curl --socks5 192.168.4.1:1080 http://ifconfig.co
.pre

^ nmigen - OV7670 with st7789

https://gitter.im/ulx3s/Lobby?at=5f949a4e6c8d484be2a6df34

> Lawrie Griffiths @lawrie Oct 24 23:19

@goran-mahovlic I now have a version of the OV7670 camera application working in nmigen with the st7789 display - https://github.com/lawrie/ulx3s-nmigen-examples/tree/master/ov7670

^ oberon

https://gitter.im/ulx3s/Lobby?at=5f949d40270d004bcfea9716

> Charles Perkins @charlesap Oct 24 23:31

@pnru_gitlab @emard I have created a new disk image based on the www.projectoberon.com sources, only adding some more LED output in the inner core boot process.

Here's a zip file of a disk image that you should be able to directly write to an SD card: https://github.com/io-core/io/blob/main/images/ledboot.img.zip ... this image has the Oberon partition at the correct offset but I did not bother to format the first part with a FAT partition. It boots on my ulx3s with the earlier Oberon .bit file.

.pre
Here's the meaning of the LEDs on booting:
LEDs: 7------- In BootLoad Firmware
LEDs: 7-----1- In BootLoad Firmware
LEDs: 7----2-- In BootLoad Firmware
LEDs: -------0 Control transferred to Modules
LEDs: ------1- Control transferred to Files
LEDs: -----2-- Control transferred to Kernel
LEDs: ----3--- In Kernel - Temporary Trap installed
LEDs: ---4---- In Kernel - Stack and heap origins and limits configured
LEDs: --5----- Kernel SecMap initialized, control transferred to FileDir
LEDs: -6------ Directory traversal complete
LEDs: 7------- Sectors marked, control transferred to Modules which has loaded Oberon.
LEDs: -------- Icons are defined, display subsystem initialized, ready to load System.
LEDs: --5----0 GC in the Oberon Loop
LEDs: --5---10 GC in the Oberon Loop
LEDs: --5--210 GC in the Oberon Loop
LEDs: --5-----
.pre

If there is an early trap before the system introduces a nicer printing trap the leds will fast-blink now with the trap value (0-7).
If the system gets an error trying to load modules after the boot loader successfully loads the kernel (which Oberon needs to actually display graphics and text to the screen) then this code fast-blinks bit zero.

The Oberon source code modified with the LED output is here:

https://github.com/io-orig/projectoberon/blob/main/Kernel.Mod.NL
https://github.com/io-orig/projectoberon/blob/main/FileDir.Mod.NL
https://github.com/io-orig/projectoberon/blob/main/Files.Mod.NL
https://github.com/io-orig/projectoberon/blob/main/Modules.Mod.NL
https://github.com/io-orig/projectoberon/blob/main/Oberon.Mod.NL

^ oled pins

https://gitter.im/ulx3s/Lobby?at=5fa2bcb374152347c213d4ae

> emard @emard Nov 04 11:59

@sthornington yes bitstream projects do rearrange pins. At least GND and 3.3V must match, FPGA is flexible about pins, practical is to plug display directly without wires. Original markings are for SSD1331. ST7789 7-pin is similar but I think pin has BL (backlight) function instead of CS. wifi_gpio17 refers to the same thing and also ESP32 is flexible about SPI pinout so you can match practicaly any combination.
esp32 Channels 1 or 2 itself are the same but if you mount SD card from ESP32 it will always use channel 1 so channel 2 remains free. Without SD channel 1 or 2 are for display the same.

@sthornington of course GND and VCC can't be swapped by FPGA, because OLED draws current and must connect to hard power supply, can't be powered from FPGA 16mA pins (so low power devices actually could swap even GND/VCC). new board will have 8-pin LCD header instead of 7-pin but there's really crowded with routing so additional 2 pins are nearly impossible. But if display has GND and VCC swapped, then it will fit to external connector GN/GN 0-27 so there's still a possibility to plug such display directly on board on the side

^ rtc - i2c master example

https://gitter.im/ulx3s/Lobby?at=5fa7ba79c6fe0131d4e19d31

> emard @emard Nov 08 10:29

There is example https://github.com/emard/ulx3s-misc/tree/master/examples/rtc/i2c_master/proj which makes i2c master in verilog, talks to RTC and displays time as HEX on DVI and LCD. There can't be interference with ESP32 because ESP32 is not directly connected to RTC, FPGA is between them.

^ rt2232 second channel openocd

https://gitter.im/ulx3s/Lobby?at=5fc57a82150b213e980592d8

> emard @emard 00:04

@sthornington if you have external ft2232 it is fastest and normally used as openocd jtag debugger for softcore cpus like litex or saxonsoc linux. Secondary US1 channel is possible and fully supported by openocd, but it will be unacceptably slow to transfer big files like kernel or root fs images. https://github.com/emard/ulx3s-jtagthru/blob/master/scripts/ft231x2.ocd here is some project that has openocd script to export secondard jtag channel to external pins but normally you can use it internally to soft-core too. See also the schematics for your board (v3.0.8) how FTDI is connected to FPGA

> Simon Thornington @sthornington 01:04

@emard thanks, mostly what I want to get going is an on-board scope to dump traces, is there any particular recommended F2232 interface? Does that plug into the jtag header of the below the oled one?

> emard @emard 02:56

any FT2232 breakout board or programmer is ok. It should connect to external pins GP/GN something, depends on where litex/saxonsoc expects them, usually pins 0-5 I guess. I does not plug to JTAG header, it doesn't need to program ECP5 but the CPU RISC5 done by FPGA. If you need onboard scope to display traces in realtime check hdl4fpga project, it has great scope for our boards.

^ esp32 passthrough

https://gitter.im/ulx3s/Lobby?at=601c699dd0d32d7d4fc94dfc

> liebman @liebman Feb 04 22:39

@emard this one is improved. It tristates gpio0 instead if setting it high so that it can be used elsewhere if needed. Also added an enable that can be used as a reset for the esp32.

.pre
module ulx3s_passthru (
  input  wire txd,
  output wire rxd,
  input  wire dtr,
  input  wire rts,
  input  wire esp_txd,
  output wire esp_rxd,
  output wire esp_en,
  output wire esp_io0,
  input  wire en,
);
  // TX/RX passthru
  assign rxd     = esp_txd;
  assign esp_rxd = txd;

  // Programming logic
  // SERIAL  ->  ESP32
  // DTR RTS -> EN IO0
  //  1   1     1   Z
  //  0   0     1   Z
  //  1   0     0   Z
  //  0   1     1   0
  assign esp_en  = (~dtr |  rts) & en;
  assign esp_io0 = ( dtr | ~rts) ? 1'bz : 1'b0; // we only want to drive this pin low

endmodule
.pre

can be called like

.pre
module top(
    input wire clk_25mhz,
    output wire ftdi_rxd,
    input wire ftdi_txd,
    inout wire ftdi_ndtr,
    inout wire ftdi_nrts,
    output wire wifi_rxd,
    input wire wifi_txd,
    inout wire wifi_en,
    inout wire wifi_gpio0,
    output [7:0] led,
    input  [6:0] btn,
    output wire shutdown,
);
    ulx3s_passthru passthru(.txd(ftdi_txd),
                            .rxd(ftdi_rxd),
                            .dtr(ftdi_ndtr),
                            .rts(ftdi_nrts),
                            .esp_txd(wifi_txd),
                            .esp_rxd(wifi_rxd),
                            .esp_en(wifi_en),
                            .esp_io0(wifi_gpio0),
                            .en(btn[0]),  // btn[0] will work as a reset for esp
    );

    // blinky for something to do so we know its operational
    assign led[0]   = btn[1];
    assign led[6:1] = 0;
    assign led[7]   = wifi_gpio0;
endmodule
.pre

> liebman @liebman Feb 04 23:18

thats good to know, which are the (non esp) pins that are clock capable?
(that explains why some of my tests failed)

> emard @emard Feb 04 23:19

They are mentioned on pdf schematics_v3.0.8 let me see
https://github.com/emard/ulx3s/blob/master/doc/schematics_v308.pdf page 2 GP,GN 12 are clock capable and shared with ESP32 but small design fail is those pins are on ESP32 input only. In new board v3.1.5 I tried to fix this by routing one esp32 output capable pin to FPGA clock input capable...

PCLK .. means primary clock capable pins. they are best. GR_PCLK are second best, general routed to primary clock capable

A small fix could be possible with a jumper GN11-GN12 this will connect ESP32 pin 25 GN11 which is output capable to FPGA clock input capable at GN12

^ lpf documentation

https://gitter.im/ulx3s/Lobby?at=601fa45432e01b4f717e0ebb

> Dave Anderson @danderson 09:27

Couldn't find any decent docs other than nextpnr source code and poorly explained technical notes from lattice, so I wrote https://github.com/danderson/ulxs/blob/main/lpf.md
Also comes with pointers to the Lattice tech notes that go into more detail about e.g. ECP5 configuration and I/O pin config.

^ hdmi

https://gitter.im/ulx3s/Lobby?at=6029a8349337c51bc688733e

> splinedrive @splinedrive Feb 14 23:46

Hi, I have done a hdmi reimplementation for ulx3s and blackicemx (ice40) they have the same code base. I hope you like it. I learned from other projects to take the semantic (ulx3s-examples-dvi, fpga4fun, ...) . ulx3s has DDR and SRD support and blackicemx can only DDR. I used the pmod from Luke Wren. It works only with passive resistors and works with long hdmi cables without any problems. https://github.com/splinedrive/my_hdmi_device

^ osd

https://gitter.im/ulx3s/Lobby?at=603a1016457d6b4a948f3208

> Lawrie Griffiths @lawrie 10:25

@sylefeb I am not sure that between us, @emard and I, have documented the OSD and rom loader very well. There are lots of versions of the code in different projects. This is the spi slave from my Z80 template project - https://github.com/lawrie/ulx3s_z80_template/blob/main/src/osd/spirw_slave_v.v
The rest of the code is in that osd directory.
This is a version of the micropython code that reads and writes memory and controls the cpu remotely from the esp32 - https://github.com/lawrie/ulx3s_z80_template/blob/main/esp32/spiram.py
The rest of the esp32 code including osd.py is in that directory.
Here is a youtube video that shows the osd and loader being used - https://www.youtube.com/watch?v=YE7pSuZiN9Y&t=8s
The latest version of the osd look a bit nicer.

This is my TRS 80 Model 1 implementation that has a short description on using the OSD - https://github.com/lawrie/ulx3s_z80_trs80
Perhaps @emard knows of a better description of all this.

The OSD and loader is used by many Ulx3s projects including the Apple II, C64, ZX Spectrum, Mac Plus, QL, TI-99/4A, Amiga (OSD only), Vic 20, NES, SNES, Sega Master System, Orao, etc.
This is a good video by @Speccery that shows the OSD used on the TI-99/4A - https://www.youtube.com/watch?v=zdST3wz00KU
I don't think there is a Risc-V implementation on the Ulx3s that uses the OSD yet.

> emard @emard 12:16

@sylefeb @lawrie OSD loader behaves similar as SPI RAM using 32-bit byte address. FPGA behaves as SPI slave, ESP32 as SPI master. If slave needs to initiate transfer, there is additional IRQ line. Resources at SPI address space are memory mapped, RAM to upload for CPU, reset/halt control, buttons, OSD video chars, floppy disks etc. All is very simple and protocol is not too much standardized so it can be adapted to completely unusual usage. Generally for apple2 c64 vic20 mac trs80 etc we just copy-paste the same thing

^ saxonsoc memory map

https://gitter.im/ulx3s/Lobby?at=606dcc72bc8e6f2e0d2e5be9

> Dolu1990 @Dolu1990 Apr 07 17:14

@irvise:matrix.org

    0x340000

That's the flash address. the CPU copy that part of the flash to the SDRAM at 0x80F80000 (global address). See :

    Memory copy : https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/radiona/ulx3s/smp/app/bootloaderConfig.h#L99
    source address : OPENSBI_FLASH
    destination address : OPENSBI_MEMORY

Then it does similar things with uboot but with that set of addresses : https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/radiona/ulx3s/smp/app/bootloaderConfig.h#L22

    if I generate a program that load to the address 0x380000 it should "just work"

Yes, as long you programe is complied to sit at 0x80F00000 in the global memory space

    And where can I find more info on what memory addresses are being used for MMIO

This autogenerated header file contains all the peripheral addresses :

https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/radiona/ulx3s/smp/include/soc.h#L64

    blink

See https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/software/standalone/blinkAndEcho/src/main.c
used with https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/radiona/ulx3s/smp/include/bsp.h#L15

you can compile it using the command "saxon_standalone_compile blinkAndEcho" It will sit where uboot sit (see <https://github.com/SpinalHDL/SaxonSoc/blob/dev-0.3/bsp/radiona/ulx3s/smp/linker/default.ld#L1>)

^ nmigen

https://gitter.im/ulx3s/Lobby?at=608e7b59d5e2793379e961a8

> Lawrie Griffiths @lawrie May 02 12:13

I am currently working on my nmigen OV7670 camera application - https://github.com/lawrie/ulx3s-nmigen-examples/blob/master/image/camtest.py
That now displays the image on the HDMI monitor and I am starting to add image signal processing functions like brightness and color control, and simple edge detection.

The latest code that I have pushed calculates the mouse pointer (p_x, p_y) - https://github.com/lawrie/ulx3s-nmigen-examples/blob/master/image/image_stream.py

If you set the ImageStream filter switch then pixels with a red channel value less than some threshold are filtered out and the remaining pixels are displayed on the HDMI monitor as pure red. You can adjust the threshold with the up and down arrows, and a value of about 30 seems best. As the threshold is increased the picture turns black except where the laser pointer points, and the spot gets smaller as the threshold is increased. I then calculate the min and max x and y values for those red pixels, and calculate the mid points as p_x and p_y. It seems to be working.

^ saxon esp32ecp5 start

https://gitter.im/ulx3s/Lobby?at=60b93a55a10461235db71cff

> emard @emard Jun 03 22:23

I have just checked saxonsoc linux and it still works, lAN8720 ethernet (ssh) works out of the box. Tetris still compiles and works. A small hint here is the esp32 script for new esp32ecp5 to start linux

.pre
import os
from machine import SDCard, Pin
import ecp5

os.mount(SDCard(slot=3),"/sd")
# copy to root of SD card: dtb, rootfs.cpio.uboot, uImage
# flash with "False" without starting the bitstream
ecp5.flash("/sd/linux/smp/fw_jump.bin@0x340000",0x340000,False)
ecp5.flash("/sd/linux/smp/u-boot.bin@0x380000",0x380000,False)
ecp5.prog("/sd/linux/smp/ulx3s_12f_1core_saxonsoc.bit")
os.umount("/sd")
p12=Pin(12,Pin.IN)
p13=Pin(13,Pin.IN)
p14=Pin(14,Pin.IN)
p15=Pin(15,Pin.IN)
.pre

With esp32ecp5 I'd recommend micropython builds with idf3 because idf4 builds reboot ad SD card deinit (ftp> site umount)

^ dfu and openfpgaloader

https://gitter.im/ulx3s/Lobby?at=6213c5d29a09ab24f36e464d

 I suggest new passthru with DFU integrated. Get or compile latest openFPGALoader. connect to US1 and flash this first: You don't need to unzip, openfpgaloader will detect .gz and unzip on-the-fly

.pre
download https://github.com/emard/ulx3s-bin/blob/master/fpga/dfu/85f-v317/multiboot.img.gz
openFPGALoader -b ulx3s -f --unprotect-flash --file-type raw multiboot.img.gz
.pre

If you hold BTN1 or set DIP SW1 ON and plug board to US2 (optionally press BTN0 if it doesn't power up at plug) then USB DFU compatible device should be detected and you can use much faster flashing like this

.pre
openFPGALoader -b ulx3s_dfu bitstream.bit
.pre

This is for user-bitstream, if you need to reflash bootloader DFU itself from US2, hold BTN1 and BTN2 together and use DFU alternate 5 option back to ESP32: plug to US1 again and try to erase and flash ESP32

^ bootloader switches

https://gitter.im/ulx3s/Lobby?at=62370af9f43b6d783f0de7d8

> emard @emard 12:07

@NostosArch bootloader checks DIP SW1 state on power up. Switching it afterwards doesn't matter. 3 LEDs ON means it is DFU bootloader and passthru, and US2 should enumerate DFU with 3 LEDS it should be possible to flash esp32 with 3 LEDs on. 7 LEDs on means it is in passthru only (not DFU) mode. esp32 should be able to be flashed from passthru-only mode like from DFU+passthru mode. Apart from that I can either say esp32 is flashed with something difficult to get rid of or another PC and OS should be tried.

I didn't follow, but are you using linux microsoft or apple? Does ESP32 respond with ">>>" usbserial 115200 micropyhton prompt on US1?

If you upload blink, then passthru-only mode is overwritten. Still DFU+passthru mode (3 LEDs) is kept (write protected from fujprog, only openfpgaloader can overwrite bootloader). So DFU+passthru 3 LEDS should allow flashing esp32 but of course PCs and OSs compatibility and contents of esp32 already flashed may cause difficulty
Page renamed to [OpenVZ Dapper container]
Page renamed to [Promise SmartStor]
{toc: }

^ first steps

Here I will try to document correct order to read documentation to get setup for ULX3S:

https://github.com/emard/ulx3s-bin/blob/master/README.md

There is also useful things from chat at [ULX3S Lobby]

^^ udev rule

^^ ujprog

.pre
git clone https://github.com/f32c/tools f32c-tools
cd f32c-tools/ujprog/
dpavlin@x200:/mnt/nuc/FPGA/f32c-tools/ujprog$ rm ujprog
dpavlin@x200:/mnt/nuc/FPGA/f32c-tools/ujprog$ make -f Makefile.linux
cc -Wall -D__linux__ -std=gnu99 -static ujprog.c /usr/lib/x86_64-linux-gnu/libftdi.a /usr/lib/x86_64-linux-gnu/libusb.a -o ujprog
dpavlin@x200:/mnt/nuc/FPGA/f32c-tools/ujprog$ sudo cp ujprog /usr/local/bin/
.pre

* create udev rule

^^ passthru to access esp32

source at https://github.com/emard/ulx3s-passthru

.pre
dpavlin@x200:/mnt/nuc/FPGA/ulx3s-bin/fpga/passthru/passthru-v20-85f$ ujprog -j flash ulx3s_85f_passthru.bit
ULX2S / ULX3S JTAG programmer v 3.0.92 (built Nov 19 2019 10:55:50)
Using USB cable: ULX3S FPGA 12K v3.0.3
[Wed Nov 20 18:02:01 2019] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[Wed Nov 20 18:02:01 2019] ftdi_sio 1-5.2:1.0: device disconnected
Programming: 100%
Completed in 24.36 seconds.
[Wed Nov 20 18:02:25 2019] usb 1-5.2: reset full-speed USB device number 56 using ehci-pci
[Wed Nov 20 18:02:26 2019] ftdi_sio 1-5.2:1.0: FTDI USB Serial Device converter detected
[Wed Nov 20 18:02:26 2019] usb 1-5.2: Detected FT-X
[Wed Nov 20 18:02:26 2019] usb 1-5.2: FTDI USB Serial Device converter now attached to ttyUSB0

.pre

^^ update size of your FPGA

.pre
dpavlin@x200:/mnt/nuc/FPGA/ulx3s-bin$ usb-jtag/linux-amd64/ftx_prog --product "ULX3S FPGA 85K v3.0.3"
.pre

power cycle board to get new usb id, test that it's supported by ujprog

.pre
dpavlin@x200:/mnt/nuc/FPGA/ulx3s-bin$ ujprog -r
.pre

^^ esptool and esp32 booting problems

You should be using ecptool from ulx3s-bin repository to quite @emard from https://gitter.im/ulx3s/Lobby#dark-theme

> OK then. If you have issues with ESP32 not booting with SD card but booting without SD card then then the fuse burn script from ulx3s-bin should be run. So far so good, you erased its flash, try linux. If no issue then can try to flash micropython and my new ESP32 OTA programmer ecp5.py end uftpd.py

> I have wisely taken some esptool.py which works and frozen it in ulx3s, versions change all the time and maybe you took something in the middle of development action :)

^^ install micropython

https://github.com/emard/esp32ecp5/

.pre
dpavlin@nuc:/nuc/FPGA$ git clone https://github.com/emard/esp32ecp5/
dpavlin@nuc:/nuc/FPGA$ cd esp32ecp5/
dpavlin@x200:/mnt/nuc/FPGA/esp32ecp5$ wget https://micropython.org/resources/firmware/esp32-idf3-20191120-v1.11-580-g973f68780.bin

.pre

It's important to erase flash or micropyhton will complain about corrupt fat filesystem like:

FAT filesystem appears to be corrupted. If you had important data there, you
may want to make a flash snapshot to try to recover it. Otherwise, perform
factory reprogramming of MicroPython firmware (completely erase flash, followed
by firmware programming).

.pre
dpavlin@x200:/mnt/nuc/FPGA/esp32ecp5$ ../ulx3s-bin/esp32/serial-uploader/esptool.py --chip esp32 --port /dev/ttyUSB0 erase_flash
esptool.py v2.6-beta1
Serial port /dev/ttyUSB0
Connecting....
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
MAC: a4:cf:12:55:c5:60
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 8.7s
Hard resetting via RTS pin...


dpavlin@x200:/mnt/nuc/FPGA/esp32ecp5$ ../ulx3s-bin/esp32/serial-uploader/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 esp32-idf3-20191120-v1.11-580-g973f68780.bin
esptool.py v2.6-beta1
Serial port /dev/ttyUSB0
Connecting....
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
MAC: a4:cf:12:55:c5:60
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1240192 bytes to 783187...
Wrote 1240192 bytes (783187 compressed) at 0x00001000 in 18.7 seconds (effective 529.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

dpavlin@x200:/mnt/nuc/FPGA/esp32ecp5$ microcom -p /dev/ttyUSB0
connected to /dev/ttyUSB0
Escape character: Ctrl-\
Type the escape character to get to the prompt.

>>>
> help()
Welcome to MicroPython on the ESP32!

For generic online docs please visit http://docs.micropython.org/

For access to the hardware use the 'machine' module:

import machine
pin12 = machine.Pin(12, machine.Pin.OUT)
pin12.value(1)
pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)
print(pin13.value())
i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))
i2c.scan()
i2c.writeto(addr, b'1234')
i2c.readfrom(addr, 4)

Basic WiFi configuration:

import network
sta_if = network.WLAN(network.STA_IF); sta_if.active(True)
sta_if.scan()                             # Scan for available access points
sta_if.connect("<AP_name>", "<password>") # Connect to an AP
sta_if.isconnected()                      # Check for successful connection

Control commands:
  CTRL-A        -- on a blank line, enter raw REPL mode
  CTRL-B        -- on a blank line, enter normal REPL mode
  CTRL-C        -- interrupt a running program
  CTRL-D        -- on a blank line, do a soft reset of the board
  CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)
For a list of available modules, type help('modules')
.pre

^^ webrepl

.pre
dpavlin@klin:/klin/FPGA$ git clone https://github.com/hyperglitch/webrepl


.pre

You can send files from command-line:

.pre
dpavlin@x200:/mnt/nuc/FPGA/webrepl$ ./webrepl_cli.py -p ulx3s ../esp32ecp5/ecp5.py 192.168.3.130:/
op:put, host:192.168.3.130, port:8266, passwd:ulx3s.
../esp32ecp5/ecp5.py -> /ecp5.py
Remote WebREPL version: (1, 11, 0)
Sent 22777 of 22777 bytes
dpavlin@x200:/mnt/nuc/FPGA/webrepl$ ./webrepl_cli.py -p ulx3s ../esp32ecp5/uftpd.py 192.168.3.130:/
op:put, host:192.168.3.130, port:8266, passwd:ulx3s.
../esp32ecp5/uftpd.py -> /uftpd.py
Remote WebREPL version: (1, 11, 0)
Sent 19482 of 19482 bytes

.pre

^ open source toolchain

Just use kost's binary builds: https://github.com/alpin3/ulx3s/releases

Or nightly builds: https://github.com/open-tool-forge/fpga-toolchain/releases

*this is old and needs update*

* https://github.com/SymbiFlow/prjtrellis

.pre
dpavlin@klin:/klin/FPGA$ git clone https://github.com/SymbiFlow/prjtrellis
dpavlin@klin:/klin/FPGA/prjtrellis$ ./download-latest-db.sh 

dpavlin@klin:/klin/FPGA/prjtrellis$ cd libtrellis/
dpavlin@klin:/klin/FPGA/prjtrellis/libtrellis$ sudo apt-get install libpython3-dev libboost-python-dev libboost-filesystem-dev libboost-thread-dev libboost-program-options-dev
dpavlin@klin:/klin/FPGA/prjtrellis/libtrellis$ cmake -DCMAKE_INSTALL_PREFIX=/usr/local .
dpavlin@klin:/klin/FPGA/prjtrellis/libtrellis$ make
sudo make install


dpavlin@klin:/klin/FPGA/nextpnr$ cmake -DARCH=ecp5 -DBUILD_GUI=OFF -DTRELLIS_ROOT=../prjtrellis/ .
make
make install




.pre

^ diamond

https://github.com/jandob/lattice-diamond-archlinux/blob/master/eth0DummyToggle

^^ docker

https://gitter.im/ulx3s/Lobby?at=5dff4b08d2dadb38935c570a

https://github.com/dok3r/diamond/

.pre
docker run -it -v /host/fpga:/fpga -- local /host/fpga will end up in /fpga in docker

yes path will be fine
you will be missing make
so inside container you need to yum install make
and yum install libxslt
export ETHMAC=b0:5a:da:XX:XX:XX
set your MAC
docker run -it -v /media/internal/FPGA:/fpga -e LM_LICENSE_FILE=/fpga/license.dat --mac-address=$ETHMAC --privileged --ipc host -v /dev/bus/usb/:/dev/bus/usb/ dok3r/diamond:latest
run docker
yum install make libxslt
go tu project inside fpga folder and find makefile for diamond and then just make

then you share it with docker container with -v /yourHOSTfpgadir:/fpgadockerdir -e LM_LICENSE_FILE=/fpgadockerdir
for version you need to use like this dok3r/diamond:version
versions are here
https://hub.docker.com/r/dok3r/diamond/tags
docker run -it -v /media/internal/FPGA:/fpga -e LM_LICENSE_FILE=/fpga/license.dat --mac-address=$ETHMAC --privileged --ipc host -v /dev/bus/usb/:/dev/bus/usb/ dok3r/diamond:v3.7
like this
Not understanding -v /media/internal/FPGA
that is my local FPGA folder with samples and license.dat
it will mount on docker /fpga
and I see now that I need to share prjtrallis folder to docker so it can do ecppll
docker run -it -v /media/internal/FPGA:/fpga -v /local/prjtrellis/libtrellis:/mt/scratch/tmp/openfpga/prjtrellis/libtrellis -e LM_LICENSE_FILE=/fpga/license.dat --mac-address=$ETHMAC --privileged --ipc host -v /dev/bus/usb/:/dev/bus/usb/ dok3r/diamond:v3.7
but for that we will need @kost
we probably need ecppll and tools already there and compiled with centos- maybe just binaries
.pre

^ NES

https://gitter.im/ulx3s/Lobby?at=5de033f49319bb5190a9c3b6

* https://github.com/ironsteel/nes_ecp5
* flash arbitrary data to flash: https://github.com/ironsteel/tools/commit/cb0c43b6681a52f1cc19b6b70ddd587a307da90c#diff-3b94c2a26ac88b4b2363e058acf1852fR2281
* list of idcode: https://github.com/SymbiFlow/prjtrellis/blob/master/devices.json

* ported to ulx3s: https://github.com/lawrie/nes_ecp5

^ oberon

https://gitter.im/ulx3s/Lobby?at=5e007d1e8897197969e3331c

So, I have now managed to build oberon with diamond 3.7.
What I have to do is:

1. Build it with diamond 3.11, which fails
2. mv clocks clocks_save
3. make clean 
4. cp -r clocks_save clocks
5. run docker for diamond 3.7
6. edit synpbase/bin/config/platform_check to allow 5.* linux.
7. make
8. Use ujprog in host linux to upload generated bit file

Thanks @kost for adding for adding make and libxslt to the docker image. It would be useful if you could patch the platform_check to allow versions before 3.11 to run on 5.* linux.
I got a lot of errors in the diamond 3.7 docker build, but the .bit file was created.
I can now run oberon and can see windows on the screen, but I don't have a working mouse or keyboard. I would need Goran's USB board to get both mouse and keyboard.
@lawrie i fixed in latest v3.7 - just make sure that you're running latest:

docker pull dok3r/diamond:v3.7

woohoo! Cool
@kost I pulled the latest v3.7 about 10 minutes ago, but still had to edit platform_check.
synpbase/bin/config/platform_check has:

        case $VERSION in
            4.* | 3.* | 2.4.* | 2.6.* )

It needs:

        case $VERSION in
            5.* | 4.* | 3.* | 2.4.* | 2.6.* )

I did the docker pull to make sure I had the latest version.
I changed oberon makefile to generate clocks in already existing directory to get rid of annoying mkdir clocks
In my instructions above it is safer to do make ECPPLL=echo in docker, so that it does not try to use ecppll, but uses the saved clocks that were generated on host linux.

^ 21f repack from 25f image

.pre
ecpunpack --input ulx3s_25.bit --textcfg ulx3s_12f.config --idcode 0x41111043
ecppack --input ulx3s_12f.config --bit ulxs3_12f.bit --idcode 0x21111043

.pre

^ compress bitstream

.pre
ecppack --compress
.pre

^ esp32ps2

https://github.com/emard/esp32ps2

^ saxonsoc

^^ linux

Instructions at https://github.com/lawrie/saxonsoc-ulx3s-bin/tree/master/linux
work for me on 85f :-)

https://gitter.im/ulx3s/Lobby?at=5de8ba2f08d0c961b7f3a25f

.pre
git clone https://github.com/SpinalHDL/buildroot.git -b saxon buildroot
git clone https://github.com/SpinalHDL/linux.git -b vexriscv --depth 1 linux
cd buildroot
cp board/spinal/saxon_default/linux_nonet.config board/spinal/saxon_default/linux.config
# Add extra options to board/spinal/saxon_default/linux.config
make spinal_saxon_default_defconfig
make linux-rebuild all -j$(nproc)
output/host/bin/riscv32-linux-objcopy -O binary output/images/vmlinux output/images/Image
# Make sure Image is at least 116KB less than 4MB
.pre

^^ 85f version

https://gitter.im/ulx3s/Lobby?at=5dea74995ac7f22fb57055ae

https://github.com/lawrie/saxonsoc-ulx3s-bin/blob/master/linux/README.md

https://github.com/lawrie/saxonsoc-ulx3s-bin/tree/master/linux/u-boot

https://github.com/SpinalHDL/SaxonSoc/tree/dev/bsp/Ulx3sLinuxUboot

^^ leds

https://gitter.im/ulx3s/Lobby?at=5dec101f46397c721ca4c814

.pre
#!/bin/sh
cd /sys/class/gpio
echo 488 > export
echo out > gpio488/direction
for i in 1 0 1 0 1 0
do
  sleep  0.1
  echo   $i > gpio488/value
done

.pre

^^ slirp

https://gitter.im/ulx3s/Lobby?at=5df1467d0616d6515e20d197

^^ modifications

https://gitter.im/ulx3s/Lobby?at=5dfced993e3f133894ca9b4b

^^ u-boot config for 85f with 64M SDRAM

Modify bootcmd to include:

.pre
load mmc 0:1 0x80000000 /boot/uImage
load mmc 0:1 0x81EF0000 /boot/dtb
fdt add 0x81EF0000
fdt memory 0x80000000 0x04000000
bootm 0x80000000 - 0x81EF0000
.pre

^^ ppp networking

* https://github.com/dok3r/ulx3s-saxonsoc/wiki/ulx3s-networking
* https://github.com/emard/esp32ppp

^^ smp support

https://gitter.im/ulx3s/Lobby?at=5f4ea80bd4f0f55ebbf6ec33

https://github.com/SpinalHDL/SaxonSoc/tree/dev-0.1/bsp/radiona/ulx3s/smp

Instructions there need a bit of modification to run on blue 85f board with 64Mb of ram:

.pre
# Sourcing the build script
source SaxonSoc/bsp/radiona/ulx3s/smp/source.sh

# Clone opensbi, u-boot, linux, buildroot, openocd
saxon_clone

# Build the FPGA bitstream
saxon_standalone_compile bootloader CFLAGS_ARGS="-DSDRAM_TIMING=AS4C32M16SB_7TCN_ps"
SDRAM_SIZE=64 saxon_netlist
FPGA_SIZE=85 saxon_bitstream

# Build the firmware
saxon_opensbi
saxon_uboot
saxon_buildroot

# Build the programming tools
saxon_standalone_compile sdramInit CFLAGS_ARGS="-DSDRAM_TIMING=AS4C32M16SB_7TCN_ps"
saxon_openocd
.pre

Copy generated bitstream

.pre
dpavlin@klin:/klin/FPGA/saxonsoc$ cp SaxonSoc/hardware/synthesis/radiona/ulx3s/smp/bin/toplevel.bit saxon.bit
dpavlin@klin:/klin/FPGA/saxonsoc$ gzip -9 saxon.bit
.pre

Transfer it using ftp

.pre
ftp> put saxon.bit.gz
local: saxon.bit.gz remote: saxon.bit.gz
200 OK
150 Opened data connection.
226 Done.
359484 bytes sent in 10.27 secs (34.1994 kB/s)
ftp> site saxon.bit.gz
.pre

u-boot will fail to boot if you have rootfs on second partition

.pre
SDRAM init
OpenSBI copy
U-Boot copy
OpenSBI boot

OpenSBI v0.6-8-gd7b62b8
   ____                    _____ ____ _____
  / __ \                  / ____|  _ \_   _|
 | |  | |_ __   ___ _ __ | (___ | |_) || |
 | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
 | |__| | |_) |  __/ | | |____) | |_) || |_
  \____/| .__/ \___|_| |_|_____/|____/_____|
        | |
        |_|

Platform Name          : VexRiscv SMP simulation
Platform HART Features : RV32AIMS
Platform Max HARTs     : 4
Current Hart           : 0
Firmware Base          : 0x80f80000
Firmware Size          : 84 KB
Runtime SBI Version    : 0.2

MIDELEG : 0x00000222
MEDELEG : 0x0000b101


U-Boot 2020.07-08304-gd361dd3997 (Sep 05 2020 - 09:45:52 +0200)

DRAM:  32 MiB
MMC:   spi@10020000:mmc@1: 0
Loading Environment from FAT... Unable to use mmc 0:1... In:    serial@10010000
Out:   serial@10010000
Err:   serial@10010000
Net:   No ethernet found.
Hit any key to stop autoboot:  0
Wrong Image Format for bootm command
ERROR: can't get kernel image!
=>
.pre

https://github.com/dok3r/ulx3s-saxonsoc/wiki/SaxonSoc-on-ULX3s

.pre
setenv bootcmd "load mmc 0:1 0x80000000 /boot/uImage;load mmc 0:1 0x80FF0000 /boot/dtb;fdt add 0x80FF0000;fdt memory 0x80000000 0x04000000;bootm 0x80000000 - 0x80FF0000"
setenv bootargs "rootwait console=hvc0 root=/dev/mmcblk0p2 init=/sbin/init mmc_core.use_spi_crc=0"
saveenv
.pre

> Lawrie Griffiths @lawrie Sep 01 21:59

The new SaxonSoc is now working on a 12F for me. Here are the instructions to build from source - https://github.com/SpinalHDL/SaxonSoc/tree/dev-0.1/bsp/radiona/ulx3s/smp
The images and bitstream are here - https://github.com/lawrie/saxonsoc-ulx3s-bin/tree/master/Smp
There is no sdcard image at the moment, but all the files are there for you to build your own.

^ ov7670 pmod

https://github.com/goran-mahovlic/fpga-odysseus/tree/master/projects/OV7670-HDMI

pmod pin mapping:

https://github.com/goran-mahovlic/fpga-odysseus/blob/master/projects/OV7670-HDMI/ulx3s.lpf#L335

^^ SCCB Pullup Resistors

from https://github.com/westonb/OV7670-Verilog

The SCCB interface for the camera requires pull up resistors. You need to solder 4.7K resistors from the SIOD and SIOC pins on the camera to the 3.3V supply. You can do this yourself or have the staff in the EDS help you.

^^ ov7670_rgb_yuv_320x240_colorfilter

https://github.com/JdeRobot/FPGA-robotics/tree/master/Projects/ComputerVision

^^ nmigen

https://github.com/lawrie/ulx3s-nmigen-examples/blob/master/image/camtest.py

^ csi

https://twitter.com/mad_archer_/status/1231249513509261313

https://github.com/libv/fosdem-video-linux

^ litex

(just links, need to test it)

* https://gojimmypi.blogspot.com/2020/03/litex-soft-cpu-on-ulx3s-reloading.html
* https://github.com/timvideos/litex-buildenv/wiki/LiteX-for-Hardware-Engineers
* https://github.com/enjoy-digital/litex

^ spiram

https://gitter.im/ulx3s/Lobby?at=5ef22d4c54d7862dc4a42395

@Speccery thereis also commandline "spiram.py" for some low-level inspection, so to reset TI this works for me

>>> spiram.poke(0x100008,bytearray([0xFC]))
>>> spiram.poke(0x100008,bytearray([0xFF]))

and to read bytes

>>> spiram.peek(0,16)

bytearray(b'\x83\xe0\x00$\x83\xc0\t\x00\x83\xc0\n\x920\xaa\x04`')

^ led

.pre
ftx_prog --cbus 3 DRIVE_0 # green OFF

ftx_prog --cbus 3 SLEEP # green ON if enumerated
.pre

This is active after power cycle

^^ micropython blue led

.pre
>>> from machine import Pin
>>> led=Pin(5,Pin.OUT)
>>> led.on() # upali plavu
>>> led.off() # ugasi plavu
.pre

^ micropython

.pre
from upysh import *

.pre

^ TODO

try various projects for ulx3s

* https://gitlab.com/pnru/cortex

^ c64

part of https://github.com/lawrie/ulx3s_retro

https://github.com/emard/ulx3s_c64

.pre
dpavlin@klin:/klin/FPGA/ulx3s_c64/proj$ time make FPGA_SIZE=25



.pre

^ tfmicro on LiteX/VexRiscv

https://github.com/dlobato/tfmicro-on-litex-vexriscv

^ ML CNN accelerator

https://github.com/BracketMaster/maeri

^ kianRiscV

https://gitAhub.com/splinedrive/kianRiscV/tree/master/linux_socs/kianv_mc_rv32ima_sv32/demo

openFPGALoader -f -o $((1024*1024)) --board=ulx3s bootloader.bin
Up: [Workspace Tour - Table of Contents]
Back: [Conversations]

* Log the outline of an upcoming meeting or phone conference, and give the address out to participants.
* Make links out to separate pages detailing issues as needed.
* Update the agenda before the meeting, or on the fly during the meeting as new discussion points come up.

| ^^^^ Project Widget Planning Meeting

January 13, 2004
Call-in number: 512-555-1212

* [Widget Product Questions] - Bob
* [Widget Performance Standards] - Akash
* [Widget Production Issues] - Janice |

...a Workspace can also help you with [project plans]...
https://github.com/misterblack1/HU-058_ESPHome

fork with NTC, LDR and buzzer

https://github.com/mrceedjay/HU-058_ESPHome-NTC-LDR-Buzzer
BeagleBone Black

{toc}

https://elinux.org/Beagleboard:BeagleBoneBlack

^ info

.pre
root@beaglebone:~# uname -a
Linux beaglebone 3.8.13 #1 SMP Wed Sep 4 09:09:32 CEST 2013 armv7l GNU/Linux
root@beaglebone:~# cat /proc/cpuinfo 
processor       : 0
model name      : ARMv7 Processor rev 2 (v7l)
BogoMIPS        : 297.40
Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x3
CPU part        : 0xc08
CPU revision    : 2

Hardware        : Generic AM33XX (Flattened Device Tree)
Revision        : 0000
Serial          : 0000000000000000
root@beaglebone:~# cat /etc/issue
Angstrom v2012.12 - Kernel \r
.pre

^ serial

Board	Cable
Pin 1 (GND)	Black (GND)
Pin 4 (RX)	Green (TX)
Pin 5 (TX)	White (RX)

^ update board

.pre
dpavlin@nuc:/tmp$ xzcat bone-debian-9.3-iot-armhf-2018-01-28-4gb.img.xz | sudo dd of=/dev/sdc bs=1M
.pre

Insert SD card, press S2 USER/BOOT button to boot from SD card

https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#Flashing_eMMC

.pre
root@beaglebone:~# uname -a
Linux beaglebone 4.9.78-ti-r94 #1 SMP PREEMPT Fri Jan 26 21:26:24 UTC 2018 armv7l GNU/Linux
root@beaglebone:~# cat /etc/issue
Debian GNU/Linux 9 \n \l

BeagleBoard.org Debian Image 2018-01-28

.pre


^^ flash update to emmc

https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#Flashing_eMMC

^ usb network

.pre
root@nuc:/home/dpavlin# ip link

8: enxd05fb8d1023b: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether d0:5f:b8:d1:02:3b brd ff:ff:ff:ff:ff:ff
9: enxd05fb8d1023e: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether d0:5f:b8:d1:02:3e brd ff:ff:ff:ff:ff:ff

root@beaglebone:~# ip addr
5: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d0:5f:b8:d1:02:3c brd ff:ff:ff:ff:ff:ff
    inet 192.168.7.2/30 brd 192.168.7.3 scope global usb0
       valid_lft forever preferred_lft forever
    inet6 fe80::d25f:b8ff:fed1:23c/64 scope link 
       valid_lft forever preferred_lft forever
6: usb1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether d0:5f:b8:d1:02:3f brd ff:ff:ff:ff:ff:ff
    inet 192.168.6.2/30 brd 192.168.6.3 scope global usb1
       valid_lft forever preferred_lft forever
    inet6 fe80::d25f:b8ff:fed1:23f/64 scope link 
       valid_lft forever preferred_lft forever

# matchs IP addresses to find out which interface on bbb is which on nuc (mac on nuc is one less than bbb), so

root@nuc:/home/dpavlin# ifconfig enxd05fb8d1023b 192.168.7.1
root@nuc:/home/dpavlin# ping -c 1 192.168.7.2
PING 192.168.7.2 (192.168.7.2) 56(84) bytes of data.
64 bytes from 192.168.7.2: icmp_seq=1 ttl=64 time=0.817 ms

--- 192.168.7.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.817/0.817/0.817/0.000 ms

# nat bbb

root@nuc:/home/dpavlin# iptables -t nat -A POSTROUTING -s 192.168.7.0/30 -o eth0 -j MASQUERADE

dpavlin@nuc:~$ ssh debian@192.168.7.2
debian@192.168.7.2's password: 
Linux beaglebone 4.9.78-ti-r94 #1 SMP PREEMPT Fri Jan 26 21:26:24 UTC 2018 armv7l

root@beaglebone:/home/debian# ip route add default via 192.168.7.1
root@beaglebone:/home/debian# ip route add default via 192.168.7.1
root@beaglebone:/home/debian# cat /etc/resolv.conf 
nameserver 8.8.8.8
root@beaglebone:/home/debian# ping -c 1 www.google.com
PING www.google.com (172.217.21.100) 56(84) bytes of data.
64 bytes from fra07s32-in-f100.1e100.net (172.217.21.100): icmp_seq=1 ttl=51 time=30.4 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 30.460/30.460/30.460/0.000 ms

.pre


^ PRU

http://ianrrees.github.io/2016/11/20/getting-started-with-beaglebone-pru-programming-the-new-way.html
{toc: }

* http://www.open-mesh.org/wiki/batman-adv-quick-start-guide

^ create new adhoc interface

.pre
iw phy phy0 interface add mesh0 type adhoc

ip link set mesh0 mtu 1524

iwconfig mesh0 mode ad-hoc essid open-mesh ap 02:12:34:56:78:9A channel 6

modprobe batman_adv
batctl if add mesh0

.pre
{toc: }

^ power

* what about power it by USB http://forums.parallella.org/viewtopic.php?f=12&t=1128
* 2A to micro-usb connector next to the rj45 Ethernet http://forums.parallella.org/viewtopic.php?f=50&t=1081
* How to minimize Epiphany standby power? http://forums.parallella.org/viewtopic.php?uid=590&f=10&t=1069&start=0

* Critical issue with non-conforming USB powered hubs. http://forums.parallella.org/viewtopic.php?f=10&t=841
* USB port change http://forums.parallella.org/viewtopic.php?f=10&t=1072
* USB power fix http://forums.parallella.org/viewtopic.php?f=50&t=1510

* Where can I draw 5V for a fan ? http://forums.parallella.org/viewtopic.php?f=23&t=1049&start=10

^ Update boot flash

This is required to get CR10 led working

* http://forums.parallella.org/viewtopic.php?f=49&t=983
* https://github.com/parallella/parallella-hw/tree/master/boards/parallella-I/firmware

enviroment before u-boot update:

.pre
zynq-uboot> env print
baudrate=115200
bitstream_image=parallella.bit.bin
bootcmd=run modeboot
bootdelay=0
devicetree_image=devicetree.dtb
devicetree_size=0x20000
ethact=zynq_gem
ethaddr=04:4f:8b:00:10:13
fdt_high=0x20000000
initrd_high=0x20000000
ipaddr=192.168.0.99
kernel_image=uImage
kernel_size=0x500000
modeboot=run qspiboot
qspiboot=echo Configuring PL and Booting Linux...;mmcinfo;fatload mmc 0 0x4000000 ${bitstream_image};fpga load 0 0x4000000 0x3dbafc;fatload mmc 0 0x3000000 ${kernel_image};fatload mmc 0 0x2A00000 ${devicetree_image};bootm 0x3000000 - 0x2A00000
serverip=192.168.0.101
stderr=serial
stdin=serial
stdout=serial

Environment size: 655/131068 bytes
.pre

flasing output:

.pre
zynq-uboot> mmcinfo
Device: SDHCI
Manufacturer ID: 3
OEM: 5344
Name: SU08G 
Tran Speed: 50000000
Rd Block Len: 512
SD version 2.0
High Capacity: Yes
Capacity: 7.4 GiB
Bus Width: 4-bit
zynq-uboot> fatload mmc 0 0x4000000 parallella.7020.flash.bin
reading parallella.7020.flash.bin

4351800 bytes read
zynq-uboot> sf probe 0 0 0
SF: Detected N25Q128 with page size 64 KiB, total 16 MiB
zynq-uboot> sf erase 0 0x1000000
SF: Successfully erased 16777216 bytes @ 0x0
zynq-uboot> sf write 0x4000000 0 0x$filesize
SF: program success 4351800 bytes @ 0x0

# I skipped set ethaddr because it was already set correctly

zynq-uboot> set AdaptevaSKU SKUA101040
zynq-uboot> saveenv
Saving Environment to SPI Flash...
SF: Detected N25Q128 with page size 64 KiB, total 16 MiB
Erasing SPI flash...SF: Successfully erased 131072 bytes @ 0x4e0000
Writing to SPI flash...SF: program success 131072 bytes @ 0x4e0000
done


.pre

^ GPIO

.pre
dpavlin@parallella:~/parallella-utils$ make gpiotest
gcc -o gpiotest gpiotest.c para_morse.c para_gpio.c -Wall -lrt

dpavlin@parallella:~/parallella-utils$ sudo ./gpiotest 
[sudo] password for dpavlin: 
GPIOTEST - Basic test of para_gpio

Initializing...
Success, pausing 5 seconds
Setting direction (forces output to 0!)...
Pausing 5 seconds
Reading multiple times
> 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
Toggling pin 100000 times...
Took 1.432 seconds, 69818 updates/sec
Write / Read test, 100000 times...
Took 2.618 seconds, 76384 ops/sec
Setting output to 0
Verifying level... OK
Disabling output and monitoring input
Gave up waiting for the input to transition
Setting output to 1
Verifying level... OK
Disabling output and monitoring input
Input flipped after 0 cycles
Closing



.pre

^ FPGA

* Zynq documentation http://forums.parallella.org/viewtopic.php?f=51&t=1114

* Command-line programming http://forums.parallella.org/viewtopic.php?uid=590&f=51&t=1161&start=0

.pre
sudo mknod /dev/xdevcfg c 250 0
sudo -s
cat parallella.bit.bin > /dev/xdevcfg
exit

# programming time
cat /sys/devices/amba.1/f8007000.devcfg/prog_done
.pre

* Routing additional Zynq hard block I/O to PEC_FPGA http://forums.parallella.org/viewtopic.php?f=51&t=1154

* Source http://forums.parallella.org/viewtopic.php?uid=590&f=10&t=1069&start=0

* does the board contains thermal sensor(s) ? http://forums.parallella.org/viewtopic.php?f=23&t=930

.pre
/sys/bus/iio/devices/iio:device0/in_temp0_raw
/sys/bus/iio/devices/iio:device0/in_temp0_offset
/sys/bus/iio/devices/iio:device0/in_temp0_scale

T = ((in_temp0_raw + in_temp0_offset) * in_temp0_scale) / 1000)
.pre

script:

.pre
#!/bin/bash
raw=`cat /sys/bus/iio/devices/iio:device0/in_temp0_raw`
offset=`cat /sys/bus/iio/devices/iio:device0/in_temp0_offset`
scale=`cat /sys/bus/iio/devices/iio:device0/in_temp0_scale`

c_temp=`echo "scale=1;(($raw + $offset) * $scale) / 1000" | bc`
f_temp=`echo "scale=1;(($c_temp * 9) / 5) + 32" | bc`

echo
echo "Zynq Temp: $c_temp C / $f_temp F"
echo
.pre

Modified to display temperature in loop: {file: temp.sh}

^^ headless stream

http://forums.parallella.org/viewtopic.php?f=48&t=1213

removed html traces from device tree

^ serial

* serial port http://forums.parallella.org/viewtopic.php?f=10&t=845

^ hardware

* Eagle library available http://forums.parallella.org/viewtopic.php?f=11&t=559
* KiCad daughter card template http://forums.parallella.org/viewtopic.php?f=11&t=1204 https://github.com/TiZed/Parallella_Template
* Parallella Case With 12V Fan http://www.thingiverse.com/thing:273701
* Parallella clip case https://github.com/kyllikki/designs/tree/master/Parallella
* ARM JTAG http://forums.parallella.org/viewtopic.php?f=10&t=167
* uboot network problems http://forums.parallella.org/viewtopic.php?f=48&t=1667&p=10416&hilit=devicetree#p10416

^ software

^^ device tree

.pre
sudo apt-get install device-tree-compiler

# Compiling a device tree blob from source (.dts-->.dtb):
dtc -I dts -O dtb -o devicetree.dtb zynq-parallella1-headless.dts

# To get source from compiled device tree (.dtb-->.dts):
dtc -I dtb -O dts -o devicetree.dts devicetree.dtb

.pre

^^ /dev

see how to modify devicetree at http://elinux.org/Parallella_Speed_Up_Ubuntu

^^ Debian

http://elinux.org/Parallella_Debian

^^ Epiphany

* cgminer https://github.com/LordRafa/cgminer
{toc: }

^ Similar boards

^^ B3606

https://github.com/UsrnameTaken/B3606

^^ D3806

I have unit, there is no alternative firmware for this model but there is for:

https://github.com/delboy711/BST900

https://www.falatic.com/index.php/161/minghe-buckboost-converters-handy-if-youre-careful

^ B3603

{image: b3603-swim.jpg}

working keys: https://github.com/nlitsme/b3603/network

https://hackaday.io/project/4362-power-supply-b3603-alternative-firmware

{image: control_pinouts.png}

* http://www.eevblog.com/forum/reviews/b3603-dcdc-buck-converter-mini-review-and-how-the-set-key-could-be-fatal/
* https://github.com/baruch/b3603
* http://www.banggood.com/DC-LED-Digital-Controlled-Step-Down-Driver-Power-Module-p-910096.html

^ Specification

Input voltage: 6V ~ 40V
Output voltage: 0V ~ 36V
Output current: 0A ~ 3A
Conversion efficiency: up to 92%
The output ripple: ≤50mV
Working temperature: -40°C ~ +85°C
Working frequency: 150KHz
Short circuit protection: constant current
Voltage regulation/display resolution: 0.01V
Current regulation/display resolution: 0.001A
The minimum display resolution of power: 0.001W
The minimum display resolution of capacity: 0.001AH
Input reverse connect protection: no, if necessary please install diode
Connection mode: terminals
Size: 66 x 50 x 21mm
Weight: 44g

^ backup existing flash

.pre
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s eeprom -r b3606/eeprom.bin
action = 1Determine EEPROM area
Reading 128 bytes at 0x4000... OK
Bytes received: 128
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s flash -r b3606/flash.bin
action = 1Determine FLASH area
Reading 8192 bytes at 0x8000... OK
Bytes received: 8192
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s ram -r b3606/ram.bin
action = 1Determine RAM area
Reading 1024 bytes at 0x0... OK
Bytes received: 1024

.pre

^ unprotect stm8 using stm8flash

https://github.com/vdudouyt/stm8flash/issues/38#issuecomment-195123081

.pre
$ echo "00" | xxd -r -p >ROP_CLEAR.bin
$ stm8flash -c stlinkv2 -p stm8s103f3 -s opt -w ROP_CLEAR.bin 
.pre

^ compile

.pre
pi@rpi2 ~ $ git clone https://github.com/swegener/b3603
Cloning into 'b3603'...
remote: Counting objects: 1109, done.
remote: Total 1109 (delta 0), reused 0 (delta 0), pack-reus
Receiving objects: 100% (1109/1109), 11.04 MiB | 2.90 MiB/s
Resolving deltas: 100% (770/770), done.
Checking connectivity... done.


pi@rpi2 ~/b3603/stm8 $ sudo apt-get install sdcc


pi@rpi2 ~/b3603/stm8 $ make

Code fits the flash, it is 7930

dpavlin@nuc:/nuc/b3603/stm8$ uname -a
Linux nuc 4.4.0-1-amd64 #1 SMP Debian 4.4.6-1 (2016-03-17) x86_64 GNU/Linux
dpavlin@nuc:/nuc/b3603/stm8$ sdcc -v
SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/TININative/ds400/hc08/s08/stm8 3.5.0 #9253 (Mar 21 2016) (Linux)
published under GNU General Public License (GPL)

dpavlin@nuc:/nuc/b3603/stm8$ scp b3603.ihx rpi2:stm8flash/





.pre

^ flash

.pre
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -w ./b3603.ihx 
action = 2Determine FLASH area
Writing Intel hex file 8160 bytes at 0x8000... Tries exceeded

# unprotect flash

pi@rpi2 ~/stm8flash $ echo "00" | xxd -r -p >ROP_CLEAR.bin
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s opt -w ROP_CLEAR.bin 
action = 2Determine OPT area
Writing binary file 1 bytes at 0x4800... OK
Bytes written: 1

# 



.pre

^ serial

.pre
dpavlin@x200:/x200/stm8$ microcom -p /dev/ttyUSB0 -s 38400
connected to /dev/ttyUSB0
Escape character: Ctrl-\
Type the escape character followed by c to get to the menu or q to quit

B3603 starting: Version 1.0.1
.pre

.pre
pi@rpi2 ~/b3603/stm8 $ cat ~/b3603.sh
#!/bin/sh -x

microcom -s 38400 -p /dev/serial/by-path/platform-3f980000.usb-usb-0\:1.5.1\:1.0-port0
.pre

^ calibrate

.pre
dpavlin@cubieboard:/mnt/nuc/b3603/stm8$ git diff ./calibrate.py
diff --git a/stm8/calibrate.py b/stm8/calibrate.py
index f94f866..313e1f6 100755
--- a/stm8/calibrate.py
+++ b/stm8/calibrate.py
@@ -153,7 +153,8 @@ class Multimeter(object):
         return self._sample() != None
 
     def _sample(self):
-        p = os.popen('sigrok-cli -d %s:conn=%s --samples 1' % (self.model, self.portname))
+        print('## sigrok-cli -d %s:conn=%s --samples 1' % (self.model, self.portname))
+        p = os.popen('sigrok-cli -d %s:conn=%s --samples 1 -O analog' % (self.model, self.portname))
         s = p.read()
         p.close()
         return float(s.split(' ')[1])
@@ -214,9 +215,9 @@ def calibration_voltage(auto):
         return
 
     if auto == True:
-        dmm = Multimeter(sys.argv[3], sys.argv[4])
+        dmm = Multimeter(sys.argv[4], sys.argv[5])
         if not dmm.open():
-            print 'Failed to open serial port to multimeter on serial %s model %s' % (sys.argv[3], sys.argv[4])
+            print 'Failed to open serial port to multimeter on serial %s model %s' % (sys.argv[4], sys.argv[5])
             psu.close()
             return



dpavlin@cubieboard:/mnt/nuc/b3603/stm8$ ./calibrate.py -a voltage /dev/ttyUSB0 /dev/ttyUSB1 uni-t-ut61e-s
er
OPEN "M: B3603"
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
PSU Input voltage is 11305.0 mV, will use 10 steps between 10 mV and 4000 mV
0 . Setting voltage to 10 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Multimeter samples vary too much, stddev=0.244349, data: [1.2358, 0.8785, 0.6413]
Failed to read stable value, trying again, maybe
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 0 Set voltage 10.000000 mV Read voltage 0.273667 mV PWM 114.0 ADC 132.0 (0.149)
1 . Setting voltage to 409 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 1 Set voltage 409.000000 mV Read voltage 0.403467 mV PWM 185.0 ADC 172.0 (0.377)
2 . Setting voltage to 808 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 2 Set voltage 808.000000 mV Read voltage 0.807800 mV PWM 257.0 ADC 244.0 (0.772)
3 . Setting voltage to 1207 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 3 Set voltage 1207.000000 mV Read voltage 1.212667 mV PWM 329.0 ADC 316.0 (1.179)
4 . Setting voltage to 1606 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 4 Set voltage 1606.000000 mV Read voltage 1.617200 mV PWM 401.0 ADC 387.0 (1.574)
5 . Setting voltage to 2005 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 5 Set voltage 2005.000000 mV Read voltage 2.022333 mV PWM 473.0 ADC 459.0 (1.975)
6 . Setting voltage to 2404 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 6 Set voltage 2404.000000 mV Read voltage 2.425333 mV PWM 545.0 ADC 531.0 (2.376)
7 . Setting voltage to 2803 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 7 Set voltage 2803.000000 mV Read voltage 2.829333 mV PWM 617.0 ADC 603.0 (2.782)
8 . Setting voltage to 3202 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 8 Set voltage 3202.000000 mV Read voltage 3.232000 mV PWM 689.0 ADC 675.0 (3.178)
9 . Setting voltage to 3601 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 9 Set voltage 3601.000000 mV Read voltage 3.635667 mV PWM 761.0 ADC 747.0 (3.579)
['OK', '']
ADC
(0.005373500905021045, -0.8923354860819778) 352 58480
['OK', '']
PWM
(179.88709677419354, 185.25806451612908) 11789080 12141072
['OK', '']

.pre