Home Archive Code About

2017-05-31 23:53:13 PDT -- d3fault modified the file: Projects/wasdf/assets/ArduinoSketches/ArduinoWriteChangesOnAnalogPinsToSerial/ArduinoWriteChangesOnAnalogPinsToSerial.ino
2017-05-31 21:36:21 PDT -- d3fault modified the file: todo.txt
2017-05-31 01:23:45 PDT -- d3fault created the file: Documents/minddump/2017/5/1496186493-TJ1445.txt
In theory, fallacious arguments don't work. In practice, they very definitely do.
2017-05-31 01:18:14 PDT -- d3fault modified the file: Projects/wasdf/src/lib/wasdfarduino.cpp
2017-05-31 00:41:07 PDT -- d3fault created the file: Documents/minddump/2017/5/1496183595-LhX832.txt
By saying (understanding?) "At least I can save myself", and then doing so, I become a part of the problem. We, as a species, have really bad case of voters fallacy. If we were to all simultaneously try to "save everyone", then it would work. OT'ish: I am saving myself, but I'm not going to be a hypocrite about it; I admit that in doing so I am part of the problem. I don't really want to [waste my time] but I can't live with myself if I don't at least dispatch a low priority background thread to try to solve the problem. We really just need a vote, but I'm not even sure such "federal doanything" votes exist. states have them apparently (weed just become legal because of popular vote), but does the federal government? I don't think it does, which means in it's current form (had:state) it's a piece of shit. I, a citizen, must be able to call to vote anything at all on a federal level. If the "constitution" or whatever core document doesn't allow for this, it should be altered (or rewritten) so that it does. If you say "but a cititzen can't modify those core documents", then I question the validity of those documents to begin with; after all, they were made by just random ass humans (that gave themselves fancy titles, but that's irrelevant). A politician can't block this because the entire purpose of it is to side-step political corruption in the first place. Meh in all honesty, holding a vote yourself and it passing is plausible, but what then? Aren't taxes supposed to be used to create those solar powered food farms? Randomly winning some "unofficial" (by their definition) vote doesn't all-of-the-sudden give you tax spending abilities. Remember they'd DIE before giving up their power? Hmm so the vote would need to be official -- meh this'd never happen (but still I should press on (low priority background task), I must. I can't not)
2017-05-30 01:49:10 PDT -- d3fault modified the file: Projects/wasdf/src/lib/wasdfarduino.h
2017-05-30 01:21:44 PDT -- d3fault created the file: Projects/Ideas/all.projects.should.make.testing.videos.rather.than.formal.standardized.testing.documents.written.out.because.fuck.that.txt
The easiest way to make an STD (standardized testing document) is to film (screen record) yourself using every feature of an app. Even as new features are added, you could still concat that new video onto the older video. Thinking about "what to test" is a painfully boring subject, but being mostly braindead while following the same tests happening on video (differences will JUMP OUT) is ez and you can also be more confident that you performed every test (doing the testing from memory always leaves you asking-yourself/wondering if you left any tests of features out.
2017-05-30 01:15:40 PDT -- d3fault modified the file: Projects/MindDumper/src/minddumperfirstlaunchdirselector.cpp
2017-05-30 01:13:44 PDT -- d3fault created the file: Documents/minddump/parkour.danzig.jlsdkfjasdlasdfkjoiuerljsdklfjsdlkf.txt
Due to the nature of this world, one can only save themself. At least I can do that. I want to go run around the forest parkour-danzig wearing wasdf (and hope I don't get shot) for the cheap thrill of it. bonus points for not hurting anyone in the process (the only way to win in the us "economy" is to out-compete (hurt) others).
2017-05-29 21:29:39 PDT -- d3fault created the file: Documents/minddump/lsjflkasjflkdjasfljasdlfkjsdoiuwlerjoiulkjslfkd.txt
kek some forest rangers on quads scoped me out a few mins ago. they paused briefly on the trail next to where I am, checked out my setup... camper + screen house (fkn flies) + solar panel + solar cooker... probably saw the trash bag I had hanging up (and no litter on the ground)... looked at me in the camper waving at them... then drove off (didn't even wave back :-/).
2017-05-29 21:26:36 PDT -- d3fault created the file: Documents/minddump/lkjslkdfjlsdkfjdlsfjdlskfjlkjoiuewlrjlkjdfslk.txt
Eh enough with the sensationalist writing and borderline treason... that's shit's boring BECAUSE I'm not committed to it. Still this is my mind dump...
2017-05-29 19:42:49 PDT -- d3fault created the file: Documents/minddump/lkjskldfjklsdfjlksdjflkjsdfkljdslfkjdsofulewrjoulsf.txt
I unfortuately understand that a bloody rebellion is probably the only way to go. I also understand that I (we?) probably can't win anyways. Even if we could, it feels completely immoral to say "blowing up Google HQ is the way to go". However when your enemy uses violence to control you, you are forced to use violence to escape it. I do consider the threat of jail/prison to be violence (and not just because of anal/oral rape): stealing time from a human is an act of violence. Throwing them in a cage, like an animal, is an act of violence. Spartacus may have had the [human] right and a damn good reason (slavery) to rebel..... but he still fucking lost/died, man. My mind scours for a peaceful solution. USA can in theory transition. In practice, though? Since I can't find such peaceful solution and since I don't think a bloody rebellion would succeed (though if I ever confirm infinite multiverse theory... then I KNOW it would succeed ;-P)... I'll just go back to dicking around with electronics/music/etc for fun and lulz. A cheap thrill, fuck it. Hopefully by freezing myself I can wake back up to a world much less retarded.
2017-05-29 19:29:04 PDT -- d3fault created the file: Documents/minddump/lskdfjkllkjasfljsdafkljsdlfkjsldkfjdlsfjlsdjflkj.txt
A government by the people for the people, or a government by the corporations for the corporations? Yes a corporation is made up of numerous people, but as an "entitiy" there is no single emotional/compassionate/human consciousness driving that entity; it's, as rms put it, a psychopath (I prefer the term sociopath, but w/e). A publicly traded corporation is required by law to chase profit with complete disregard for humanity as a whole (except the few regards that laws demand of such corporations: e.g. "no littering").
2017-05-29 19:24:11 PDT -- d3fault created the file: Documents/minddump/lsjflksjflkdsjfdklsfjdklsjfsdoiulwjeroulksdjfl.txt
When the US economy is working the best it can, we are all at war with one another (survival of the fittest, dog eat dog, "we can't all win"), united only under the idea that our government, through lobbying/bribery, gets to decide who dies.
2017-05-29 09:19:37 PDT -- d3fault modified the file: Projects/MindDumper/src/minddumperfirstlaunchdirselector.h
2017-05-29 09:15:09 PDT -- d3fault modified the file: Projects/MindDumper/src/minddumpermainwindow.cpp
2017-05-29 08:53:38 PDT -- d3fault modified the file: Projects/MindDumper/src/minddumpermainwindow.h
2017-05-29 08:39:52 PDT -- d3fault created the file: Documents/minddump/lasdjfldksjflksdjfoiuwelrjosuflsdfjsofiudslkfjsdofiulk.txt
I have higher hopes for humanity. As long as our well being depends on the economy, we will always be vulnerable to the economic "depressions" in which people (had-here:literally) starve to death. The economy is a weakness; our dependency on the economy is a weakness we must get rid of. A worldwide government (by the humans for the humans) would be much better. It could guarantee, using solar powered robot farms, that humans don't have to work to not die (had:"survive" instead of "not die"). Whether or not the "economy" exists on the side is irrelevant. ^I'd be a dollar that the economy would go out of it's way to make that robot-provided existence miserable. It would do this so you would pay it for an existence [of any kind (could even be the same kind of existence, but with slightly less for you and slightly more for them)]. ^^The economy does right at this very moment work against a worldwide government. Lots of people would lose a lot of power. They are willing to kill for it. Without a fucking doubt. ^^^idk wat do about that problem tbh. It seems the only way to beat them is for infinite multiverse theory to be true ("because in at lease one universe, you have to survive a given event (had:experience)"). re: infinite universe theory -- you can live knowing it is true or die trying to find out if it is true, or live not trying to find out if it's true (the default)
2017-05-30 01:15:40 PDT -- d3fault created the file: Projects/MindDumper/src/minddumperfirstlaunchdirselector.cpp
#include "minddumperfirstlaunchdirselector.h" #include <QVBoxLayout> #include <QHBoxLayout> #include <QDateTime> #include <QLabel> #include <QStandardPaths> #include <QPushButton> #include "labellineeditbrowsebutton.h" MindDumperFirstLaunchDirSelector::MindDumperFirstLaunchDirSelector(const QString &optionalSeededDirectoryProbablyPassedInAsAppArg, QWidget *parent) : QDialog(parent) { bool prepopulateDirWithGuessGoodStartingPoint = optionalSeededDirectoryProbablyPassedInAsAppArg.isEmpty(); QString mindDumpDirectoryPrepopulatedGuess; if(prepopulateDirWithGuessGoodStartingPoint) { //guesses:"documents" (if writable) -> desktop (dgaf if writable, but must exist) -> "/" QString guess = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); //TODOreq: guess. something like ~/ or /var/documents or fuck if I know. let Qt guess for you :). maybe the "desktop" is a good guess (most people don't know how to get to their documents folder (except using a shortcut, so actually yea maybe Documents is better guess dir. hell "Documents" dir could be used as minddump dir for all I care, since I generate filenames so safely))? if(guess.isEmpty()) { QStringList desktopLocationsMaybe = QStandardPaths::standardLocations(QStandardPaths::DesktopLocation); if(!desktopLocationsMaybe.isEmpty()) { guess = desktopLocationsMaybe.first(); } else { guess = "/"; } } mindDumpDirectoryPrepopulatedGuess = guess; } else { mindDumpDirectoryPrepopulatedGuess = optionalSeededDirectoryProbablyPassedInAsAppArg; } removeTrailingSlashIfPresentButNotIfItsTheOnlyChar(&mindDumpDirectoryPrepopulatedGuess); QVBoxLayout *myLayout = new QVBoxLayout(); QDateTime currentdateTime = QDateTime::currentDateTime(); QString currentYearNumberAsString = QString::number(currentdateTime.date().year()); QString currentMonthNumberAsString = QString::number(currentdateTime.date().month()); QLabel *welcomeText = new QLabel("Welcome. Please choose a MindDumper directory to save your files in. In that directory, your files will be stored in a folder named after the year, and then a subfolder named after the month.\n\nSo for example if you choose: " + mindDumpDirectoryPrepopulatedGuess + "\nThen we will save files like this: " + appendSlashIfNeeded(mindDumpDirectoryPrepopulatedGuess) + currentYearNumberAsString + "/" + currentMonthNumberAsString + "/example.txt\n\n"); welcomeText->setWordWrap(true); myLayout->addWidget(welcomeText); m_MindDumpDirectoryRow = new LabelLineEditBrowseButton("Save files in folder:", LabelLineEditBrowseButton::OpenDirectoryMode); myLayout->addLayout(m_MindDumpDirectoryRow); QHBoxLayout *quitAndOkButtonsRow = new QHBoxLayout(); QPushButton *quitButton = new QPushButton("&Quit"); connect(quitButton, &QPushButton::clicked, this, &MindDumperFirstLaunchDirSelector::reject); quitAndOkButtonsRow->addWidget(quitButton); QPushButton *okButton = new QPushButton("&Ok"); connect(okButton, &QPushButton::clicked, this, &MindDumperFirstLaunchDirSelector::accept); quitAndOkButtonsRow->addWidget(okButton); myLayout->addLayout(quitAndOkButtonsRow); setLayout(myLayout); m_MindDumpDirectoryRow->lineEdit()->setText(mindDumpDirectoryPrepopulatedGuess); } QString MindDumperFirstLaunchDirSelector::selectedDir() const { return m_MindDumpDirectoryRow->lineEdit()->text(); }
2017-05-29 09:19:37 PDT -- d3fault created the file: Projects/MindDumper/src/minddumperfirstlaunchdirselector.h
#ifndef MINDDUMPERFIRSTLAUNCHDIRSELECTOR_H #define MINDDUMPERFIRSTLAUNCHDIRSELECTOR_H #include <QDialog> class LabelLineEditBrowseButton; class MindDumperFirstLaunchDirSelector : public QDialog { Q_OBJECT public: explicit MindDumperFirstLaunchDirSelector(const QString &optionalSeededDirectoryProbablyPassedInAsAppArg = QString(), QWidget *parent = 0); QString selectedDir() const; private: static inline void removeTrailingSlashIfPresentButNotIfItsTheOnlyChar(QString *inputString) { int inputStringLength = inputString->length(); if((!inputString->endsWith("/")) || inputStringLength < 2) return; *inputString = inputString->left(inputStringLength-1); } static inline QString appendSlashIfNeeded(const QString &inputString) { if(inputString.endsWith("/")) return inputString; return inputString + "/"; } LabelLineEditBrowseButton *m_MindDumpDirectoryRow; }; #endif // MINDDUMPERFIRSTLAUNCHDIRSELECTOR_H
2017-05-29 05:47:15 PDT -- d3fault modified the file: Projects/MindDumper/src/MindDumper.pro
2017-05-29 04:59:10 PDT -- d3fault created the file: Documents/minddump/2017/5/1496026719-MTJ876.txt
I'm in an incredibly optimistic mood lately. It might stem from my happiness of late.
2017-05-29 04:44:31 PDT -- d3fault created the file: Projects/wasdf/design/checksummed.message.protocol.notes.on.when.to.read.the.message.header.txt
we want to wait before we see N bytes before checking/verifying that we have a valid message header. N bytes being sizeof(SYNC) + sizeof(checksumOfSize) + sizeof(dataSize) we could read SYNC and then keep an eye out for checksumOfSize and then keep an eye out for dataSize, but we might as well keep it simpler for ourselves by not reading that data from Serial until all 3 pieces of the header are already available. this gives us just 2 code paths: "watching for message header", "reading in message data [and will call a callback when the num bytes have been read in]" TODOreq: of course, we still need to scan the remainder of that "potential header" for the word SYNC even if the first 4 bytes that we read in weren't SYNC. any candidate for "SYNC" gets repositioned (putchar? maybe there's a peek?) so that it will be detected by the same "watching for message header" code that got us here in the first place
2017-05-29 04:32:23 PDT -- d3fault created the file: Projects/wasdf/design/checksummed.message.protocol.txt
binary protocol: SYNC,checksumOfSize,size,checksumOfData,data "size" is sizeof(checksumOfData) + sizeOf(data) the reason we send the checksum of the size is in case the size is corrupt and huuuuge, it might cause us to become waaay out of sync with the serialized message stream (cause us to miss a lot of messages (unless we saved a copy before doing the checksum and replayed them, but fuck that)), because we can't perform the checksum later until _all_ data has been read in. checksum of size is just an early warning system. yes it adds overhead but it also adds simplicity (or, decreases complexity? sameshit). oh and OT but I still want to write it somewhere fuck: we have to search for the word "SYNC" in all 4 types that are sent following a SYNC (including the boundaries from 1 type to the next). we have to search for that false positive "SYNC" _before_ we send (on sender side), and we have to take measures so that it doesn't say "SYNC" accidentally. this is a TODOreq and is somewhat important, but shouldn't go in initially because it makes the task of implementing the protocol initially too complicated.
2017-05-29 04:16:09 PDT -- d3fault created the file: Documents/minddump/2017/5/1496023906-MTJ789.txt
Who gives a shit, technology will fix everything eventually anyways. But meh I want awesomeness NOW. I look left and right at my neighboring countries and it makes me sad to see how shitty they're doing. Hell even my own country has extremely varied success rates. A lot of people have it great and a lot of people have it shit. The reason for it is easy to understand: the only way to be successful in this economy (and yes this economy has taken over many people's lives) is to out-compete others. "Well we can't all win", you say. I disagree, and a government "for the people by the people" should strive to achieve exactly that. Government owned solar powered food farms (and automating shelter is ez too (everybody deserves a space at least as big as their body! good I'm glad we agree)). "I promise not to trespass on anybody else's body." -me, now
2017-05-29 04:07:09 PDT -- d3fault created the file: Documents/minddump/2017/5/1496023209-MTJ782.txt
The United States of America, in all it's greatness (or least shittiness), was formed from the human species, at a starting-to-become-technologically-advanced state, rebelling against itself to start anew. I have written about this before and how the later it happens, the better. The USA must adapt. There is no place for us to "rebel against ourselves and start anew". Even the moon wouldn't work, assuming you could get there. The USA has become it's own monster, the very thing it escaped when it was formed from rebellion. So anyways since it's probably not possible (unless I can convince all the stupid people around me... which isn't very likely), let's consider the fact that it probably can't be done peacefully. Just like Britain tried to eat (what is now) the USA, so too does the USA eat everything. USA is an adaptable system. Just the mere act of analyzing what I've just said means we could migrate the USA to that hypothetical 3rd state (with peace). Core documents (I don't know which) would have to be rewritten, but who gives a shit we have gotten so much better at writing shit since then. It's not a matter of editting them, it's a matter of rewriting them under different mindsets. What different mindsets am I talking about? This is where I'm supposed to explain it to you, but I'm not going to waste my breath (or keystrokes (time)).
2017-05-29 03:51:47 PDT -- d3fault created the file: Documents/minddump/2017/5/1496022570-LhX790.txt
If I only ever know unix time (seconds since epoch), I can do exactly that (assuming I don't [subconsciously] calculate the "date" using that number (but eh that math is hard without calculator). OT: and yea I know there are tricks to make it easier to calculate in your head, but I have no use for those because my computer does all my calculations for me.
2017-05-29 03:48:17 PDT -- d3fault created the file: Documents/minddump/2017/5/1496022435-MTJ790.txt
I want to block out the time and forget what day it is. Obviously I'll always be able to (as long as I see daylight) guess what time it is, but mostly I want to forget the date. I hate hearing/feeling/knowing the "tick" of my system (my life and this universe I live in).
2017-05-29 03:44:38 PDT -- d3fault created the file: Documents/minddump/2017/5/1496021883-MTJ782.txt
The philosopher defines things using arbitrary terminology and is fine with it, the physicist tries to connect all the pieces (starting from a single point/formula) and [so far] can't. "It's illogical to demand vibrations spend a majority of their time (time vibrating, that is) censoring vibrations that happen to get tangled up in the recordinds of a person's own vibrations" s/vibrations/motions <-- this is the thought that triggered the first line. maybe it was "movements". they both ask (had:say) "what is movements?", but philosophers come to an agreement on what it is (arbitrarily defined (like everything)) and move on. Maybe philosophers don't, but I do. And I tend to think that I'm thinking (lol) philosophically (rather than..... scientifically? idk arguably philosophy is a science).
2017-05-28 20:55:54 PDT -- d3fault created the file: Documents/minddump/2017/5/1495997462-nnS784.txt
Overall I like Better Call Saul, despite it being rather slow so far (oh and I haven't seen the past 2 eps xD), but I found what I consider to be a rather large plot hole. Or more appropriately, an accurate representation of a typical STUPID human. Bob Odenkirk's _character_ is fucking retarded (like most humans): he's BREAKING BAD because bawww his big brother was mean to him bawwww. W.W. had a good reason to break bad: "I'm 'bout to die and want to leave my family with some money". Odenkirk's though, "boo hoo my brother blocked me from being an attourney at his company, bawww". The point I'm trying to make is that it's stupid to let your interactions with others have such a large impact on your decision making process (ie, how you live your life). Fuck your brother, cut him out of your life, but don't let his actions (mean'ness) affect yours! Basically I don't want to be an asshole just because my father is ;-).
2017-05-28 20:49:21 PDT -- d3fault created the file: Documents/minddump/2017/5/1495996366-LhX784.txt
I think I have the [human] right to release [most of] my "copyright iffy" archive. This chain of thought came to me while imagining/preparing-for a court case that would [maybe/probably] arise out of my releasing it. Given: to hold information private can give power to a person who acertains that information Anyone who hacks my "copyright iffy" archive (and indeed I made it hackable because I myself want to be able to access it (it's impossible to have one without the other)) will then have power over me: can blackmail me etc etc or just see into my brain further than most others can. Since society is flooded with copyrighted works (advertisements mostly), it is illogical to expect a human who records their [entire] life to retroactively censor those copyright infringing recordings. Such a human being would either have to detach from society entirely or spend more hours than are available in a given day editting out copyright infringing materials. e.g. if I'm up for 16 hours (recording) and sleeping for 8 hours (also recording, because I try to speak in my sleep), what hours do I have left to go and censor those 24 hours (unless I sacrifice entire days of my life doing it, which means AT LEAST half of my lifetime will be spent censoring previous days (assuming the [waking] recordings are littered with copyright infringing material, and they would be). This might not apply retroactively but only going forward. I knew back then (though I didn't understand the gravity of it) that my talking while listening to music was probably copyright infringing, so those kinds of infringement are [probably] not justified. But going forward, not myself being the one to initiate the playback of such copyright infringing materials, I can... I _MUST_... be able to record and redistribute those works which, not because of my doing, are contaminated with copyright infringing works. Let's ignore the fact that I try to stay away from society and it's copyrighted BRAINWASH: whether I like it or not I am forced to enter and interact with society every once in a while. So since a government obviously can't push it's citizens away from it (society), and since it's illogical to expect/demand a human to censor their own 24/7/365 lifestream, it is therefore unconstitutional in the cases described above to charge a person with copyright infringment. If it is found to be constitutional (by stupid/corrupt lawyers/judges/politicians/etc), then the constitution itself is illogical and I will tear it up and write a new one.
2017-05-28 20:32:04 PDT -- d3fault created the file: Documents/minddump/2017/5/1495995924-MTJ784.txt
Philosophers and physicists both try to explain the world, but they take completely different approaches. Philosophers tackle the problem from a more "top down" perspective, physicists from a more "bottom up". Philosophers try to whip up succinct explainations using just their brain, whereas physicists go around measuring everything and trying to figure out the complex interplay of the various aspects of nature. Physicists and philosophers seek the same thing: truth/understanding. Philosophy factors in the constant (for now) stream of new information that physicists pump out, but the opposite isn't true: physicists don't give a flying fuck about what the philosophers have to say (unless they are themselves part-time philosophers). All that being said, I don't know which approach will "discover" the "truth" first.
2017-05-27 21:27:26 PDT -- d3fault modified the file: Projects/wasdf/src/lib/wasdfcalibrationconfigurationsettingsreaderwriter.cpp
2017-05-27 21:21:17 PDT -- d3fault modified the file: Projects/wasdf/design/mouse.action.serialization.stream.is.likely.to.become.desynced.and.cause.total.system.failure.here.is.a.solution.to.it.but.also.the.keyboard.could.desync.too.etc.txt
2017-05-27 21:12:25 PDT -- d3fault created the file: Projects/Ideas/3.button.mouse.driver.hack.or.implement.in.wasdf.ofc.txt
OT (but definitely could implement IN wasdf): I want a 3 button mouse, using my right ring finger for "left click and hold". I don't like that left click is the same button as the "click and hold" (I mean sure you can right click and hold, but click and holds are USUALLY with the left mouse (if you right click and hold a bunch, a 4 button mouse is 4 u)). I tend to accidentally click and hold my left mouse button when I'm only intending on clicking regularly. This could potentially have disasterous results, and programming around it is a waste of complexity (which us programmers try to minimize). So basically hack the fucking drivers so that left mouse is always "left mouse down" -> IMMEDIATELY AFTERWARDS "left mouse up". there should be no time in between down/up to process "mouse move" events. The driver or OS needs to be designed a specific way to be able to do that (but if I'm the one synthezising(splol) it, such as the case of wasdf, then I can easily arrange for that to always happen. If you hack (or provide) the usb mouse drivers (assuming you can even find such a mouse, but I'm willing to bet you can), then you can arrange for that to always happen (notice how I didn't say easily. it might be ez af it might be a bitch).
2017-05-26 06:30:22 PDT -- d3fault created the file: Documents/minddump/2017/5/1495772765-TJ1174.txt
I smile when I'm outside at night in the wilderness, for 2 reasons. 1 good reason and 1 shitty reason. I'll tell you the shitty reason first: 0) So strangers who I might happen to see will think I'm a nice person, which decreases my chances of getting accidentally shot. 1) So my teeth are seen from a distance by a particular kind of large feline (being feline gives them good night vision, so even though I can't see them they can see me). The teeth serve as a way of saying "I will [attempt to] defend myself" (I am an animal that WILL put up a fight). Hopefully this encourages them to pick an easier target.
2017-05-26 06:20:55 PDT -- d3fault modified the file: scripts/d3faults.superior.unattended-upgrades.sh
2017-05-26 05:50:48 PDT -- d3fault modified the file: Projects/wasdf/src/lib/wasdf.cpp
2017-05-25 23:45:17 PDT -- d3fault created the file: scripts/pushTextToAnyUsbFilesystemConnected.sh
#!/bin/bash exit 1 #I think this would work, but idk kinda scared to use it as a script. I'm 99% sure git won't push if the arg isn't a repository (or the right repository (or the right repository at the right state (doesn't overwrite without --force))). the thing of note is the asterisk in the push command cd ~/text #git push --all /media/user/*/textBare && echo "done pushing to usb filesystems" #^actually I think that's unsafe, a 3rd party thumb drive could provide untrusted code that could be somehow accidentally interpreted as bash code. I might be wrong, but I don't know that I'm not right (or something). Maybe globbing first and then using a for loop is best? it'd defintely give me better feedback "done pushing to /path/for/example/in/$i", but that's besides the point.
2017-05-25 23:36:00 CEST -- d3fault created the file: Projects/wasdf/design/mouse.action.serialization.stream.is.likely.to.become.desynced.and.cause.total.system.failure.here.is.a.solution.to.it.but.also.the.keyboard.could.desync.too.etc.txt
I need to realtime replay my serialized wasdf actions (the raw user input stream) on a different computer, then overlay the mouse--- scratch that, compare the sha512 of the screenshots of the computers (every GUI piece must be deterministic (and that's pretty ez tbh)). but anyways the original idea (involving mouse) was that I need to overlay the mouses of the separate computer(s) to make sure they don't get out of sync. like I mean the leonardo/micro "special" (real?) usb channel might get out of sync with my KeyboardAndMouse "dupe" channel that is getting sent over the Serial port. If the different channels of KeyboardAndMouse input [streams] get desynchronized and not corrected (and the differences would likely multiply as time grew), the entire serialized user input becomes useless. The serialization has failed (save for maybe keystrokes. I guess yea this is about mouse. but that's the thing, the mouse controls a TON of actions on the computer [that we want to be replayable FROM that user input stream].
2017-05-25 23:13:33 CEST -- d3fault created the file: Documents/minddump/2017/5/1495746402-TJ1090.txt
re: my comment on qt3d 2.0's new blog post "a mode (disabled by default) where smaller images for use in LOD are automatically generated (and cached) by Qt 3D rather than manually by the coder. there could be some compression ratio property to tune it or something. idk maybe you guys have this in the works" auto-tune would be best, detecting the optimal compression ratio of (least lossy image while knowing, in advance, that we have the cpu/gpu/etc power to compress the images at that compression ratio without there being any slowdown in the 3D scene below theHertzOfTheMonitor (or maybe 60 fps is a better number (it certainly gives us more room to work with), since some hertz are overkill high. obviously user configurable though (directly (in args/settings) and indirectly (through monitor))) I think I've already written a proof of concept of a "determine num of [arbitrary] actions per second that can be performed in N amount of time" that could be used in realtime for auto-tune/determining-of-that-compression-ratio-property
2017-05-25 22:26:16 CEST -- d3fault created the file: Documents/minddump/2017/5/1495743948-LhX814.txt
The speed of light [seems, therefore is] faster on a smaller scale, so life can be lived at a faster pace (or slower, but duh).
2017-05-25 22:24:37 CEST -- d3fault created the file: Documents/minddump/2017/5/1495743760-MTJ814.txt
There's no need for them to have even remotely close time scales. But I think there's an upper limit in that a [sub-or-parent]universe can't go INFINITE times faster (or slower maybe in the case of parent (or both or neither)). It has to use the same laws of physics as us but the concept of time is completely relative to the experiencer (was tempted to put observer).
2017-05-25 22:21:07 CEST -- d3fault created the file: Documents/minddump/2017/5/1495743524-MTJ808.txt
It shatters into a new universe where It shatters into it's own universe (existant(ent?) in ours, but we lack the ability to see inside black holes [that far?]. In that sub-universe, black holes can form and small pieces of magnet get sucked in and the cycle could [in theory] happen infinitely because you can always split a thing into 2. s/Magnet/Something
2017-05-25 22:17:09 CEST -- d3fault created the file: Documents/minddump/2017/5/1495743421-MTJ787.txt
What happens when you put (drop?) a magnet into a black hole?
2017-05-25 19:39:50 CEST -- d3fault modified the file: Projects/QuickDirtyStaticGitWeb/src/quickdirtystaticgitweb.cpp
2017-05-25 19:30:57 CEST -- d3fault created the file: Documents/minddump/dreams/2017/5/1495731533-MTJ802.txt
Dicran hooked me up with a job at the place he works, the #1 silicon manufacturer in the world. They had a "drive any car you want" policy just like Bob Odenkirk's previous employer. For some reason Dicran drove my car at/before/the-day-of my hiring and crashed it and for some reason wanted me to take the blame for it. Analyzing this more while awake it doesn't make much sense, why would he not just swap out his car for the same model as mine (the one he chose for me, which was like a big SUV that had oversized wheels and whose front and back wheels were close together. sorta resembled a monster truck but not really. also it was completely black)? And why was it a big deal that he crashed it? Surely the company understands that mistakes happen. Idk anyways onto something of more substance: at the job there was a lot of distrust. You'd have to fill out psychological questionaire/reports frequently (weekly, perhaps daily) and the company a had dozens of psychologists on it's payroll to analyize both the coders and even themselves. I witnessed that first day a coder get fired because he answered one of the quizzes wrong accidentally. It (the question he got wrong) had something to do with whether or not he'd want to to work from home and something to do with kids, maybe "if you had kids then would you want to work from home?". Since as you can see there are 2 parts to that question (sorta), he I think answered yes (or maybe the question was worded opposite and he answered no?) and fuck I honestly can't remember the details but he basically said what he didn't mean to say. Maybe he meant to say he doesn't have kids so he answered no but then what that was interpreted as was that he didn't want to work in-office. Yea I think that's about it, but fuck trying to figure out the proper wording of the question corresponds to that. So yea they fired his ass because wanting to work from home shows that he's not a "team player" (my wording now, not the wording used in the dream) or whatever. His explaination of what he meant didn't matter, he was fired. The female psychologist who came into the cube farm to do the firing received a look from me in reaction to this event. I obviously disapproved and thought her scum. Later the dream showed her talking (in group therapy) with the other shrinks about how she at first felt attracted to me, but then the look I gave her made her feel terrible. Bill Gates was the president/CEO/whatever of the company (lol), and I followed him around the hallways some to get shown around or whatever. But most of this part of the dream took part in that cube farm. The distrust stuff was a pretty constant theme in the dream, with Billy G repeatedly asking Dicran what he'd been doing last night because something didn't add up ("last night" was the night he crashed "my" car and lied about it). Eventually he had some hard piece of evidence that Dicran's report was at least partially false. Dicran finally confessed and there didn't seem to be any punishment (or I just didn't see it), maybe Dicran was too valuable? This obviously showed that I'd been lying too, and I walked over and shook Billy G's hand and said "sorry, lying on the first day is a terrible thing to do". He replied, "well at least you were just covering up for a friend", and I said in response to that "yea for sure" (didn't know what else to say). Now we were all at a baseball game. I said "I don't want to play" (my feelings about baseball are mixed: it's pretty fun but I fucking hated being forced to play it as a kid), and for some reason my saying that made Irvin want to play. He went and played 2nd base and did pretty good. Daniel played shortstop as usual. A tiny bit later I ended up out near (in?) left field and was watching back at the bleachers at all the Silicon Manufacturer employees doing a song and dance together. I scanned the group trying to find Dicran to see if he too was doing it. To my delight, he was. It was a pretty simple dance but it was still groovy as fuck: step left, step right, clap (repeat). Dicran looked happy and into it, they all did. I pondered about whether or not the extreme distrust somehow made them all closer to each other and allowed them to be themselves without having to (or more accurately, being able to) hide anything. Was it net positive? Oh teh noez, the baseball game got hacked! Some script kiddy in the basement below the bleachers flooded the baseball field. Us h4x0rz were on it, talk about right place at the right time. My solution was simple and non-tech: "we need a security guard right here" (sitting next to the laptop in the basement that had been comprimised). Now back up top: eh some underwater truck thing drove into the basement, it being submerged in the process, to start draining the baseball field. 2 unnamed employees of SM stood next ot the bleachers and looked away from the field towards a man standing on a small grassy hill who was fiddling with a tablet or smartphone. The 2 guessed (correctly) that he was the perp, but still couldn't go over there and look at his screen because that'd be a violation of his fuckin rights, man. I woke up not wanting that job, but for some reason while having the dream it didn't seem so bad.
2017-05-25 06:40:09 CEST -- d3fault modified the file: Projects/QuickDirtyStaticGitWeb/src/quickdirtystaticgitweb.h
2017-05-25 03:20:33 CEST -- d3fault created the file: Documents/minddump/2017/5/1495674878-MTJ836.txt
I made it my goal in life to live in a cabover camper and to have DDRaceNetwork (a Teeworlds mod) be my "baseline" in life (that game is so fun and relaxing... but still of course dumb like all games are). I'd get bored of it after some hours and could then go on to code stuff. Well I got the lifted 4x4 truck and the cabover camper and am at this very moment up in the California mountains... but I failed at reaching that goal (for now) because my $35 linux computer doesn't have proper 3D support... so DDNet runs at ~2 fps facepalm.jpg. On the other hand I'm coding my ass off for lack of better things to do (can't hike ALL day EVERY day (well could but... don't want to...)).
2017-05-25 03:13:49 CEST -- d3fault created the file: Documents/minddump/2017/5/1495674485-MTJ817.txt
0) Our forelobes are perhaps the biggest credit stealers of all time. I think more and more (or maybe just like the idea) that our subconsciences are really the ones driving our bodies. The thing is, in order for our subconscience to send commands to our body, the commands have to pass through our forelobe. So our forelobe sees the command/idea just before we put it to action, "agrees" that it's a good idea, thinks it's the one that came up with it in the first place, then puts it into action. I could go on to mention a wild theory that aleenz in another dimension ARE our subconscience and they're pissed as fuck that we keep stealing their credit... but I won't. 1) If you commit no acts of civil disobedience, you're implicitly stating that the world (or country) is perfect the way it is. Yes I know civil disobedience is not the "proper channel" to get issues addressed, but the proper channels are fucking broken as shit in this shitty ass country. Corruption is winning. Eh I could probably rant for a couple more pages on this subject but I'll just keep it short and sweet.
2017-05-25 03:07:41 CEST -- d3fault created the file: Pictures/shirts/sdlfjdlasfjdasjfklsdjfklsdjfklsdj.txt
eh these aren't shirts but are instead signs. 0) I was walkin around beaumont and saw a lot of "beware of dog" signs, some of em had a silhouette (sp wtf) of a dog barking. "beware of god" would be better, with a silhouette of jeebus sitting down on the ground leaning back against a building holding out a cup (asking for spare change ofc, but those words aren't on the sign). oh and he'd have a halo too 1) all over riverside county are signs with arrows pointing at the streets "the bus stops here". meh "the buck stops here". ok ok it's not that funny (but putting those stickers (just the word "buck" over "bus") would be a fun prank)
2017-05-24 21:37:23 CEST -- d3fault modified the file: Projects/wasdf/src/lib/wasdf.h
2017-05-24 04:27:37 CEST -- d3fault modified the file: Projects/wasdf/src/lib/wasdfcalibrationatrestdetector.cpp
2017-05-24 04:00:19 CEST -- d3fault modified the file: Projects/wasdf/src/lib/wasdfcalibrationatrestdetector.h
2017-05-24 03:21:13 CEST -- d3fault modified the file: Projects/wasdf/src/lib/wasdfcalibrator.cpp
2017-05-24 04:27:37 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrationatrestdetector.cpp
#include "wasdfcalibrationatrestdetector.h" #include <QHashIterator> #include <QMutableHashIterator> //TODOmb: like I'm pushing this functionality into it's own class, so too should I (probably/maybe, but also maybe not [yet] if it's too much work to refactor xD) push the "analog pin detection" and "normal use range detection" into their own classes. Additionally, all calibration related classes should go in a ./calibration subfolder. The WasdfCalibrator should simply hasA these 3 types of calibration 'mode' thingies (for lack of a better word) void WasdfCalibrationAtRestDetector::addAnalogPinPosition(int analogPinId, int newPinPosition) { m_CurrentAllAnalogPinPositions_ByAnalogPinId.value(analogPinId, SharedPointerToListOfIntAtRestValues(new QList<int /*sensor value*/>()))->append(newPinPosition); } void WasdfCalibrationAtRestDetector::weJustFinishedCalibratingThisAnalogPinId(Finger fingerWeJustFinishedCalibrating, int analogPinWeJustFinishedCalibrating) { //0) discard the positions for the analog pin id passed in (because we told the user to move it a bunch, so it wasn't "at rest" at all!) m_CurrentAllAnalogPinPositions_ByAnalogPinId.remove(analogPinWeJustFinishedCalibrating); //now discard all position data for fingers on the same hand <---- NVM. although we know the finger that was just calibrated, we have no idea (yet) what finger the rest of them are (ok that's only partially true. as we get nearer and nearer to the last finger we know more and more fingers. still, simpler to discard "same hand" values at the very end in finalize, when we know ALL fingers) //1) average all the remaining at rest positions gathered in the last 5 seconds QHashIterator<int /*pin number on arduino*/, SharedPointerToListOfIntAtRestValues> it(m_CurrentAllAnalogPinPositions_ByAnalogPinId); while(it.hasNext()) { it.next(); int average = calculateAverage(*(it.value().data())); m_AveragedAtRestValuesGatheredWhileCalibratingFingers_ByFinger.value(fingerWeJustFinishedCalibrating, SharedPointerToListOf_PinNumbersAndAtRestValues(new QList<PinNumberAndAtRestValue>()))->append(PinNumberAndAtRestValue(it.key(), average)); } //2) clear the 'current' lists for the next 5 seconds of calibration (assuming there will be more, but it doesn't matter if there isn't) m_CurrentAllAnalogPinPositions_ByAnalogPinId.clear(); } void WasdfCalibrationAtRestDetector::finalize(WasdfCalibrationConfiguration *out_Calibration) { //first discard all position data collected for fingers on the same hand //fuck, 'staggered' deletion of averages? fuck, my head hurts, what? like uhh when Finger6_RightIndex was being calibrated we delete the index 0 at rest average of the right hand, then Figner5_LeftIndex was being calibrated we delete the index 0 at rest average of the left hand, then Finger7_RightMiddle we delete index 1.. WAIT NO if we 'removed' index 0 (during RightIndex), then the new one we remove is going to be index 0 again!!! not 'staggered' after all. still my head hurts, typing this out certainly helps. so I use my ordered finger iterator I think. hmm I need to map the analog pins to the fingers first though, wait no that's already done in out_Calibration. wait no it IS staggered after all, since index 0 [now] points to an at rest value that we want to keep (one gathered while the opposite hand finger was being calibrated)! fuck, my head!!! still that just means a ++indexToDeleteOnRightHand and a ++indexToDeleteOnLeftHand, or something? //^hmmmm to make things easier for my head I could record which finger each set of "at rest" values corresponds to. Hmmmm QHash<Finger, QSharedPointer<QList> > atRestValues_ByFingerBeingCalibratedWhenTheyWereDetected ??? then I iterate that hash, map the analog pins to the fingers, determine if it's the same hand as in that QHash's key, drop that reading if it is, if it's opposite then add it to a newly built QHash<Finger, QSharedPointer<QList> >, then finally after that iteration of same-hand droppage, iterate the newly built hash simply to calculate the average rest value and THEN stuff it into out_Calibration QHashIterator<Finger /*finger that was being calibrated when we gathered these averages*/, SharedPointerToListOf_PinNumbersAndAtRestValues> it0(m_AveragedAtRestValuesGatheredWhileCalibratingFingers_ByFinger); QHash<Finger, SharedPointerToListOfIntAtRestValues> atRestValuesOfFingersWithSameHandFingersRemoved_ByFinger; while(it0.hasNext()) { it0.next(); SharedPointerToListOf_PinNumbersAndAtRestValues listOfPinNumbersAndSensorValuesGatheredWhileCalibratingTheFingerKEY = it0.value(); Q_FOREACH(const PinNumberAndAtRestValue &pinNumberAndAtRestValue, *(listOfPinNumbersAndSensorValuesGatheredWhileCalibratingTheFingerKEY.data())) { if(!out_Calibration->hasFingerWithAnalogPinId(pinNumberAndAtRestValue.PinNumber)) continue; //the pin number might not correspond to a finger, like when that analog pin was not used Finger mappedFinger = out_Calibration->getFingerByAnalogPinId(pinNumberAndAtRestValue.PinNumber); if(Wasdf::fingerIsLeftHand(it0.key()) != Wasdf::fingerIsLeftHand(mappedFinger)) { //mappedFinger is on the same hand as it0.key(), so we keep it's at rest value SharedPointerToListOfIntAtRestValues mappedFingersListOfAtRestValues = atRestValuesOfFingersWithSameHandFingersRemoved_ByFinger.value(mappedFinger, SharedPointerToListOfIntAtRestValues(new QList<int>())); mappedFingersListOfAtRestValues->append(pinNumberAndAtRestValue.AtRestValue); } //else: discard at rest values gathered on same hand as finger that was being calibrated at the time } } //get all the at rest readings for the fingers connected to analog pins we actually care about, then average those all together one last time, then stuff that final "at rest" value into the calibration QHashIterator<Finger, SharedPointerToListOfIntAtRestValues> it1(atRestValuesOfFingersWithSameHandFingersRemoved_ByFinger); while(it1.hasNext()) { it1.next(); WasdfCalibrationFingerConfiguration fingerConfiguration = out_Calibration->value(it1.key()); fingerConfiguration.AtRestPosition = calculateAverage(*(it1.value().data())); out_Calibration->insert(it1.key(), fingerConfiguration); } } int WasdfCalibrationAtRestDetector::calculateAverage(const QList<int> &numbersToAverageTogether) { qreal result = 0.0; Q_FOREACH(int currentNumber, numbersToAverageTogether) { result += currentNumber; } result /= static_cast<qreal>(numbersToAverageTogether.size()); return qRound(result); }
2017-05-24 04:00:19 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrationatrestdetector.h
#ifndef WASDFCALIBRATIONATRESTDETECTOR_H #define WASDFCALIBRATIONATRESTDETECTOR_H #include <QHash> #include <QList> #include <QSharedPointer> #include "wasdf.h" class WasdfCalibrationAtRestDetector { public: void addAnalogPinPosition(int analogPinId, int newPinPosition); void weJustFinishedCalibratingThisAnalogPinId(Finger fingerWeJustFinishedCalibrating, int analogPinWeJustFinishedCalibrating); void finalize(WasdfCalibrationConfiguration *out_Calibration); private: struct PinNumberAndAtRestValue { PinNumberAndAtRestValue(int pinNumber, int atRestValue) : PinNumber(pinNumber) , AtRestValue(atRestValue) { } int PinNumber; int AtRestValue; }; typedef QSharedPointer<QList<int/*at rest value*/> > SharedPointerToListOfIntAtRestValues; typedef QSharedPointer<QList<PinNumberAndAtRestValue> > SharedPointerToListOf_PinNumbersAndAtRestValues; int calculateAverage(const QList<int> &numbersToAverageTogether); QHash<int /*pin number on arduino*/, SharedPointerToListOfIntAtRestValues> m_CurrentAllAnalogPinPositions_ByAnalogPinId; QHash<Finger /*finger that was being calibrated when we gathered these averages*/, SharedPointerToListOf_PinNumbersAndAtRestValues> m_AveragedAtRestValuesGatheredWhileCalibratingFingers_ByFinger; }; #endif // WASDFCALIBRATIONATRESTDETECTOR_H
2017-05-24 01:40:02 CEST -- d3fault modified the file: Projects/wasdf/src/lib/wasdfcalibrator.h
2017-05-24 01:37:55 CEST -- d3fault created the file: Documents/minddump/2017/5/1495582511-TJ1363.txt
When you're russian, and I always find myself russian when I'm "on the clock", and employers tend to put pressure on their code monkeys because they want the most bang for their buck (they usually aren't aware of the "choose 2 of 3" thingy relating to code: good, fast, cheap)... err this sentence is hard to continue but anyways when I'm rushing I tend to NOT push separate pieces of functionality into their own class (like I should). It's only when I'm relaxed and coding at my own pace do I stop and think "hmm this isn't really related so I should make a class and hasA that class". When russian I tend to make giant monolithic classes that have assloads of special one-time-use member variables and methods and it's hard to decipher what's related to what. Fuck business-minded people.
2017-05-24 01:31:04 CEST -- d3fault modified the file: Projects/wasdf/src/wasdf.pri
2017-05-23 19:59:27 CEST -- d3fault modified the file: Documents/minddump/dreams/2017/5/1495474237-MTJ800.txt
2017-05-23 19:58:16 CEST -- d3fault created the file: Projects/Ideas/downhill.mountain.biking.on.foreign.trail.kicker.confidence.helper.gps.app.txt
2 part idea, the second part is the only idea to be considered an "idea/project/invention" (and it's probably patentworthy, but everything and their mom is these days if you're willing to bribe the USPTO $10k). a) I want to get a mountain bike for exercise/fun, and I've heard of (but haven't yet tried) these pedal-assist bikes that do ~50% of the pedaling for you. Since they require you to pedal as well (and they don't keep going when you stop (or crash xD)) and since they aren't doing a "majority" of the work, they aren't considered motorized vehicles and you can ride them anywhere you can ride a normal bike (which is a LOT more places than motor vehicles (regular electric bikes or gas motorcycles) are allowed to go... and much less licensing/permit/etc requirements too). Cool I'm fucking sold, especially since I could (in theory) charge them up with my solar panels (well the solar panels I plan to get, it'd probably take eons for my 15w panel to charge them up). The "idea" is rather simple: park my truck/camper at the bottom of a hill (such as the one I'm parked on right now: Thomas Mountain Road in Idyllwild), use pedal assist to go UP the hill. When the battery runs out, turn around and coast/jam/fly back down :-). I like downhill mountain biking and am a decent (but far from good/pro) bike rider, so this idea isn't for everyone. Exercising this way will strengthen you more in the "endurance" kind of way rather than the "FFFF YEAAA ROIDS I WANT MY MUSCLES TO BE MASSIVE" kind of way, since you are doing 50% less work but for twice as long. Additionally, you get to downhill mountain bike TWICE as far (on average) with the same amount of up-hill energy (excluding electricity, talking body energy only) expended. I'm indifferent to whether or not I get "endurance" or "beefy" exercise, it was just an observation. b) While riding uphill, I can observe/analyze kickers/jumps/bumps-that-if-you-go-fast-enough-over-you-get-air-off-of and, after analyzing the landing and making sure it's a safer kicker (this is key), put the gps coords of the kicker (and maybe it's difficulty or how fast I should take it or something along those lines) into my computer. On the way back down, my computer can tell me (audio preferably, I don't want to sacrifice visuals during downhill mountain biking) when a kicker is approaching and how fast to take it. Without such an app, you'd have to ride down the hill multiple times before you had each kicker memorized and could confidently/safely hit them. Another thing to complement the gps-coords/difficulty could be a side-view picture of the kicker and landing... because that way you'd be able to see/remember exactly what to expect and how to take the jump. That picture could substitute for the difficulty rating (but maybe not an "estimated speed" rating unless we take another picture of the approach and after-landing as well). Sure you don't want to look away from the road but a quick glance at a picture is worth a thousand words. Would also be nice to have a speedometer on the bike, but eyeballing your speed isn't so hard at such low speeds. This is kinda like what rallycar racers use their navigator for, but way better imo (why the fuck don't rallycar racers use a similar app? Hah now that I've mentioned it they can't patent that either, pigfuckers).
2017-05-23 19:38:53 CEST -- d3fault created the file: Documents/minddump/2017/5/1495560525-LhX788.txt
Dehydrated/powdered/instant milk is superior to regular wet milk for 3 very good reasons: 1) Doesn't go bad nearly as quickly. Stays good for maybe half a year to a year. Probably longer if you refrigerate it. I hate FORCING myself to drink milk just because I don't want it to go bad, it ruins the milk experience (and I, like my brother and Caydon, have a milk fetish (with my mom to thank -- she used to force us(me?) to drink milk lololol)). 2) You can choose how creamy/thick you want it to be. I'm not talking fat content, which is the only thing you can choose when it comes to regular/wet milk. With powdered milk you can keep pouring and pouring (keeping the amount of water the same) until you [probably (haven't tried it)] have something so thick it resembles a milkshake. Or if you want it watered down, you have the option (actually nvm you could water down regular/wet milk too). There are instructions on the powdered milk box for how much to use. I read them once but every time since I just fucking eyeball it and I've never been disappointed. Simple trial and error (adjusting from previous days) gives me the optimal (preference) creaminess. 3) Fortification. Yea maybe some regular/wet milks fortify too, but I'm pretty sure most don't (I might be wrong). I'm a huge fan of multivitamins because I know I'm not the best eater in the world; I need all the help I can get. Extra vitamins/nutrients in my milk? Yes please. On that note (but slightly OT) I've heard people declare (while ranting) that "all man-made chemicals are bad for you". I chuckled internally and didn't argue with them, fuck it le them have their rant to blow off steam. There's no fucking difference (if done properly): a chemical is a chemical. If there is a difference, it (the synthesis/extraction/whatever) wasn't done properly and we aren't takling about the same 2 chemicals.
2017-05-23 19:28:29 CEST -- d3fault created the file: Documents/minddump/dreams/2017/5/1495559788-MTJ788.txt
Was at the old batting cages in riverside. I'm not sure where it is exactly or even what it's called. There was an arcade there too (on the right when you enter the door). The arcade wasn't part of the dream though. I think I went there after hours, or thought I was there after hours until towards the end of the dream some baseball players started showing up using batting cages. Most of the dream (towards beginning) took place inside the building though. It was a family operated business and that building doubled as their house (I don't think this is the case IRL). I remember talking to the wife/mom and their daughter, but I don't recall ever seeing the husband/dad in the dream. I think the mom gave me a haircut. I talked to the little girl some but the only thing I remember asking her was her age (7). I might have my ordering wrong but at some point I was sitting on their porch and there was a big glass (or hard clear plastic) box sitting on a table with a slit in the top. It was filled a good ways with cold hard cash. Towards the top of the slit was a $50 bill and I schemed to return (with a mask covering my face, because they had cameras) sometime at night maybe and to use a skinny stick with pinchers on the end to grab that $50 (and probably more). I'm not sure I committed to that plan because there was definitely a moral dilemna going on. It's true I am tempted with theft all the fucking time IRL (but I'd probably stick to electronic theft, since I'd be way better at it), but you should be glad to hear that the "good steven" is winning that fight: I haven't stolen anything (that I didn't think was abandoned) in many years, so many in fact that I consider myself a kid back then (even if I was over 18 at the time). Well anyways not much more to the dream than that except I considered asking them if they'd give me a tour of "behind the batting cages" (you know, where you always see employees walking around). I said, or thought about saying (in dreams, when you "consider" doing something, the thought of doing it tends to takes over and that consideration becomes the dream itself. neat), "it may not be interesting to you since you see it every day, but to someone like me it's a mystery" (or something along those lines. I didn't use the word mystery but I am now). I also thought about asking them if they hated it when people, such as myself (but whether I'd admit that depended on their answer), threw balls laying around back through the holes they came out of.
2017-05-23 20:03:39 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrationconfigurationsettingsreaderwriter.cpp
#include "wasdfcalibrationconfigurationsettingsreaderwriter.h" #include <QHashIterator> #define WasdfCalibrationConfigurationSettingsReaderWriter_FINGERS_ARRAY "fingers" #define WasdfCalibrationConfigurationSettingsReaderWriter_FINGER_KEY "finger" #define WasdfCalibrationConfigurationSettingsReaderWriter_KEY_ANALOG_PIN_ON_ARDUINO "analogPin" #define WasdfCalibrationConfigurationSettingsReaderWriter_KEY_MINVALUE "minValue" #define WasdfCalibrationConfigurationSettingsReaderWriter_KEY_MAXVALUE "maxValue" //TODOreq: "profiles" void WasdfCalibrationConfigurationSettingsReaderWriter::writeToSettings(QSettings &settings, const WasdfCalibrationConfiguration &wasdfCalibrationConfiguration) { settings.beginWriteArray(WasdfCalibrationConfigurationSettingsReaderWriter_FINGERS_ARRAY); int i = 0; QHashIterator<Finger, WasdfCalibrationFingerConfiguration> it(wasdfCalibrationConfiguration); while(it.hasNext()) { settings.setArrayIndex(i); it.next(); settings.setValue(WasdfCalibrationConfigurationSettingsReaderWriter_FINGER_KEY, /*fingerEnumToHumanReadableString*/static_cast<int>(it.key())); //I thought (while laying in bed last night) about maybe using this int-converted value in place of "i" for the settings array, but then I'd have to convert the hash to a map before inserting (not hard at all!) and idk it just might lead to problems if for example a "FingerNegative1_InvalidFinger" ever gets introduced. it's also why I changed various static_casts to int instead of uint. you never know what design changes you'll make in the future settings.setValue(WasdfCalibrationConfigurationSettingsReaderWriter_KEY_ANALOG_PIN_ON_ARDUINO, it.value().AnalogPinIdOnArduino); settings.setValue(WasdfCalibrationConfigurationSettingsReaderWriter_KEY_MINVALUE, it.value().MinValue); settings.setValue(WasdfCalibrationConfigurationSettingsReaderWriter_KEY_MAXVALUE, it.value().MaxValue); settings.endGroup(); ++i; } settings.endArray(); } void WasdfCalibrationConfigurationSettingsReaderWriter::readFromSettings(QSettings &settings, WasdfCalibrationConfiguration *out_wasdfCalibrationConfiguration) //TO DOnereq: I think settings passed in should be a _const_ reference, but my compiler is saying that settings.beginReadArray (keyword _READ_) discards const qualifiers yada yada. I should see if that's still the case in newer versions of Qt, and file a bug if it is (but really this is not very important). hmm maybe it can't be const because settings has to do cross-process synchronization. yea that's probably it xD { int numFingers = settings.beginReadArray(WasdfCalibrationConfigurationSettingsReaderWriter_FINGERS_ARRAY); //TODOmb: verify i == 10 ... however I like this class being dumb/static, so that error checking should be the responsibility of the caller for(int i = 0; i < numFingers; ++i) { settings.setArrayIndex(i); Finger finger = static_cast<Finger>(settings.value(WasdfCalibrationConfigurationSettingsReaderWriter_FINGER_KEY).toInt(/*TODOmb: &convertOk error checking that converted to int was successful. also applies to the next few lines of code*/)); WasdfCalibrationFingerConfiguration fingerConfigutation; fingerConfigutation.AnalogPinIdOnArduino = settings.value(WasdfCalibrationConfigurationSettingsReaderWriter_KEY_ANALOG_PIN_ON_ARDUINO).toInt(); fingerConfigutation.MinValue = settings.value(WasdfCalibrationConfigurationSettingsReaderWriter_KEY_MINVALUE).toInt(); fingerConfigutation.MaxValue = settings.value(WasdfCalibrationConfigurationSettingsReaderWriter_KEY_MAXVALUE).toInt(); *out_wasdfCalibrationConfiguration->insert(finger, fingerConfigutation); } settings.endArray(); }
2017-05-23 00:05:22 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrationconfigurationsettingsreaderwriter.h
#ifndef WASDFCALIBRATIONCONFIGURATIONSETTINGSREADERWRITER_H #define WASDFCALIBRATIONCONFIGURATIONSETTINGSREADERWRITER_H #include <QSettings> #include "wasdf.h" struct WasdfCalibrationConfigurationSettingsReaderWriter { static void writeToSettings(QSettings &settings, const WasdfCalibrationConfiguration &wasdfCalibrationConfiguration); static void readFromSettings(QSettings &settings, WasdfCalibrationConfiguration *out_wasdfCalibrationConfiguration); }; #endif // WASDFCALIBRATIONCONFIGURATIONSETTINGSREADERWRITER_H
2017-05-22 21:07:34 CEST -- d3fault created the file: Projects/wasdf/src/lib/fingeriteratororderedbymostusedfingers.cpp
#include "fingeriteratororderedbymostusedfingers.h" //right-handed master race bool FingerIteratorOrderedByMostUsedFingers::hasNext() { if(m_InitialState) return true; if(m_Finger == Finger::LeftPinky_Finger0) //ignore the "0" in this, it really is our "least used finger" (therefore "last") in this context. but from "left to right" it is the "first"/0th, kek { return false; } return true; } Finger FingerIteratorOrderedByMostUsedFingers::next() { if(m_InitialState) { m_InitialState = false; m_Finger = Finger::RightIndex_Finger6; return m_Finger; } m_Finger = privateNextFinger(); return m_Finger; } void FingerIteratorOrderedByMostUsedFingers::reset() //I had this called "toFront" at first, but wouldn't that mean I'm pointing to RightIndexFinger? I guess not (that's not how Qt iterators work) but the wording still kinda implies yes... so reset is clearer { m_InitialState = true; } Finger FingerIteratorOrderedByMostUsedFingers::privateNextFinger() { switch(m_Finger) { case Finger::Finger6_RightIndex: return Finger::LeftIndex_Finger3; break; case Finger::Finger3_LeftIndex: return Finger::Finger7_RightMiddle; break; case Finger::Finger7_RightMiddle: return Finger::LeftMiddle_Finger2; break; case Finger::Finger2_LeftMiddle: return Finger::Finger5_RightThumb; break; case Finger::Finger5_RightThumb: return Finger::Finger4_LeftThumb; break; case Finger::Finger4_LeftThumb: return Finger::Finger8_RightRing; break; case Finger::Finger8_RightRing: return Finger::Finger1_LeftRing; break; case Finger::Finger1_LeftRing: return Finger::Finger9_RightPinky; break; case Finger::Finger9_RightPinky: return Finger::Finger0_LeftPinky; break; case Finger::Finger0_LeftPinky: return Finger::Finger6_RightIndex; //should never get here (unless the user of this class forgets to check hasNext() themselves), but it's best to wrap around to beginning in case they use this class wrong break; } return Finger::RightIndex_Finger6; //should (will) never get here }
2017-05-22 21:07:29 CEST -- d3fault created the file: Projects/wasdf/src/lib/fingeriteratororderedbymostusedfingers.h
#ifndef FINGERITERATORORDEREDBYMOSTUSEDFINGERS_H #define FINGERITERATORORDEREDBYMOSTUSEDFINGERS_H #include "wasdf.h" class FingerIteratorOrderedByMostUsedFingers { public: bool hasNext(); Finger next(); void reset(); private: Finger privateNextFinger(); bool m_InitialState = true; Finger m_Finger; // = Finger::Finger6_RightIndex; }; #endif // FINGERITERATORORDEREDBYMOSTUSEDFINGERS_H
2017-05-22 20:14:06 CEST -- d3fault created the file: Documents/minddump/2017/5/1495476626-LhX831.txt
re: maintaining a monolithic git repo encapsulating all my git submodules, as a failsafe backup strategy, but avoiding dupe code I haven't thought this through very much but here goes nothing: what if for my monolithic (backup) repo I use a symlink to projects I want to use (as libs (submodules)), and somehow intelligently swap them out for traditional submodules for the proper/git-submodule repos. I'm pretty sure git handles symlinks the right way (by not ENTERING the symlink), so eh there might be something here. Maybe my monolithic commit-helper app could parse the git config of each submodule and then know which subfolders are git repos (and to treat them like symlinks instead). You know in all honesty while this does sound possible (esp if using libgit), it sounds way the fuck too complex/confusing so fuck this shit
2017-05-22 20:08:14 CEST -- d3fault created the file: Documents/minddump/2017/5/1495475769-MTJ831.txt
It's 2017 and I'm still using a monolithic git repo? bah. w2b submodules (but sure as shit not about to manage them manually). Even though I know they're superior and I know want to switch to them, there's still a fear of using them: what if I (or my code) forgets to commit/push some deeply nested submodule? By now you all know how I feel about data loss (FFFFFFF). Maybe fuck it I'll just ALWAYS have a monolithic repo, even when I'm simultaneously using submodules! The monolithic repo would serve as a backup in case I manage submodules wrong. Ehh thinking about that a little more it's obvious that there would get introduced TONS of dupe code (unless I grew and grew my root .gitignore file (or maybe it's better to then have .gitignore files at lower levels (but then the submodule would get ignored KEK)), since the typical git submodule workflow is to add whatever libs you're using to your repo AS a submodule (whereas in my monolithic repo strategy I simply use a relative path ../../../GloballySharedFiles/library.pri). Well anyways back on track: I've got so many smaller projects I do really want to work on, but (before just a few days ago) I was torn trying to decide which ones to give my love to. Eventually I had my eureka moment: fuck code I want to make music for a while damnit. So now I'm giving wasdf 100% of my attention as you could probably tell by my past few commits. I'm not russian, but by giving it 100% of my attention I could probably have a decently working musical instrument within the next few weeks. I'm completely backburnering the whole integration with timeline shit (recording the PRE-SYNTH state of fingers in a timeline manner). I know I know this means I've wasted like 5+ years of the prime time of my life, but as you get older your standards of living drop significantly. Fuck it. A part of me also thinkis that sliding some timeline code into it will be trivial once I have it up and running (and trying to design it with timeline already there leads to feature creep and halts development entirely, as I've seen happen with fucking hundreds of my projects). I'm fine with analog (mic recording of the post-synth-and-even-post-SPEAKERS (so lossy as FUCK)) recordings for now, I really just want to make some fucking music. If only I had this mentality when I first came up with wasdf oh so many years ago (easily 5+, but I can't even remember tbh). Fuck it life doesn't work that way (I also wish I'd bought a cabover camper the moment I turned 18 heh).
2017-05-23 19:59:27 CEST -- d3fault created the file: Documents/minddump/dreams/2017/5/1495474237-MTJ800.txt
0) Tom 1) Clayton 0) Had a dream where my non-HS friend Tom got got. His death was similar to that one dream I had with the underwater music vest. We were outdoors on the streets. I kinda felt like I was just an observer in the dream, flying/floating around following the action, but Tom spoke to me directly towards the (his) end. There was some confrontation between him and some assholes. They made him surrender his gun with the threat of violence. He complied and tossed it onto the ground. Immediately one of them shouted "TARGET!!!" and they all started chasing him. He was less of a target (though obviously still being fucked with) while he held the gun (in his jacket or wherever), but once he dropped it he became more of a sitting (well, soon to be running) duck. He ran his ass off. He ran like a skinny person (sup) runs; I doubt the actual Tom could run this fast xD. It didn't matter though, he only made it a few hundred feet before one of them intercepted his path and incapacitated him by shooting his back and legs. I as the observer caught up to this action and witnessed one of them give him the money shot right to his eye. The assholes ran away and Tom started expressing his pain. At first it was just like "ouch, ouch, my eye" kinda shit but then moved onto "I can't see" and good ole "sheer terror" (-Sphere) kind of shit. His arms still flailed around while he tried to make sense of of what was going on (more like ACCEPT his imminent death). "I can't feel my legs"... as his hands were clearly groping his legs. Eventually he started crying (not the tear kind) and whining like a little bitch, exactly how I and most people would in that same situation. In his whining state he said "Steven, don't make the same mistake as I did". I'm pretty sure he meant dropping his gun, but a part of me wonders if simply allowing himself to be confronted by the assholes in the first place was his actual mistake. "Man is weakest by himself" (-Pale Rider). They are probably both mistakes, but idk which one he (or my subconscience) is referring to. Perhaps my subconscience intentionally made it ambiguoius to get me to think about it harder (it's working!). 1) Was I think the last day of school in 12th grade or at least the last stretch of school weeks. Miss Clayton (my 6th grade teacher) was our teacher and my classmates from K-1 and 5-8 (I went to a different school from 2-4) were there. I came to class hours late but the teacher didn't seem to really care too much. I knew better than to ask dumb questions at that point to get myself caught up: if I'm lost on what she's talking about, it's my own fault. It was perhaps that I didn't ask those kinds of "catch me up" questions that the teacher didn't mind (too much) that I was late. An idiot would come late and expect to be caught up. Still I did some of the classwork wrong because of it. After a while I put the pieces together when I heard the teacher re-state (perhaps for my benefit) that some assignment/work/website-thingo had been 302 moved PERMANENTLY (emphasis hers). I had been still using the old link I guess? I don't remember actually viewing a website though lol, but I do remember plugging something into an extension cable that went right across the teacher's front walking area... and I also remember trying to keep that cable flat/etc so she wouldn't trip over it. Turned out I didn't need the extension cable though if I'd had known the assignment was changed. She let me do the wrong thing for a little bit of time because after all it was my own fault.
2017-05-21 22:02:11 CEST -- d3fault modified the file: Projects/wasdf/src/wasdf-cli.pro
2017-05-24 22:21:33 CEST -- d3fault created the file: Projects/wasdf/assets/ArduinoSketches/ArduinoWriteChangesOnAnalogPinsToSerial/ArduinoWriteChangesOnAnalogPinsToSerial.ino
//rewriting the first version of this instead of just removing calibration because I also want to try to not to use pp defines/macros. pure C++ is cleaner and easier to read/modify. aside from that it's just a functionally equivalent rewrite (with the calibration stripped out since that's going to be done on the PC side) #if (NUM_ANALOG_INPUTS < 10) #error "Your board does not support at least 10 analog inputs" //TODOmb: fail gracefully. but don't simply uncomment this, otherwise we will probably have a memory access violation in this code. namely when we try to pull out the "old" sensor value of finger9, but we only allocated (on the stack) an array of size NUM_ANALOG_INPUTS to hold our old sensor values #endif static const int NUM_HANDS = 2; static const int NUM_FINGERS_PER_HAND = 5; static const int HALF_THRESHOLD_FOR_NOTIFYING_OF_CHANGE = 2; //TODOoptional: this could be determined during 'calibration' (so it'd be received from PC over serial). example instructions to uesr for determining it: "move your right index finger as little as possible until you see on screen that it's registered" or some such (haven't thought this through very much, maybe it's dumb idea) //TODOmb: when in calibrating mode maybe I should blink pin 13 rapidly, and when normal mode starts I should do 3 long pulses and then disable it (because leaving it on is dumb) bool newSensorValueHasChangedEnoughThatWeWantToReportIt(int oldSensorValue, int newSensorValue) { /*if(NewSensorValue == OldSensorValue) return false; return true;*/ if(newSensorValue < (oldSensorValue-HALF_THRESHOLD_FOR_NOTIFYING_OF_CHANGE)) return true; if(newSensorValue > (oldSensorValue+HALF_THRESHOLD_FOR_NOTIFYING_OF_CHANGE)) return true; return false; } class Finger_aka_AnalogPin { public: explicit Finger_aka_AnalogPin() : NewSensorValue(0) , OldSensorValue(0) { } void setStringAndIntPinIds(const char *stringPinId, int intPinId) { StringPinId = stringPinId; IntPinId = intPinId; } void reportMovementOverSerialPort() { NewSensorValue = analogRead(IntPinId); if(newSensorValueHasChangedEnoughThatWeWantToReportIt(OldSensorValue, NewSensorValue)) { Serial.print(StringPinId); Serial.print(":"); Serial.println(NewSensorValue); OldSensorValue = NewSensorValue; } } ~Finger_aka_AnalogPin() { } const char *StringPinId; int IntPinId; int NewSensorValue; int OldSensorValue; private: explicit Finger_aka_AnalogPin(const Finger_aka_AnalogPin &other) { } //delete }; struct Hand { void setupHand(bool leftTrue_rightFalse) { //TODOreq: the arduino micro doesn't use analog pins 0-9 (note that finger 9 below maps to pin A11), so the following mappings are arduino micro specific. there should obviously be some way to use this code with other boards of course (even a mapping 'file' is better than hardcoding it here). the BEST solution is to, before/during calibration, 'probe' every analog port to see if it's wired, and then to have the user tell us which finger that pin corresponds to.. then to yea save it in some ~/.config 'profile' thingo. for now I'm fine with hardcoding the pin mappings since my target is to get range-of-fingers realtime-with-feedback calibration working [first]. I wonder what happens when you read an analog pin that has nothing attached... it returns 0. in any case and whatever value it is, it shouldn't "move" (I hope) //TODOreq:^I also need to change the MusicFingers serial READ code (runs on PC) to use 0-9 and not the whacky micro-specific mapping like in the previous version of this code //TODOreq: this obviously needs to be refactored to use the calibration data received from the PC if(leftTrue_rightFalse) { //left hand Fingers[0].setStringAndIntPinIds("0", A0); Fingers[1].setStringAndIntPinIds("1", A1); Fingers[2].setStringAndIntPinIds("2", A2); Fingers[3].setStringAndIntPinIds("3", A3); Fingers[4].setStringAndIntPinIds("4", A4); } else { //right hand Fingers[0].setStringAndIntPinIds("5", A5); Fingers[1].setStringAndIntPinIds("6", A8); Fingers[2].setStringAndIntPinIds("7", A9); Fingers[3].setStringAndIntPinIds("8", A10); Fingers[4].setStringAndIntPinIds("9", A11); } } void reportFingerMovementOverSerialPort() { for(int i = 0; i < NUM_FINGERS_PER_HAND; ++i) { Fingers[i].reportMovementOverSerialPort(); } } Finger_aka_AnalogPin Fingers[NUM_FINGERS_PER_HAND]; }; struct Hands //eh hands class should have just contained 10 fingers (instead of 2 hands each containing 5 fingers), but not about to un-code it xD { explicit Hands() { hands[0].setupHand(true); hands[1].setupHand(false); } void reportFingerMovementOverSerialPort() { for(int i = 0; i < NUM_HANDS; ++i) { hands[i].reportFingerMovementOverSerialPort(); } } Hand hands[NUM_HANDS]; }; struct Mode { enum ModeEnum //TODOreq: I forget how to properly set up 'flags' that can be combined, this might be wrong (also calibrating can never be used with any other modes, but eh) { DoNothingMode = 0x000 , Calibrating = 0x001 , Sending10FingerMovementsMode = 0x010 , KeyboardAndMouseMode = 0x100 }; }; //Globals int CalibrationDataOldSensorValues[NUM_ANALOG_INPUTS]; String inputCommandString; Mode::ModeEnum CurrentMode; Hands hands; void setup() { Serial.begin(38400 /*, SERIAL_8O2 TODOreq: I want to try out "Odd" (that's an oh not a zero in between 8 and 2) parity and 2 stop bits to see if it improves reliability, but I keep getting an error that begin() only takes one argument wtf? maybe I need to upgrade? but it doesn't even look like debian stretch bumped the version at all (except a small patch). the define SERIAL_8O2 does in fact exist, so wtf?*/); for(int i = 0; i < NUM_ANALOG_INPUTS; ++i) CalibrationDataOldSensorValues[i] = 0; CurrentMode = Mode::DoNothingMode; inputCommandString.reserve(1024); //TODOreq: calculate the max string length and reserve that much (or maybe a little more to be on the safe side). it can be determined because the values only take up so many characters. only thing is maybe the arduino mega 2560x1000 might have 999999999999 analog pins xDDDD, ya know what I mean?? while(!Serial) ; //wait for serial port to connect. Needed for Leonardo/Micro only. I intentionally put the String::reserve command (and other cmds) in between this and Serial.begin() in case the connect happens asynchronously (idfk tbh, but it might), in which case I may have saved an entire millisecond!!! } void readAndReportChangesToAnalogPinOverSerial(int pinId, int indexIntoCalibrationDataOldSensorValues) { int oldSensorValue = CalibrationDataOldSensorValues[indexIntoCalibrationDataOldSensorValues]; int newSensorValue = analogRead(pinId); if(newSensorValueHasChangedEnoughThatWeWantToReportIt(oldSensorValue, newSensorValue)) { Serial.print(pinId); Serial.print(":"); Serial.println(newSensorValue); CalibrationDataOldSensorValues[indexIntoCalibrationDataOldSensorValues] = newSensorValue; } } void calibrationLoop() { for(int j = 0, i = A0; j < NUM_ANALOG_INPUTS; ++j, ++i) { readAndReportChangesToAnalogPinOverSerial(i, j); } } void processInputCommandString() { if(inputCommandString == "calibrate") { CurrentMode = Mode::Calibrating; } else if(inputCommandString.startsWith("startReportingThesePinsExcludingTheirAtRestRanges:")) { //TODOreq: //where the fuck is my String.split!?!? aww come pls don't make me use indexOf :( //*cough* json *cough* } else { //TODOreq: blink pin 13 rapidly to indicate an error. longer term should request the command is re-sent. note: even if the checksum succeeds we still might get an invalid command (checksums aren't perfect), we we'd STILL want to request the command is re-sent. if however 50 invalid commands are received IN A ROW, then we would want to go into blink-13-error-mode as that indicates a bug } } void loop() { while(Serial.available()) { char inChar = (char)Serial.read(); if(inChar == '\n') { processInputCommandString(); inputCommandString = ""; } else inputCommandString += inChar; } switch(CurrentMode) //TODOreq: this switch case doesn't support simultaneous 10-fingers and keyboardMouse modes { case Mode::Sending10FingerMovementsMode: hands.reportFingerMovementOverSerialPort(); //tell, don't ask ;-) break; case Mode::KeyboardAndMouseMode: //TODOreq break; case Mode::Calibrating: calibrationLoop(); break; case Mode::DoNothingMode: delay(50); //mb this saves battery? w/e lol break; } delay(2); //TODOreq: this might fuck up MOUSE MOVEMENT, everything else should be fine with it tho }
2017-05-21 21:31:21 CEST -- d3fault modified the file: Projects/wasdf/src/cli/main.cpp
2017-05-21 21:22:54 CEST -- d3fault created the file: Projects/wasdf/src/cli/wasdfcli.h
#ifndef WASDFCLI_H #define WASDFCLI_H #include <QObject> #include <QTextStream> class WasdfCli : public QObject { Q_OBJECT public: explicit WasdfCli(QObject *parent = 0); private: QTextStream m_StdErr; QTextStream m_StdOut; private slots: void handleE(const QString &msg); void handleO(const QString &msg); }; #endif // WASDFCLI_H
2017-05-21 21:22:50 CEST -- d3fault created the file: Projects/wasdf/src/cli/wasdfcli.cpp
#include "wasdfcli.h" #include <QCoreApplication> #include "wasdf.h" WasdfCli::WasdfCli(QObject *parent) : QObject(parent) , m_StdErr(stderr) , m_StdOut(stdout) { Wasdf *wasdf = new Wasdf(this); connect(wasdf, &Wasdf::e, this, &WasdfCli::handleE); connect(wasdf, &Wasdf::o, this, &WasdfCli::handleO); connect(wasdf, &Wasdf::wasdfFinished, qApp, QCoreApplication::quit); wasdf->startWasdf(); } void WasdfCli::handleE(const QString &msg) { m_StdErr << msg << endl; } void WasdfCli::handleO(const QString &msg) { m_StdOut << msg << endl; }
2017-05-21 21:22:39 CEST -- d3fault created the file: Projects/wasdf/assets/ArduinoSketches/ArduinoWriteChangesOnAnalogPinsToSerial/Makefile
BOARD_TAG = micro ARDUINO_LIBS = include /usr/share/arduino/Arduino.mk
2017-05-21 21:22:24 CEST -- d3fault created the file: Projects/MusicFingers/assets/ArduinoSketches/ArduinoWriteChangesOnAnalogPinsToSerial_WithCalibration/ArduinoWriteChangesOnAnalogPinsToSerial_WithCalibration.ino
int sensorValue = 0; #define MUSIC_FINGERS_CALIBRATION_MAX 127 //TODOreq: this should be 1023. The value should be mapped to 0-127 only JUST before being sent to stk-demo's stdin (MAYBE a tiny bit earlier, so we 'know' what stk-demo currently has as a value... but definitely not here on the arduino). I think, though, that calibration has to be moved off of the Arduino in order for that to happen (which requires a more robust serial protocol (so fuck that for now. KISS)) #define MUSIC_FINGRERS_ANALOG_PIN_VAR(pin) analogInPin_##pin #define MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin) pin##_newSensorValue #define MUSIC_FINGERS_OLD_SENSOR_VALUE_VAR(pin) pin##_oldSensorValue #define MUSIC_FINGERS_MIN_SENSOR_VALUE_VAR(pin) pin##_minSensorValue #define MUSIC_FINGERS_MAX_SENSOR_VALUE_VAR(pin) pin##_maxSensorValue #define MUSIC_FINGER_GLOBALS(pin) \ const int MUSIC_FINGRERS_ANALOG_PIN_VAR(pin) = pin; \ int MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin) = 0; \ int MUSIC_FINGERS_OLD_SENSOR_VALUE_VAR(pin) = 0; \ int MUSIC_FINGERS_MIN_SENSOR_VALUE_VAR(pin) = 1023; \ int MUSIC_FINGERS_MAX_SENSOR_VALUE_VAR(pin) = 0; /* EX: int analogPin_A0 = 0; int A0_newSensorValue = 0; int A0_oldSensorValue = 0; int A0_minSensorValue = 1023; int A0_maxSensorValue = 0; */ MUSIC_FINGER_GLOBALS(A0) MUSIC_FINGER_GLOBALS(A1) MUSIC_FINGER_GLOBALS(A2) MUSIC_FINGER_GLOBALS(A3) MUSIC_FINGER_GLOBALS(A4) MUSIC_FINGER_GLOBALS(A5) MUSIC_FINGER_GLOBALS(A8) MUSIC_FINGER_GLOBALS(A9) MUSIC_FINGER_GLOBALS(A10) MUSIC_FINGER_GLOBALS(A11) #define MUSIC_FINGERS_CALIBRATE(pin) \ sensorValue = analogRead(pin); \ if(sensorValue > MUSIC_FINGERS_MAX_SENSOR_VALUE_VAR(pin)) \ { \ MUSIC_FINGERS_MAX_SENSOR_VALUE_VAR(pin) = sensorValue; \ } \ if(sensorValue < MUSIC_FINGERS_MIN_SENSOR_VALUE_VAR(pin)) \ { \ MUSIC_FINGERS_MIN_SENSOR_VALUE_VAR(pin) = sensorValue; \ } #define MUSIC_FINGERS_MAIN_LOOP(pinQuoted, pin) \ MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin) = analogRead(MUSIC_FINGRERS_ANALOG_PIN_VAR(pin)); \ if(MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin) < (MUSIC_FINGERS_OLD_SENSOR_VALUE_VAR(pin)-halfThresholdForNotifyingOfChange) || MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin) > (MUSIC_FINGERS_OLD_SENSOR_VALUE_VAR(pin)+halfThresholdForNotifyingOfChange)) \ { \ Serial.print(pinQuoted); \ Serial.print(":"); \ int sensorValueMappedAkaCalibrated = map(MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin), MUSIC_FINGERS_MIN_SENSOR_VALUE_VAR(pin), MUSIC_FINGERS_MAX_SENSOR_VALUE_VAR(pin), 0, MUSIC_FINGERS_CALIBRATION_MAX); /* 0-127 corresponds to the typical synthesis toolkit min/max ranges it accepts for the frequency on stdin....*/ \ sensorValueMappedAkaCalibrated = constrain(sensorValueMappedAkaCalibrated, 0, MUSIC_FINGERS_CALIBRATION_MAX); \ Serial.println(sensorValueMappedAkaCalibrated); /*TODOoptimization: pretty sure i don't need newlines, but I can't be fucked atm. edit: newlines cost just as much as any other delimiter, so what gives? i think now that i have a colon-separated-protocol, this optimization can no longer happen*/ \ MUSIC_FINGERS_OLD_SENSOR_VALUE_VAR(pin) = MUSIC_FINGERS_NEW_SENSOR_VALUE_VAR(pin); \ } int halfThresholdForNotifyingOfChange = 2; //plus OR minus, hence 'half' void setup() { Serial.begin(9600); //BEGIN Calibrate pinMode(13, OUTPUT); digitalWrite(13, HIGH); while(millis() < 5000) { MUSIC_FINGERS_CALIBRATE(A0) MUSIC_FINGERS_CALIBRATE(A1) MUSIC_FINGERS_CALIBRATE(A2) MUSIC_FINGERS_CALIBRATE(A3) MUSIC_FINGERS_CALIBRATE(A4) MUSIC_FINGERS_CALIBRATE(A5) MUSIC_FINGERS_CALIBRATE(A8) MUSIC_FINGERS_CALIBRATE(A9) MUSIC_FINGERS_CALIBRATE(A10) MUSIC_FINGERS_CALIBRATE(A11) } digitalWrite(13, LOW); //END Calibrate } void loop() { MUSIC_FINGERS_MAIN_LOOP("0", A0) MUSIC_FINGERS_MAIN_LOOP("1", A1) MUSIC_FINGERS_MAIN_LOOP("2", A2) MUSIC_FINGERS_MAIN_LOOP("3", A3) MUSIC_FINGERS_MAIN_LOOP("4", A4) MUSIC_FINGERS_MAIN_LOOP("5", A5) MUSIC_FINGERS_MAIN_LOOP("8", A8) MUSIC_FINGERS_MAIN_LOOP("9", A9) MUSIC_FINGERS_MAIN_LOOP("10", A10) MUSIC_FINGERS_MAIN_LOOP("11", A11) delay(2); }
2017-05-21 21:21:20 CEST -- d3fault modified the file: .gitignore
2017-05-21 22:11:10 CEST -- d3fault created the file: scripts/d3faults.superior.unattended-upgrades.sh
#!/bin/bash exit 1 #TODOreq: implement it #For doing "unattended upgrades" on a remote server, the following strategy can be used (note: I am aware debian has an unattended-upgrades package, but I don't trust it -- wtf does it do when an upgrade asks me a question? how could that package possibly know my answer?) #0) A tmux session is launched as root on the remote server #1) A while true loop in bash, sleeping ~24 hours at the end of each iteration #2) We launch a background process that performs the following: # 2a) Sleep for ~45 minutes (or whatever is determined to be a good "max upgrade duration") # 2b) Send an email to us saying that an upgrade is awaiting response to a question, at which point we can re-attach to the tmux session and answer the question # 2c) pause (see the comment in (4) for an explaination of why) #3) apt-get update && apt-get upgrade -y #4) Kill the process launched in (2) so that the email in (2b) never gets sent (note: the process may have already exitted, so the script needs to make sure not to crash in that case -- if we store a PID, can't that PID be used by a different process at a later date? TO DOnereq wtfz -- one solution is to add a `pause` after (2b) so that the process DOESN'T exit and we know the PID won't be re-used by some arbitrary 3rd party process) #alternatively, you can omit the "-y" flag from the apt-get upgrade in (3) so that you are asked to confirm EVERY upgrade, not just ones that ask questions... and you still won't be bothered when there's nothing to upgrade #TODOmb: instead of running once every 24 hours, run on an event: whenever a DSA is posted. all I'd have to do is subscribe to the mailing list :). I'm not sure if backports has it's own DSA mailing list, it might (and don't backports get upgraded differently anyways (by specifying install again? I forget)) -- doing this would [probably] be less bandwidth wasteful (might be more wasteful xD) and would [definitely] pull in security patches MUCH faster #TODOoptimization: optimization of above comment^ ... I could parse the relevant packages from the DSA and then determine (systematically) if it even affects me (or my dependencies). I'm not sure exactly how to do that (apt and/or dpkg magic), but I'm 99% sure it's possible. This would cause me to only ever use bandwidth when I need it (aside from polling an email server a bunch LoLoL (or being an email server (fuck that..... but maybe)))
2017-05-21 03:36:51 CEST -- d3fault modified the file: Projects/MusicFingers/src/lib/musicfingersserialportintegration.cpp
2017-05-21 02:21:38 CEST -- d3fault created the file: Documents/minddump/2017/5/1495326021-TJ3119.txt
I got over my fear/hatred of new versions of C++. The CppCoreGuidelines talk by the man himself certainly helped, but what did it was when I realized that LLVM/Clang can parse C++14/etc and spit out ANSI C :-D.
2017-05-21 02:08:35 CEST -- d3fault modified the file: scripts/apt.initial.packages.debian.txt
2017-05-21 01:42:54 CEST -- d3fault created the file: Documents/minddump/2017/5/1495323758-TJ2659.txt
Compile earlier, compile oftener.
2017-05-20 23:17:57 CEST -- d3fault modified the file: Projects/wasdf/design/pin.detection.and.finger.mapping.are.same.step.as.calibration.txt
2017-05-20 23:17:57 CEST -- d3fault created the file: Projects/wasdf/design/pin.detection.and.finger.mapping.are.same.step.as.calibration.txt
This increases my workload quite a bit, but I just realized that pin detection (which analog pings are actually in use for a given arduino) and finger mapping (which analog pins map to which fingers) should almost certainly be done at the same time as calibration (what range does each finger use between 0 and 1023?). The steps are as follows: 0) Move all 10 of your fingers Then we watch EVERY analog pin until 10 show movement before moving on and saying "Good" 1) Now move your left pinky in as far as you can back and forth Knowing when to move on poses a problem. We could wait 5 seconds, but what if they don't move their pinky at all? For the OTHER 9 fingers, we could use the pinky (or perhaps right index should come first) as a 'next' key, but that very first finger poses a problem. There's also [...gonna continue writing below...] Repeat for the other 9 fingers 2) Calibration complete ...There's also the problem that they might move the wrong (non-requested) fingers accidentally, so perhaps there needs to be a "is this right?" confirmation or some sort of (visual?) feedback so they know they're mapping their finger(s) to the right pin(s). My plan up until a few mins ago was to have an 11th form of input: a simple pushbutton that says "next" every time it's pressed. But is that an overkill solution? Will that 11th input just sit there and do nothing for the remainder of the wasdf use? Isn't 10 analog inputs FUCKING PLENTY? (yes!) Fuck in all honesty I think I need to sleep on this problem. I never until today considered realtime pin mapping, so I haven't had the chance to let my subconscience tackle it. That 11th input (pushbutton) solution (and the inferior "use first calibrated finger as 'next' button from then on (inferior because how to calibrate first finger?)) have been sitting in my subconscience for years now xD. Hmm ok forelobe'd it: after saying "move your pinky as far as you can", we can simply watch all 10 pins for ~5 seconds and the pinky is the one that moves the MOST. After that we can use the pinky itself as a 'next' key (the threshold for boolean/binary activation should maybe be calibrated before moving onto the next 9 if that's the case TODOmb), or we can simply use the ~5 sec strat for the other 9. Maybe instead of a constant ~5 sec, a min/max timeout should be used: wait a min of 2 sec and a max of 15 sec. Once ~50% range of _only_ 1 of the 10 fingers has been "used"/utilized/calibrated _AND_ 2 sec (min) has elapsed, we move on. But if 15 seconds has elapsed, we'll settle with whatever finger moved the most (maybe a min of 10% utilization though?). If more than 1 finger utilizes >= ~50% range before that 2 seconds minimum, we tell the user to keep the other 9 fingers still and then start the process over (wait another 2 sec) -- loops infinitely until they behave (shit there are people with diseases who literally can't keep their hands still xDDDDD (but there are also people with greater than and less than 10 fingers (and same with the 2 hands assumption!))). s/LeftPinky/RightIndex -- it just makes more sense for right index to be the "next"/confirm/A(in video game console terms)/yes/OK/etc finger rather than the awkward left pinky. After sleeping on it I realized two things: 1) Don't need to have the step 1 above "move all 10 of your fingers". Since we are going to calibrate each finger anyways, pin detection can be done at the same time. 2) The concept of "50%" does not exist until AFTER calibrated. At least not accurately. 0-1023 is the range of the analog sensors, but in reality much less of that range will actually be used (and it [probably] won't start at 0 nor end at 1023, it will be some segment in between) -- that's the whole point of calibration, to determine the range actually used (both by the sensors AND the specific fingers (my pinky has less range than my index finger, for example))! Still there are two solutions (and ideally combining the two somehow would be best): a) the sensor that uses up the most range of 0-1023 is the finger we told them to move. b) the sensor that moves THE MOST (back and forth and back and forth. we keep track of "total distance moved") is the finger we told them to move. I actually like (b) better than (a) and can't off the top of my head think of a way to combine the two, so fuck it (b) it is! (weird I just came up with both (a) and (b) while writing out (2) :-D) #########Ok so to restate the revised design clearly succinctly: 0) Move your right index finger After a couple seconds we select the analog pin that moved the most (total distance wise, not just the one that utilized the most of the 0-1023 range) 1) Either repeat (0) for the other 9 fingers, or use the right index finger from now on as an OK/Next(finger) trigger -- either one works. Fuck deciding now, I'll code (0) first and let it sit in ye ole' subconscience TODOprobably: for step (0) just above there should maybe be a MINIMUM THRESHOLD of an amount of the 0-1023 range being utilized. people with that shaky hand disease might have an ultra fast vibrating finger that gives us a false positive for the "total distance moved". they might go from 0-5 (out of 0-1023) over and over REALLY fast unintentionally... and it might just marginally beat out their _intended_ finger that has a much larger range utilization. this shouldn't be in the first version, since it complicates things too much and is a corner case as well TODOmb: like fps video games give you a chance (and preferably in-game, too!) to "invert" your aiming joystick, I too should give users a chance to change from their RIGHT index finger to their LEFT. My UIs should never say "curl your right index finger to continue", they should say "press [your?] OK [finger?] to continue"
2017-05-24 03:21:13 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrator.cpp
#include "wasdfcalibrator.h" #include <QTimer> #include <QHashIterator> #include "wasdf.h" //Calibrator or Calibrater? fuggit~ //need to write this somewhere to remember/understand it better: DURING calibration there's information pertaining to every pin (>= 10) on the arduino, but ONCE CALIBRATED we only want to emit/deliver information pertaining to exactly 10 pins. it's our job as the calibrator to figure out which 10. it is (was) slightly confusing that there are 2 sets of "configutations" //TODOreq: "at rest" detection/calibration, which should be a RANGE of motion where we ignore. it needn't be hugging the extremeties (0 or 1023), can be right smack in the middle. that range-size should initially be a hardcoded percentage (10%?) of their full 0-1023 utilization, but longer term would be nice if they could specify their own range-size during the calibration phase //^"at rest" detection could be done after all 10 fingers are calibrated ("ok now put your fingers at rest and keep them still for 5 seconds"), or (ideally) we could do it on the fly while doing the initial 10 finger calibration (the less steps to calibration, the better). to do it "on the fly" requires careful logic: I should detect the "at rest" point (which the at rest 'range' is based around) for a finger on my right hand while a finger on my left hand is being pin-detected-and-full-movement-range-calibrated (aka normal calibration). the reason for this is that fingers on the same hand tend to bend alongside other ones (whereas fingers on the opposite don't). an example flow: while calibrating left index finger, do at rest detection of right index finger; while calibrating right middle finger, do at rest detection of left index finger, so on and so forth. I'm not quite sure when the at rest detection of the very last finger (left pinky) should be done, but there's bound to be sometime to do it eventually~. maybe during the "ok now choose which finger you want as your ok/next/continue/yes finger?" stage (which, if it even exists (right index finger for now)) follows immediately after the calibration stage. //^^I thought long and hard about it, and finally found a design I like that isn't toooooo complex and also doesn't require special handling of the last finger (left pinky). Basically WHILE we're doing analog pin detection and [normal use] range calibratioin we can be analyzing all of the ANALOG PINS (had:fingers) that aren't currently being calibrated for their "at rest" state. We basically just collect as much data as we can and then make sense of the data after the last finger has been calibrated. It doesn't matter that we don't know which finger each analog pin belongs to, because when we finally do "make sense of the data" we can then match up the analog pins to the fingers (and discard data for analog pins that don't have a finger now mapped). I do still want to only use "at rest" values that were collected while calibrating a fingers on the OPPOSITE hand, so really that's just dropping a couple data sets (once we know which analog pins map to each finger), no problem. Ultimately we'd get (or have remaining) 5 "at rest" values per finger, which we can average together I guess (but hey each of those 5 "at rest" values will themselves probably be averages of the ranges used for the 5 _seconds_ of calibration (happening on the opposite hand)) WasdfCalibrator::WasdfCalibrator(QObject *parent) : QObject(parent) , m_Timer(new QTimer(this)) { m_Timer->setInterval(5000); //TODOmb: visualize the countdown second by second m_Timer->setSingleShot(true); connect(m_Timer, &QTimer::timeout, this, &WasdfCalibrator::handleTimerTimedOut); } WasdfCalibrator::PinNumDetectionAndCalibrationData WasdfCalibrator::getPinCalibrationDataWithTheFurthestAccumulatedDistanceTraveled() { PinNumDetectionAndCalibrationData currentPinDataWithFurthestAccumulatedDistance; QHashIterator<int /*pin number on arduino*/, PinNumDetectionAndCalibrationData> it(m_AccumulatedDistancesEachAnalogPinMoved_ByAnalogPinId); while(it.hasNext()) { it.next(); if(it.value().AccumulatedDistanceThePinHasMoved > currentPinDataWithFurthestAccumulatedDistance.AccumulatedDistanceThePinHasMoved) { currentPinDataWithFurthestAccumulatedDistance = it.value(); } } //TODOreq: error checking? what if all pins didn't move at all for example, would likely mean the arduino is wired wrong return currentPinDataWithFurthestAccumulatedDistance; } void WasdfCalibrator::calibrateNextFingerAndEmitCalibrationCompleteAfterLastFinger() { if(m_OrderedFingerIterator.hasNext()) calibrateFingerAndThenCallCalibrateNextFingerAgain(m_OrderedFingerIterator.next()); else { m_AtRestDetector.finalize(&m_Calibration); emit calibrationComplete(m_Calibration); } } void WasdfCalibrator::calibrateFingerAndThenCallCalibrateNextFingerAgain(Finger fingerToCalibrate) { m_FingerCurrentlyBeingCalibrated = fingerToCalibrate; m_AccumulatedDistancesEachAnalogPinMoved_ByAnalogPinId.clear(); emit o("Move your " + fingerEnumToHumanReadableString(fingerToCalibrate) + " finger back and forth as much as you can and as far as you can for a few seconds. Try to keep your other fingers as still as possible (but in a position you find comfortable and natural)."); //TODOreq: the wording here sucks, the user will be confused: "aren't as far and as much the same?" an animated .gif explaining it to the user would be best, but even that gif needs to have carefully selected wording xD //TODOreq: ^ "left/right thumb finger" sounds dumb kek. there are probably other usages of that dumb-ness ofc. the solution is ez but busy work m_Timer->start(); } void WasdfCalibrator::handleAnalogPinReadingChanged(int pinNumberOnArduino, int newPinPosition) { PinNumDetectionAndCalibrationData currentPinData = m_AccumulatedDistancesEachAnalogPinMoved_ByAnalogPinId.value(pinNumberOnArduino, PinNumDetectionAndCalibrationData()); //this line of code is to facilitate analog pin number detection: currentPinData.AccumulatedDistanceThePinHasMoved += static_cast<long>(qAbs(currentPinData.PreviousPinPosition - newPinPosition)); //these next few lines of code are for finger movement range calibration: currentPinData.PinCalibrationData.AnalogPinIdOnArduino = pinNumberOnArduino; currentPinData.PinCalibrationData.MaxValue = qMax(currentPinData.PinCalibrationData.MaxValue, newPinPosition); currentPinData.PinCalibrationData.MinValue = qMin(currentPinData.PinCalibrationData.MinValue, newPinPosition); //this line of code is to facilitate finger "at rest" position calibration m_AtRestDetector.addAnalogPinPosition(pinNumberOnArduino, newPinPosition); m_AccumulatedDistancesEachAnalogPinMoved_ByAnalogPinId.insert(pinNumberOnArduino, currentPinData); } void WasdfCalibrator::startCalibrating() { m_OrderedFingerIterator.reset(); //not really necessary unless they call startCalibrating again at a later date (RE-calibration) calibrateNextFingerAndEmitCalibrationCompleteAfterLastFinger(); } void WasdfCalibrator::handleTimerTimedOut() { //pseudo: m_FingerCurrentlyBeingCalibrated = m_FingerThatMovedTheMostTotalDistance; PinNumDetectionAndCalibrationData pinCalibrationDataOfFingerCurrentlyBeingCalibrated = getPinCalibrationDataWithTheFurthestAccumulatedDistanceTraveled(); m_AtRestDetector.weJustFinishedCalibratingThisAnalogPinId(m_FingerCurrentlyBeingCalibrated, pinCalibrationDataOfFingerCurrentlyBeingCalibrated.PinCalibrationData.AnalogPinIdOnArduino); m_Calibration.insert(m_FingerCurrentlyBeingCalibrated, pinCalibrationDataOfFingerCurrentlyBeingCalibrated.PinCalibrationData); emit o("We've determined that your " + fingerEnumToHumanReadableString(m_FingerCurrentlyBeingCalibrated) + " finger is connected to arduino's analog pin #" + QString::number(pinCalibrationDataOfFingerCurrentlyBeingCalibrated.PinCalibrationData.AnalogPinIdOnArduino)); calibrateNextFingerAndEmitCalibrationCompleteAfterLastFinger(); }
2017-05-24 01:40:02 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrator.h
#ifndef WASDFCALIBRATOR_H #define WASDFCALIBRATOR_H #include <QObject> #include <QHash> #include "wasdf.h" #include "fingeriteratororderedbymostusedfingers.h" #include "wasdfcalibrationatrestdetector.h" class QTimer; class WasdfCalibrator : public QObject { Q_OBJECT public: explicit WasdfCalibrator(QObject *parent = 0); private: struct PinNumDetectionAndCalibrationData { //these two variables are used for pin number detection: int PreviousPinPosition = 0; long AccumulatedDistanceThePinHasMoved = 0; //this struct is used for finger movement range calibration: WasdfCalibrationFingerConfiguration PinCalibrationData; }; void calibrateNextFingerAndEmitCalibrationCompleteAfterLastFinger(); void calibrateFingerAndThenCallCalibrateNextFingerAgain(Finger fingerToCalibrate); PinNumDetectionAndCalibrationData getPinCalibrationDataWithTheFurthestAccumulatedDistanceTraveled(); WasdfCalibrationConfiguration m_Calibration; QHash<int /*pin number on arduino*/, PinNumDetectionAndCalibrationData> m_AccumulatedDistancesEachAnalogPinMoved_ByAnalogPinId; QTimer *m_Timer; FingerIteratorOrderedByMostUsedFingers m_OrderedFingerIterator; Finger m_FingerCurrentlyBeingCalibrated; WasdfCalibrationAtRestDetector m_AtRestDetector; signals: void o(const QString &msg); void calibrationComplete(const WasdfCalibrationConfiguration &calibrationConfiguration); public slots: void handleAnalogPinReadingChanged(int pinNumberOnArduino, int newPinPosition); void startCalibrating(); private slots: void handleTimerTimedOut(); }; #endif // WASDFCALIBRATOR_H
2017-05-24 21:50:02 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdf.cpp
#include "wasdf.h" #include <QCoreApplication> #include <QSettings> #include "wasdfarduino.h" #include "wasdfcalibrator.h" #include "wasdfcalibrationconfigurationsettingsreaderwriter.h" #define SETTINGS_KEY_IS_CALIBRATED "isCalibrated" Wasdf::Wasdf(QObject *parent) : QObject(parent) , m_Arduino(new WasdfArduino(this)) { QCoreApplication::setOrganizationName("wasdf organization"); QCoreApplication::setOrganizationDomain("wasdf.com"); QCoreApplication::setApplicationName("wasdf"); QSettings::setDefaultFormat(QSettings::IniFormat); connect(m_Arduino, &WasdfArduino::e, this, &Wasdf::e); } bool Wasdf::fingerIsLeftHand(Finger finger) { switch(finger) { case Finger::LeftPinky_Finger0: case Finger::LeftRing_Finger1: case Finger::LeftMiddle_Finger2: case Finger::LeftIndex_Finger3: case Finger::LeftThumb_Finger4: return true; break; case Finger::RightThumb_Finger5: case Finger::RightIndex_Finger6: case Finger::RightMiddle_Finger7: case Finger::RightRing_Finger8: case Finger::RightPinky_Finger9: return false; break; } return true; //shouldn't (won't) get here } void Wasdf::startWasdfActualSinceCalibrated() { connect(m_Arduino, &WasdfArduino::fingerMoved, this, &Wasdf::handleFingerMoved); m_Arduino->start(m_Calibration); //TODOoptimization: once the AtRestPosition or AtRestMinValue/AtRestMinValue stuff is implemented, it would be best if the arduino was told of those values and DIDN'T WRITE TO SERIAL whenever a finger was considered "at rest"... as opposed to us filtering that out on the PC side. the quieter we keep the serial line, the less chance of corruption/errors } void Wasdf::startWasdf() { QSettings settings; bool isCalibrated = settings.value(SETTINGS_KEY_IS_CALIBRATED, false).toBool(); if(!isCalibrated) { m_Arduino->startInCalibrationMode(); m_Calibrator = new WasdfCalibrator(this); //TODOreq: wtf for some reason this doesn't work with qt5-style syntax, which is weird because the WasdfArduino::e signal connects just fine to Wasdf::e signal. I also confirmed that the QPointer isn't the problem //connect(m_Calibrator.data(), &WasdfCalibrator::o, this &Wasdf::o); connect(m_Calibrator.data(), SIGNAL(o(QString)), this, SIGNAL(o(QString))); //qt4-style connect for now connect(m_Arduino, &WasdfArduino::analogPinReadingChangedDuringCalibration, m_Calibrator.data(), &WasdfCalibrator::handleAnalogPinReadingChanged); connect(m_Calibrator.data(), &WasdfCalibrator::calibrationComplete, this, &Wasdf::handleCalibrationComplete); m_Calibrator->startCalibrating(); } else { WasdfCalibrationConfigurationSettingsReaderWriter::readFromSettings(settings, &m_Calibration); emit o("Calibration read from settings"); startWasdfActualSinceCalibrated(); } } void Wasdf::handleCalibrationComplete(const WasdfCalibrationConfiguration &calibrationConfiguration) { m_Calibration = calibrationConfiguration; QSettings settings; WasdfCalibrationConfigurationSettingsReaderWriter::writeToSettings(settings, calibrationConfiguration); if(!m_Calibrator.isNull()) { disconnect(m_Arduino, &WasdfArduino::analogPinReadingChangedDuringCalibration, m_Calibrator.data(), &WasdfCalibrator::handleAnalogPinReadingChanged); m_Calibrator->deleteLater(); } startWasdfActualSinceCalibrated(); } void Wasdf::handleFingerMoved(Finger finger, int newPosition) { emit o("Finger '" + fingerEnumToHumanReadableString(finger) + "' moved to position: " + QString::number(newPosition)); //TODOreq: this is only here for testing static int numMovementsReceived = 0; ++numMovementsReceived; if(numMovementsReceived == 2000) emit wasdfFinished(true); } QString fingerEnumToHumanReadableString(Finger finger) { //optimized for most commonly used fingers (middle fingers vs thumbs is a tie if you ask me xD. I'd say thumb beats middle for DAILY (normal non-wasdf) USE, but this isn't going to be daily use now is it? ex: when using your mouse you use your middle finger to right click a lot) switch(finger) { case Finger::Finger6_RightIndex: return "right index"; break; case Finger::Finger3_LeftIndex: return "left index"; break; case Finger::Finger7_RightMiddle: return "right middle"; break; case Finger::Finger2_LeftMiddle: return "left middle"; break; case Finger::Finger5_RightThumb: return "right thumb"; break; case Finger::Finger4_LeftThumb: return "left thumb"; break; case Finger::Finger8_RightRing: return "right ring"; break; case Finger::Finger1_LeftRing: return "left ring"; break; case Finger::Finger9_RightPinky: return "right pinky"; break; case Finger::Finger0_LeftPinky: return "left pinky"; //rip left pinky, nobody loves/uses him (jk I hope to) break; } return "#error finger#"; //should (will) never get here } void WasdfCalibrationConfiguration::calculateAtRestRange(const WasdfCalibrationFingerConfiguration &fingerConfiguration, int *out_AtRestMin, int *out_AtRestMax) { #define WASDF_AT_REST_RANGE_PERCENT 10 //calculate range based on AtRestValue using a hardcdoed percentage _OF_ the calibrated MinValue<-->MaxValue range (not of 0-1023) //constrain it to within MinValue<-->MaxValue (inclusive) too qreal halfAtRestRangePercent = static_cast<qreal>(WASDF_AT_REST_RANGE_PERCENT) / 2.0; //half for the upper range, half for the lower range qreal calibratedTotalRange = qAbs(fingerConfiguration.MaxValue - fingerConfiguration.MinValue); int halfAtRestRange = qRound(calibratedTotalRange * (halfAtRestRangePercent / 100.0)); *out_AtRestMin = qMax(fingerConfiguration.AtRestPosition - halfAtRestRange, fingerConfiguration.MinValue); //get the higher of the 2 values: calculated at rest min vs. calibrated min value *out_AtRestMax = qMin(fingerConfiguration.AtRestPosition + halfAtRestRange, fingerConfiguration.MaxValue); //get the lower of the 2 values: calculated at rest max vs. calibrated max value } bool WasdfCalibrationConfiguration::hasFingerWithAnalogPinId(int analogPinId) const { QHashIterator<Finger, WasdfCalibrationFingerConfiguration> it(*this); while(it.hasNext()) { it.next(); if(it.value().AnalogPinIdOnArduino == analogPinId) return true; } return false; } Finger WasdfCalibrationConfiguration::getFingerByAnalogPinId(int analogPinId) const { //NOTE: a finger with that analog pin id MUST exist or the program crashes xD. use hasFingerWithAnalogPinId() first QHashIterator<Finger, WasdfCalibrationFingerConfiguration> it(*this); while(it.hasNext()) { it.next(); if(it.value().AnalogPinIdOnArduino == analogPinId) return it.key(); } qFatal("WasdfCalibrationConfiguration::getFingerByAnalogPinId called with invalid pinId. make sure it exists first by calling WasdfCalibrationConfiguration::hasFingerWithAnalogPinId"); return Finger::Finger0_LeftPinky; //won't get here }
-- d3fault created the file: Projects/wasdf/src/lib/wasdfcalibrationconfiguration.h
#ifndef WASDFCALIBRATIONCONFIGURATION_H #define WASDFCALIBRATIONCONFIGURATION_H #include <QHash> #include "wasdf.h" struct WasdfCalibrationConfigurationFinger { int MinValue = 1023; int MaxValue = 0; }; struct WasdfCalibrationConfiguration { WasdfCalibrationConfiguration() { for(Finger finger = Finger0_LeftPinky; finger <= Finger9_RightPinky; ++finger) { FingerCalibrations.insert(finger, WasdfCalibrationConfigurationFinger()); } } QHash<Finger, WasdfCalibrationConfigurationFinger> FingerCalibrations; }; #endif // WASDFCALIBRATIONCONFIGURATION_H
2017-05-24 21:37:23 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdf.h
#ifndef WASDF_H #define WASDF_H #include <QObject> #include <QHash> #include <QPointer> class WasdfArduino; class WasdfCalibrator; enum class Finger { LeftPinky_Finger0 = 0 , Finger0_LeftPinky = LeftPinky_Finger0 , LeftRing_Finger1 = 1 , Finger1_LeftRing = LeftRing_Finger1 , LeftMiddle_Finger2 = 2 , Finger2_LeftMiddle = LeftMiddle_Finger2 , LeftIndex_Finger3 = 3 , Finger3_LeftIndex = LeftIndex_Finger3 , LeftThumb_Finger4 = 4 , Finger4_LeftThumb = LeftThumb_Finger4 , RightThumb_Finger5 = 5 , Finger5_RightThumb = RightThumb_Finger5 , RightIndex_Finger6 = 6 , Finger6_RightIndex = RightIndex_Finger6 , RightMiddle_Finger7 = 7 , Finger7_RightMiddle = RightMiddle_Finger7 , RightRing_Finger8 = 8 , Finger8_RightRing = RightRing_Finger8 , RightPinky_Finger9 = 9 , Finger9_RightPinky = RightPinky_Finger9 }; QString fingerEnumToHumanReadableString(Finger finger); inline uint qHash(const Finger &key, uint seed) { return qHash(static_cast<int>(key), seed); } struct WasdfCalibrationFingerConfiguration { int AnalogPinIdOnArduino = -1; int MinValue = 1023; //TODOreq: ctrl+shift+f all non-comment instances of '1023' (and 0) and replace them all with a common constant declared at the top of this file int MaxValue = 0; int AtRestPosition; //TODOreq: we'd hardcode ~10% range around this AtRestPosition (until the AtRestMaxValue/AtRestMinValue is implemented, at which point percentages (or this mid-point) are no longer used). also worth noting that the range min/max calulcated using percentages must be constrained to 0-1023 //TODOeventually: //int AtRestMinValue; //int AtRestMaxValue; }; class WasdfCalibrationConfiguration : public QHash<Finger, WasdfCalibrationFingerConfiguration> { public: static void calculateAtRestRange(const WasdfCalibrationFingerConfiguration &fingerConfiguration, int *out_AtRestMin, int *out_AtRestMax); bool hasFingerWithAnalogPinId(int analogPinId) const; Finger getFingerByAnalogPinId(int analogPinId) const; }; class Wasdf : public QObject { Q_OBJECT public: explicit Wasdf(QObject *parent = 0); static bool fingerIsLeftHand(Finger finger); private: void startWasdfActualSinceCalibrated(); WasdfArduino *m_Arduino; QPointer<WasdfCalibrator> m_Calibrator; WasdfCalibrationConfiguration m_Calibration; signals: void e(const QString &msg); void o(const QString &msg); void wasdfFinished(bool success); public slots: void startWasdf(); private slots: void handleCalibrationComplete(const WasdfCalibrationConfiguration &calibrationConfiguration); void handleFingerMoved(Finger finger, int newPosition); }; #endif // WASDF_H
2017-05-22 04:21:23 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfarduino.h
#ifndef WASDFARDUINO_H #define WASDFARDUINO_H #include <QObject> #include <QTextStream> #include "wasdf.h" class QSerialPort; class WasdfArduino : public QObject { Q_OBJECT public: explicit WasdfArduino(QObject *parent = 0); private: void openSerialPortIfNotOpen(); void sendCommandToArduino(const QString &command); QSerialPort *m_SerialPort; QTextStream m_SerialPortTextStream; signals: void e(const QString &msg); void analogPinReadingChangedDuringCalibration(int analogPinId, int newPosition); void fingerMoved(Finger finger, int newPosition); public slots: void startInCalibrationMode(); void start(const WasdfCalibrationConfiguration &calibrationConfig); private slots: void handleSerialPortReadyReadCalibrationMode(); void handleSerialPortReadyReadNormalFingerMovementMode(); }; #endif // WASDFARDUINO_H
2017-05-24 01:31:04 CEST -- d3fault created the file: Projects/wasdf/src/wasdf.pri
INCLUDEPATH *= $$system(pwd)/lib HEADERS *= $$system(pwd)/lib/wasdf.h \ $$system(pwd)/lib/wasdfarduino.h \ $$system(pwd)/lib/wasdfcalibrator.h \ $$system(pwd)/lib/fingeriteratororderedbymostusedfingers.h \ $$system(pwd)/lib/wasdfcalibrationconfigurationsettingsreaderwriter.h \ lib/wasdfcalibrationatrestdetector.h SOURCES *= $$system(pwd)/lib/wasdf.cpp \ $$system(pwd)/lib/wasdfarduino.cpp \ $$system(pwd)/lib/wasdfcalibrator.cpp \ $$system(pwd)/lib/fingeriteratororderedbymostusedfingers.cpp \ $$system(pwd)/lib/wasdfcalibrationconfigurationsettingsreaderwriter.cpp \ lib/wasdfcalibrationatrestdetector.cpp
2017-05-20 05:36:02 CEST -- d3fault modified the file: Projects/MusicFingers/src/lib/finger.h
2017-05-24 22:04:23 CEST -- d3fault created the file: Projects/wasdf/src/lib/wasdfarduino.cpp
#include "wasdfarduino.h" #include <QtSerialPort/QSerialPort> #include <QStringList> #include <QHashIterator> #include <QDebug> #include "wasdf.h" //so now for the protocol. at least [so far (and I intend to keep it that way!)] the protocol is relatively simple. I need to also keep in mind that when the Arduino is in mouse/keyboard mode that it doesn't use the Serial.write shit (it could, but then I'd need a priveledged keyboard-press/mouse-movement-n-click daemon-thing on the PC side, and those daemon-things are OS specific!) //Modes //1) Calibrating //2) Report finger movements verbosely over serial //3) Keyboard/Mouse //are (2) and (3) mutually exclusive? idfk tbh so I'll try to make it so they can both be used simultaneously (I seem to recall a fantasy where I'm coding and making music at the same time? in fact that is part of my 'perfect moment' (goal) in life so yea they are not/shouldn't be mutually exclusive (unless I'm just toggling modes ultra fast in that fantasy. since the fantasy hasn't happened yet I'm free to define it however I please) //hmm json, binary, csv(s/comma/colon/newline/etc), hmm. time to research what kind of serialization arduino comes with, since it's libraries are way more limited than the PC sides of things //I want to use json but I don't see any built-in libs and I'm sure as shit not about to write a parser. there are very likely lightweight self-contained pure c/c++ libraries I could just #include, but I'm pretty sure this arduino micro has.... a micro amount of space available. mb just 8kb compiled? *checks*. oh nice 28kb, that should be enough for anyone (ziiiiiing) //meh after researching a decent sounding MIT-licensed ArduionJson library... and thinking about it more in the process... I don't think my protocol will be so complex to warrant json. I'll keep json in mind in case things start to get complex, but meh just a plaintext+colon+newlines protocol (like in MusicFingers, though obviously more robust since calibration mode must exist) sounds sufficient. I'll think about it more while I eat dinner (clam chowda) //another way I could do things is to have 1 sketch for calibration and 1 sketch for normal operation, that would both give me more room to code the sketches and it would get dead (calibration) code paths out of normal operation //TODOreq: the arduino could persist calibration/configuration to it's EEPROM, which would allow users to take their arduino around to various computers and use them without needing to recalibrate. The protocol would need to be more robust (we first query the arduino to see if it has a stored conf), but it wouldn't be too difficult to implement //TODOreq: I have a choice of simply telling the arduino "hey we want values for these 10 pins" and then keeping the pin-to-fingers map local to the PC, or I can say "hey we want values for these 10 pins which correspond to these fingers". It makes very little difference AT FIRST (esp since both are C++ environments I recently found out (I thought arduino was C only xD)), but considering the t0d0r3q directly above this one (persisting calibration to eeprom), I should then go with the second approach of sending more of the information to the arduino. so once started, I should receive messages like this across serial: "finger0 moved to position 69" (compared to "analog pin 18 moved to position 420"). I do/will have a copy of that pin-to-fingers map on the PC side of course, but I no longer need it once we're up and running (and I suppose if we read calibration config from eeprom, the PC never even needs to know it TODOreq: make sure to never use it then if that's the case (might be safer just to read it just in case we accidentally use it)!!!) <-- disregard that actually we do want to use the calibration on the PC side, we want to constrain (map, actually (maybe both)) the reported sensor values to the determined calibrated min/max values WasdfArduino::WasdfArduino(QObject *parent) : QObject(parent) , m_SerialPort(new QSerialPort("/dev/ttyACM0", this)) //TODOreq: be able to choose different serial ports at runtime, MusicFingers has some of this implemented (using ugly defines kek) and some decent ideas such as "use the _one_ containing the string 'arduino'" etc , m_SerialPortTextStream(m_SerialPort) { m_SerialPort->setBaudRate(QSerialPort::Baud38400); } void WasdfArduino::openSerialPortIfNotOpen() { if(!m_SerialPort->isOpen()) { if(!m_SerialPort->open(QIODevice::ReadWrite /*QIODevice::Text <-- apparently not supported, but I guess it's text by default? <- nope it's binary but eh ascii isn't so hard to work with anyways. my protocol will be pure ascii*/)) { emit e("failed to open serial port \"" + m_SerialPort->portName() + "\" for reading/writing"); //TODOreq: error out, return false or emit finished(false) etc } } } void WasdfArduino::sendCommandToArduino(const QString &commandToSendToArduino) { Q_ASSERT(commandToSendToArduino.length() < (1024)); //TODOreq: 1024 should be in a shared header file between sketch and this. the arduino calls String.reserve(1024) in setup() m_SerialPortTextStream << commandToSendToArduino << "\n"; //don't use endl, that uses \r\n sometimes I think but might be wrong since the QIODevice isn't using QIODevice::Text? fuggit m_SerialPortTextStream.flush(); } void WasdfArduino::startInCalibrationMode() { //in calibration mode, arduino sends _ALL_ (not just 10) analog pin readings over serial (TODOmb: user can pass an --exclude-analog-pins flag in case they're using the other analog pins for something else (but then they'd need to modify the sketch anyways, so maybe this isn't necessary?) disconnect(m_SerialPort, SIGNAL(readyRead())); //TODOreq: for some reason this fails with qt5-style pmf syntax. maybe a newer version of Qt doesn't (otherwise file a bugreport) connect(m_SerialPort, &QSerialPort::readyRead, this, &WasdfArduino::handleSerialPortReadyReadCalibrationMode); openSerialPortIfNotOpen(); sendCommandToArduino("calibrate"); //TODOreq: these strings should be in a shared header, shared between the arduino sketch and this sauce } void WasdfArduino::start(const WasdfCalibrationConfiguration &calibrationConfig) { //this is where the 10 fingers get mapped to the 10 analog pins disconnect(m_SerialPort, &QSerialPort::readyRead, this, &WasdfArduino::handleSerialPortReadyReadCalibrationMode); connect(m_SerialPort, &QSerialPort::readyRead, this, &WasdfArduino::handleSerialPortReadyReadNormalFingerMovementMode); openSerialPortIfNotOpen(); #if 1 QHashIterator<Finger, WasdfCalibrationFingerConfiguration> it(calibrationConfig); QString startCommand("startReportingThesePinsExcludingTheirAtRestRanges:"); bool first = true; while(it.hasNext()) { it.next(); if(!first) startCommand.append(";"); //TODOreq: semi-colon delim in shared header first = false; //startCommand.append(static_cast<int>(it.key())); //the arduino doesn't give a fuck (at this point in my design. might change in the future) which analog pins correspond to which fingers, we (the PC) simply tell it which 10 pins to report (and which ranges of values to ignore for each of those 10 pins) //startCommand.append(","); startCommand.append(it.value().AnalogPinIdOnArduino); startCommand.append(","); //TODOreq: comma delim in shared header int atRestMin, atRestMax; WasdfCalibrationConfiguration::calculateAtRestRange(it.value(), &atRestMin, &atRestMax); startCommand.append(atRestMin); startCommand.append(","); startCommand.append(atRestMax); } //example start command: //startWithPinAtRestRanges:18,0,1023;19,1,1022;28,50,950;... //18 = analog pin id //0 = min at rest value //1023 = max at rest value //repeat for each finger, separated by semicolon //note: the analog pins can be sent in any order. the semicolons separate each finger and are in order of finger id (0-9) #else //There's really only ONE reason to send the finger map to the arduino: to store it in it's eeprom. that should be implemented at a later date, on a rainy day. What we SHOULD send to the arduino during the 'start' command, however, is the "at rest range". Sure I could send the finger map over and have the arduino do the map/constrain calls, but the PC has assloads more processing power (and spare lines of code) than the arduino so it should be the one to do it. Sending over the "at rest range" is a good idea though because it will keep the Serial line much quieter (and dead silent if there's finger no movement on any of the 10 fingers). TODOreq: "at rest range", if calculated using a hardcoded percentage (~10%), might cover the entire range of their normal min/max usage! so NO movements would ever be detected. that 10% needs to be "10% of their calibrated range", not "10% of the total range (0-1023)". ----The _FOLLOWING_ ifdef'd out code sends over the finger map (but is missing the "at rest range" stuff), but the _ABOVE_ code sends over the "at rest range" stuff only---- (the amount of values sent over is the same so they appear almost identical (and indeed were copy/paste), but the values sent are completely different) QHashIterator<Finger, WasdfCalibrationFingerConfiguration> it(calibrationConfig); QString startCommand("startWithPinToFingerMap:"); bool first = true; while(it.hasNext()) { it.next(); if(!first) startCommand.append(";"); //TODOreq: semi-colon delim in shared header first = false; //startCommand.append(static_cast<int>(it.key())); //we know that the fingers are sent 'in order' from 0-9, so we don't need to send them //startCommand.append(","); startCommand.append(it.value().AnalogPinIdOnArduino); startCommand.append(","); //TODOreq: comma delim in shared header startCommand.append(it.value().MinValue); startCommand.append(","); startCommand.append(it.value().MaxValue); } //example start command: //startWithPinToFingerMap:18,0,1023;19,1,1022;28,50,950;... //18 = analog pin id //0 = min value //1023 = max value //repeat for each finger, separated by semicolon //note: the analog pins can be sent in any order. the semicolons separate each finger and are in order of finger id (0-9) #endif //TODOreq: on arduino side we do splitByColon then splitBySemiColon then splitByComma sendCommandToArduino(startCommand); //TODOreq: because serial is a piece of shit it sometimes gives us corrupt data. the arduino should be able to request a re-send of a command (and should maybe use a "SYNC" magic header thing just before that command, because who the fuck knows where we are) if a received command (not just start command) is mal-formed. however on the arduino->pc side of things it's ok if we just silently drop malformed messages (we receive finger movement messages at such a high rate that a few malformed ones is no biggy). still, parity and/or checksums for sending BOTH ways would be nice. TODOoptimization: if I send "checksumm'd messages" from arduino to pc, I should probably combine all 10 finger sensor readings into a single message, otherwise the overhead of messages might take up a large proportion of the bandwidth //TODOmb: for arduino->pc (or maybe both ways). moving to a very simple (not checksum'd) BEGINSYNC/ENDSYNC (with the colon separated message in between those 2 SYNCs) would probably be a good enough error detection (and more importantly, error ignoring) strategy //TODOprobably ------ JSON JSON JSON ------ checksum'd JSON (the checksum is not IN the json, but the checksum 'surrounds'/validates the JSON). if this protocol gets complex AT ALL (and the above comments indicate it might), JSON JSON JSON JSON } void WasdfArduino::handleSerialPortReadyReadCalibrationMode() { while(m_SerialPort->canReadLine()) { QString line = m_SerialPortTextStream.readLine(); //line is simply: "[pinId]:[sensorValue]" QStringList lineSplitAtColon = line.split(":"); if(lineSplitAtColon.size() != 2) { qDebug() << "line didn't split evenly into 2 parts:" << line; //TODOmb: use emit v() for verbose or some such instead? in general I don't like to use qDebug/etc in my proper apps continue; } bool convertOk; int analogPinId = lineSplitAtColon.first().toInt(&convertOk); if(!convertOk) { qDebug() << "lhs of colon didn't convert to int:" << line; continue; } //TODOmb: some error checking of the analog pin id. eg can't be less than 0 (or maybe it can? I have no idea what arduino's rules are on this), but [during calibration (TODOreq: after calibration we know EXACTLY what 'finger ids' we want, so we can filter out everything else)] I'm not sure what a good upper max would be (unless I read them out of arduino headers) int sensorValue = lineSplitAtColon.at(1).toInt(&convertOk); if(!convertOk) { qDebug() << "rhs of colon didn't convert to int:" << line; continue; } if(sensorValue < 0 || sensorValue > 1023) { qDebug() << "sensor value on rhs of colon was out of bounds:" << line; continue; } //should I map the raw sensor values to the calibrated range here? should wasdf do it when it receives the signal emitted below? I think it kind of makes sense to do it right here, because Wasdf called m_Arduino.start(m_Calibration) ... so it makes sense that m_Arduino (this class) reports mapped/calibrated values //TODOreq: map the sensor value to 0-1023. wait no map it to their min/max range, wait no it's a 2 step process, map it to their min/max range and then map that to 0-1023? ehh need to think a little harder on this xD. there's also "constrain" to consider. also the above error checking needs to be modified accordingly emit analogPinReadingChangedDuringCalibration(analogPinId, sensorValue); } } void WasdfArduino::handleSerialPortReadyReadNormalFingerMovementMode() { //TODOreq: }
2017-05-21 22:02:11 CEST -- d3fault created the file: Projects/wasdf/src/wasdf-cli.pro
#------------------------------------------------- # # Project created by QtCreator 2017-05-19T20:21:14 # #------------------------------------------------- QT += core serialport QT -= gui TARGET = wasdf-cli CONFIG += console c++11 CONFIG -= app_bundle TEMPLATE = app SOURCES += cli/main.cpp \ cli/wasdfcli.cpp include(wasdf.pri) HEADERS += cli/wasdfcli.h
2017-05-21 21:31:21 CEST -- d3fault created the file: Projects/wasdf/src/cli/main.cpp
#include <QCoreApplication> #include "wasdfcli.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); WasdfCli cli; Q_UNUSED(cli) return a.exec(); }
2017-05-20 05:16:24 CEST -- d3fault created the file: Projects/wasdf/design/renaming.from.MusicFingers.txt
MusicFingers was always the codename. wasdf is much better (although maybe harder to say?). but really more importantly I was rushing like fuck when I was coding MusicFingers. I remember being stressed the fuck out and sweaty and blah. I want to rewrite with a calm head and stick to cleaner code and correctness (but obviously copy/pasting and referencing MusicFingers a ton). MusicFingers was also.... too music specific (as the name implies). wasdf is going to be coded more properererer: it's a kb/mouse substitute and also a musical instrument. my target right now is simply: realtime calibration with feedback. after that I'd imagine the next step is "mode choosing/switching", but I might be wrong (and calibration might have a 2nd step: analog pin to finger mapping (coded 2nd, but obviously it'd need to be presented to the user before regular calibration). renaming now helps me keep the rushed code out of the non-rushed code.
-- d3fault created the file: Projects/wasdf/assets/ArduinoWriteChangesOnAnalogPinstoSerial/ArduinoWriteChangesOnAnalogPinstoSerial.cpp
//rewriting the first version of this instead of just removing calibration because I also want to try to not to use pp defines/macros. pure C++ is cleaner and easier to read/modify. aside from that it's just a functionally equivalent rewrite (with the calibration stripped out since that's going to be done on the PC side) static const int NUM_ANALOG_PINS_TOTAL = 15; //TODOreq: find a good maximum. maybe use whatever my mega 2560 uses (and cross fingers that boards with fewer analog pins don't crash (could always patch arduino sauce so it returns 0 when requested pin DNE)) static const int NUM_HANDS = 2; static const int NUM_FINGERS_PER_HAND = 5; static const int HALF_THRESHOLD_FOR_NOTIFYING_OF_CHANGE = 2; //TODOoptional: this could be determined during 'calibration' (so it'd be received from PC over serial). example instructions to uesr for determining it: "move your right index finger as little as possible until you see on screen that it's registered" or some such (haven't thought this through very much, maybe it's dumb idea) //TODOmb: when in calibrating mode maybe I should blink pin 13 rapidly, and when normal mode starts I should do 3 long pulses and then disable it (because leaving it on is dumb) bool newSensorValueHasChangedEnoughThatWeWantToReportIt(int oldSensorValue, int newSensorValue) { /*if(NewSensorValue == OldSensorValue) return false; return true;*/ if(newSensorValue < (oldSensorValue-HALF_THRESHOLD_FOR_NOTIFYING_OF_CHANGE)) return true; if(newSensorValue > (oldSensorValue+HALF_THRESHOLD_FOR_NOTIFYING_OF_CHANGE)) return true; return false; } class Finger_aka_AnalogPin { public: explicit Finger_aka_AnalogPin() : NewSensorValue(0) , OldSensorValue(0) { } void setStringAndIntPinIds(const char *stringPinId, int intPinId) { StringPinId = stringPinId; IntPinId = intPinId; } void reportMovementOverSerialPort() { NewSensorValue = analogRead(IntPinId); if(newSensorValueHasChangedEnoughThatWeWantToReportIt(OldSensorValue, NewSensorValue)) { Serial.print(StringPinId); Serial.print(":"); Serial.println(NewSensorValue); OldSensorValue = NewSensorValue; } } ~Finger_aka_AnalogPin() { } const char *StringPinId; int IntPinId; int NewSensorValue; int OldSensorValue; private: explicit Finger_aka_AnalogPin(const Finger_aka_AnalogPin &other) { } //delete }; struct Hand { void setupHand(bool leftTrue_rightFalse) { //TODOreq: the arduino micro doesn't use analog pins 0-9 (note that finger 9 below maps to pin A11), so the following mappings are arduino micro specific. there should obviously be some way to use this code with other boards of course (even a mapping 'file' is better than hardcoding it here). the BEST solution is to, before/during calibration, 'probe' every analog port to see if it's wired, and then to have the user tell us which finger that pin corresponds to.. then to yea save it in some ~/.config 'profile' thingo. for now I'm fine with hardcoding the pin mappings since my target is to get range-of-fingers realtime-with-feedback calibration working [first]. I wonder what happens when you read an analog pin that has nothing attached... it returns 0. in any case and whatever value it is, it shouldn't "move" (I hope) //TODOreq:^I also need to change the MusicFingers serial READ code (runs on PC) to use 0-9 and not the whacky micro-specific mapping like in the previous version of this code //TODOreq: this obviously needs to be refactored to use the calibration data received from the PC if(leftTrue_rightFalse) { //left hand Fingers[0].setStringAndIntPinIds("0", A0); Fingers[1].setStringAndIntPinIds("1", A1); Fingers[2].setStringAndIntPinIds("2", A2); Fingers[3].setStringAndIntPinIds("3", A3); Fingers[4].setStringAndIntPinIds("4", A4); } else { //right hand Fingers[0].setStringAndIntPinIds("5", A5); Fingers[1].setStringAndIntPinIds("6", A8); Fingers[2].setStringAndIntPinIds("7", A9); Fingers[3].setStringAndIntPinIds("8", A10); Fingers[4].setStringAndIntPinIds("9", A11); } } void reportFingerMovementOverSerialPort() { for(int i = 0; i < NUM_FINGERS_PER_HAND; ++i) { Fingers[i].reportMovementOverSerialPort(); } } Finger_aka_AnalogPin Fingers[NUM_FINGERS_PER_HAND]; }; struct Hands { explicit Hands() { hands[0].setupHand(true); hands[1].setupHand(false); } void reportFingerMovementOverSerialPort() { for(int i = 0; i < NUM_HANDS; ++i) { hands[i].reportFingerMovementOverSerialPort(); } } Hand hands[NUM_HANDS]; }; struct Mode { enum ModeEnum { DoNothingMode = 0x000 , Calibrating = 0x001 , Sending10FingerMovementsMode = 0x010 , KeyboardAndMouseMode = 0x100 }; }; //Globals int CalibrationDataOldSensorValues[NUM_ANALOG_PINS_TOTAL]; String inputCommandString; Mode::ModeEnum CurrentMode; Hands hands; void setup() { Serial.begin(9600); for(int i = 0; i < NUM_ANALOG_PINS_TOTAL; ++i) CalibrationDataOldSensorValues[i] = 0; CurrentMode = Mode::DoNothingMode; inputCommandString.reserve(512); //TODOreq: ensure command strings never grow beyond 512 bytes while(!Serial) ; //wait for serial port to connect. Needed for Leonardo/Micro only. I intentionally put the String::reserve command (and other cmds) in between this and Serial.begin() in case the connect happens asynchronously (idfk tbh, but it might), in which case I may have saved an entire millisecond!!! } void calibrationLoop() { for(int i = A0, j = 0; i < NUM_ANALOG_PINS_TOTAL; ++i, ++j) { int oldSensorValue = CalibrationDataOldSensorValues[j]; int newSensorValue = analogRead(i); if(newSensorValueHasChangedEnoughThatWeWantToReportIt(oldSensorValue, newSensorValue)) { Serial.print(i); Serial.print(":"); Serial.println(newSensorValue); CalibrationDataOldSensorValues[j] = newSensorValue; } } } void loop() { switch(CurrentMode) //TODOreq: this switch case doesn't support simultaneous 10-fingers and keyboardMouse modes { case Mode::Sending10FingerMovementsMode: hands.reportFingerMovementOverSerialPort(); //tell, don't ask ;-) break; case Mode::KeyboardAndMouseMode: //TODOreq break; case Mode::Calibrating: calibrationLoop(); break; case Mode::DoNothingMode: delay(50); //mb this saves battery? w/e lol break; } delay(2); //TODOreq: this might fuck up MOUSE MOVEMENT, everything else should be fine with it tho } void processInputCommandString() { if(inputCommandString == "calibrate") { CurrentMode = Mode::Calibrating; return; } } void serialEvent() { while(Serial.available()) { char inChar = (char)Serial.read(); inputCommandString += inChar; if(inChar == '\n') { processInputCommandString(); inputCommandString = ""; } } }
2017-05-20 03:12:00 CEST -- d3fault modified the file: Projects/MusicFingers/src/lib/musicfingers.cpp

This site is Open Source
Download my brain: Torrent
Bitcoin: 1FwZENuqEHHNCAz4fiWbJWSknV4BhWLuYm