lauantai 17. toukokuuta 2014

Printer toner DRM

Some time ago our old printer died - or more exactly, became mostly unusable due to the rollers becoming unable to grab paper from bypass tray. Not long before that I repaired the power board, so that was for nothing but at least bought about a month or so. Replacing rollers might have helped, or some chemical treatments but since I printer was absolutely necessary for normal business operations I couldn't just guess.

So I had to get a new one. Not that big expense, but nevertheless annoying. And of course after only thousand pages or so it started to complain about toner. And now, after few more months it finally refused to print anymore, "change toner cassette". Total to this point was about 2500 pages (I didn't check the counter then and have already printed some amount of pages with new cassette so I can't be exactly sure of the count). Then again, 2500 pages isn't too bad for "starter" cassette these days.

When changing the toner cassette I noticed a small PCB with some pads at one end (printer was delivered to us fully functional so I had no reason to take cassette out before that). Being me - that is, curious (or is that suspicious?), I of course had to take it out, and indeed it was what I suspected - an small PCB with some passives and a small chip on it.


The marking on the chip is "5ME3 R2ES90", and quick search turned out nothing. Not too surprising either, after years of researching random chips one develops kind of "gut feeling" about those markings, and this definitely spelled out "unsearchable" to me.
No matter, when comparing the layout against standard 8-pin I2C EEPROMs it is remarkably similar. So after quick visit on "junk" box I found suitable semi-dead PCB  I could use as base for further exploring (in this context "semi-dead" means that this board was somewhat functional but could not be used in customer devices, even after repairs, so it was put aside for other uses - these typically being some quick prototyping and testing something like this):

The chip visible on main board is a 256kbit EEPROM and there is space for two such chips (sharing common I2C bus) on the board; here the other one was unpopulated so I could solder wires directly there. My guess was that this is small-ish (64, 128 or 256 bytes) I2C EEPROM quick software hack was also needed - I generally use larger (32kB and 64kB) EEPROMS, meaning 16-bit addresses, but dropping hi byte was trivial enough change in C code. And some brief moments later there it is: data dump from the chip itself, all 128 bytes of it:
"T332Q..." part was easiest to decrypt, serial number of the printer as plain text. I just don't like my printer's serial being that readable so it's censored, sorry. No idea however why it is placed in toner memory, maybe every printer the cassette is used in is added there - for what reason I really can't guess.
406972 seems remarkably like a counter, but this printer has done only 2500 pages so the number is a bit high. Also, since these cassettes come in different sizes, I would expect the initial value to be high(ish), decreasing and cassette to be rejected when it reached some low threshold value, so low value would make more sense.

Now, if that 406.. is counter, it would be amount of toner used (instead of raw pages) but I can't really compare it against anything. But then there would have to be cassette type identification somewhere else so printer would know how high value could be which by itself is not that bad idea. However, since printer firmware is practically never updated, no new cassette types could be introduced after first printer was produced - new cassettes need new type ids that need to exist in printer firmware. And in my opinion that is Bad Design.
Another guess for the value would be serial number of cassette, but number doesn't match with anything on the cassette itself, there is only one sticker and it has "MNO" prefix (model number?). That is, unless printer logs lately used cassettes and their print counts, and then just rejects it if cassette "loses" a few prints. But here I may just be paranoid (but then again, that is how I would do it if I had Evil disposition) (off-topic; I have been told that this is actually how modern vehicles (cars, bikes) keep track of the odometer reading - but that is topic for another posting, some time later)

Rest of the data could be anything, your guess is as good as mine. For now I don't even bother to try.

The new cassette is high-capacity one (advertised as 7000+ pages) so I am a bit hesitant on trying to access its chip to compare data, it would suck to make a mistake and lose entire cassette immediately. Maybe later. While I am perfectly aware that it is pretty damn difficult to accidentally write data to chip through I2C I still am hesitating since stupid accidents can and do happen.

Oh, and I did know that inkjet printers use this kinds of chips to track ink usage (this also is why I expected smallish EEPROM, they seem to be commonly used), but so far I had not known laser printers (especially black-and-white ones!) to employ similar idiocy. I know, however, that my next printer very likely will be from some other manufacturer than Ricoh. Just let me use all the toner in the cassette if I want to, damn it.


tiistai 13. toukokuuta 2014

Led matrix update

After some troubles the LED matrix I quickly mentioned before is functional. Unfortunately taking pictures of it (without diffuser, I don't have any handy right now) is damn difficult so the photos aren't exactly of  the greatest quality.




The pictures really don't show observed brightness or color very well, so you have to take my word for it: it looks way better live. And unfortunately my DSLR is one model too old to have video capture, so I can't even give you that (and webcams/phone cams are absolutely worthless - been there, tried that, immediately decided to forget about it)

The four matrices in pictures are chained together and driven by Arduino Uno showing simple color cycle where each component is assigned value with simple rotating sin function, so nothing fancy. Nevertheless it looks quite nice for demonstration purposes (well, when observed live, at least). Arduino manages to update the matrix at rate of 300 updates per second, not bad, and code for updating it is very very simple.

My original idea was that this would be easy-to-use (no complex driving logic required like so many matrices do!) and fairly cheap  module for hobbyist use - showing text, smallish graphics ("We're OPEN!") and whatnot, possibly even slide show from SD card (by using some suitable Arduino shield or maybe Raspberry Pi - neither of which I have available right now). Unfortunately the initial small production run costs about twice what I was aiming for so this may be a bit too expensive (around 70€, including VAT). Damn.
 However, extending this to 16x16 matrix should be fairly simple (granted, routing will be a huge pain, even with added board area) and yet change in cost should be minimal, so maybe I just forget this smaller one and go for that instead.

Any ideas or requests, anyone?


torstai 8. toukokuuta 2014

TV antenna amplifier (another one)

I had this old antenna amplifier ready to be thrown out, but just out of curiosity I decided to open it and see what's inside. Our house was built in early 90s, and according to our neighbors the family that originally lived there was quite religious, in this context meaning that they did not have TV. The area has cable TV but it was never connected to this house. At least the inside wiring was done so connecting TV should be easy later.

Next family living there was ... well, cheap. I've been finding their half-assed fixes (and I'm using the word very liberally here) since moving in, fixing them properly one by one. Even the TV setup was cheap; apparently they bought old antenna, with associated electronics from one neighbor that was updating their system. So this amplifier is likely from the 80s.

Outside there's on/off switch, gain control, indicator LED, one input and two outputs, so quite usual configuration there. The plastic has gotten quite brown and slightly broken from some places.

Assuming that it has usual clips holding it together I tried to pry it open. Whoops. And I didn't even have to use a lots of force.

Right, here's the screw, under the sticker. Finding it first wouldn't have helped anyway, plastic was so badly deteriorated that it would have broken anyway, just from different place.

And the PCB. Top left is on/off switch, below it a fuse (whopping 500mA! Why exactly has someone decided that this thing is allowed to consume 100W is beyond me. Damn thing seems now more like a house fire waiting to happen. Of course I have no way of knowing if the fuse is original or one of those half-assed fixes mentioned earlier), then transformer, on right of it diode bridge and smoothing capacitor. Two round black things with text on them are RF transistors (types BFR 90 and BFR 91A), rest miscellaneous resistors, capacitors and inductors. Nothing too special here.

 So there. Now this thing goes back to trash bin. For good.


perjantai 2. toukokuuta 2014

Teardown of a top-set TV box

Some years ago I signed on Elisa's (local internet/mobile provider) "Viihde" ("Entertainment") service. Original (only) reason for signing up was ADSL (originally 20/1M) but it also includes Tivo-like functionality (by connecting to their servers, you are given about 4TB of (virtual) space for recordings) and on-demand movie rental (also in 1080p) by using their custom top-set box. Total is about 40€/month, not bad (rentals on top of that, if used).

When I signed on I still had my old Topfield box which was quite sufficient, but it finally broke (actually it became unreliable - HD wouldn't wake up sometimes. I still have it but don't really know what to do with it, aside throwing it away - I did examine it but couldn't find the culprit for problems) so I moved on using Elisa's box and was actually quite surprised. I didn't suck - not too much at least.

Unfortunately the TV reception of the original box had grows progressively worse over the time, so I had it replaced with newer model. No need to return the old one so of course I had to take the old one apart to see what's inside. Unfortunately it was pretty much what I expected - system-on-chip solution with minimal external parts.

Here's the board (warning, large image).


The main processor is as expected, "SMP8635LF Secure Media Processor". I couldn't find a datasheet with quick search so I'd expect it to be under NDA. No matter, it isn't too difficult to guess that it contains relatively secure boot loader and loading (possibly encrypted) software from external flash (chip below it, sticker on top) and possibly also encryption of external memory contents (four chips up and right from it). Most likely some tampering detection thrown in for good measure. From system design perspective the datasheet might provide interesting read though.

Lower left corner (highlighted in red) is a bit more interesting. Larger chip is STM32F family MCU , but smaller one is NRF24L01 - "Ultra low power 2.4GHz RF Transceiver". This is not WLAN chip, it can only transmit relatively small data frames, so my guess would be an RF remote control or possibly programming the customer-specific parameters to the unit (each unit is tied to your account and since my account is now moved to new unit, this one will only report error when trying to connect to server). Provided remote was typical IR-based one so if they had RF capability it wasn't used. Pity, I'd love to hide this kind of units that don't need physical access behind TV or other such place where it wouldn't take real estate from units that need to be accessible (like DVD player).

The smaller red square highlight another mildly interesting part of the board. This actually appears to be USB connector. Since this is not available from outside and traces go directly to the main processor, this might be the production programming interface (there is distinctly JTAG-looking header on the bottom of the board, though)

The USB connector right from there is accessible from outside, but it can only be used for time shifting live TV (as in pausing program). There is another USB connector at back of the board too. I think I never used either of those.

On the other (bottom) side there is usual load of passives (resistors and bypass caps for chips), and a card reader module with interface chip. The is also a card interface, accessible through a slot in bottom of the (fully assembled) unit. Box has ability to subscribe to paid channels through your account IPTV so it doesn't really need card, but still it could be useful for accessing usual OTA channels, say, if your fried brings his card over.

Empty footprints at left from the processor and empty connectors look interesting too. Possibly SATA interface for optional internal hard drive? (and other large empty place - PATA connector? I don't  recognize any of those footprint patterns definitely so these are just educated guesses)

At the upper part there are connectors. TV in and out (with associated RF stuff, here with can cover removed), HDMI, another video connector (looks kinda like S-Video but has 9 pins, some non-standard connector?), headphone, optical out, another USB, Ethernet and power, each with their associated interface electronics. And on right power supplies (chip in middle has markings "Summit 113 1085LA1033" - again quick search finds nothing, but my guess is some kind power management controller).

So, all in all, this is another demonstration of current trend of electronics design. Single-purpose unit with any ability to hack or repair it very carefully removed (granted, I kinda understand it in this case, being able to receive and show HD content over internet). But that seems to be the direction we're going now. Doesn't mean that I have to be happy about it though.


perjantai 25. huhtikuuta 2014

Tiny PICs: Schematic and software


This took I little longer than I intended, but after a few distractions here is the last chapter (for now at least) for using PIC12 for toy modification. So now the electrical and software details.

The airplane used three LR44 1,5v batteries in series, so it fit perfectly for PICs operating voltage limits of 2-5v. The white LED had forward voltage drop of 3v, and original series resistor was 120 ohms, meaning about 8 mA for forward current. Easy enough to handle.

I used PIC12F509 for this. PIC10F206 would have been sufficient too, but for some reason I just couldn't get it working, so after a few hours I just gave up. I could load software on the chip but it wouldn't do anything. Weird. Most likely just some stupidly minor detail I missed, but I just couldn't justify using more time on that now, especially since PIC12 worked right away. Since I only that two PIC12s remaining and five PIC10s from last attempt, I suspect that last time I tried situation was the same (yes, tried multiple PIC10s, same result with all, must be the software, or build environment bug)

So I decided to use original LED and series resistor as-is. Single pin of PIC can source 25mA (IIRC), but I still connected two in parallel (specifically GP1 and GP2, pins 5 and 6) to source the LEDs. No reason really, but the "feel good" factor for ridiculously over-engineering single part of design.

My paper schematics end always looking the same, some parts huge and some parts tiny. Oh well, guess I'll just explain it then since schematic isn't exactly most readable.

Circled + and - symbols are battery positive and negative; connecting to PIC pins 1 and 8 respectively. It may not be necessary but I still added small bypass capacitor directly between power pins. For some applications you may get away without one, but as rule of a thumb you'll always want to put one there, especially when there are significant current changed around (like here, 100nA to 10mA) as they smooth out voltage seem by MCU.

Button is connected between pins 8 (GND) and 7 (GP0). GP0 is also very very weakly (1Mohm) pulled high. Since there is basically no load on this pin the pull-up could be a lot smaller without affecting standby power consumption (say, 10k). For EMI resilience (for very very noisy environment) you might want to use smaller resistor (or more importantly, actual well designed PCB). And finally the LED with series resistor. All in all, very simple build.

I also mentioned that it might have been possible to use original switch instead of button. This assumes that the three-pin switch is breaking type (that is, connection is broken before other side is connected). In such case center pin would be negative, and both sides are connected to same sense pin and common pull-up. Pull-up might need to be smaller in that case to pull line up during short break period but it would also make constant always-on current draw so you still would want to use as large resistor as you can get away with.

Now, the software. When dealing with MCUs without OS I just write all the software in plain C nowadays, even for tiny devices such as this. I see no point in learning assembly of even one device crossing my path, there are just too many different MCUs I use. There are exceptions, of course, but there must be sufficient financial reason to spend time delving into mysteries of specific assembly dialect for me to bother for anything more complex than often-useful NOP and almost-always-necessary interrupt enable/disable instructions (and really, nowadays compilers almost always have macros for those - and more)

For PICs I do majority of my work in MPLab X, and for C compiler I used MicroChip's XC8 compiler. Software was fairly simple; whenever processor is reset (for any reason, but typically power-on or wakeup due GP0) it will turn LED on, wait for approximately 5 minutes (timing isn't that critical so variance in RC oscillator is not an issue) and then drop output drivers and enter back to sleep.

#include <xc.h>

// CONFIG - PIC12F509 Configuration Bit Settings
#pragma config OSC = IntRC      // Oscillator Selection bits (internal RC oscillator)
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection off)
#pragma config MCLRE = ON       // GP3/MCLR Pin Function Select bit (GP3/MCLR pin function is MCLR)


/* -----------------------------------------------------------
 * Small delay. About 3ms (as measured)
 */
void delay()
{
  unsigned char i;
  for (i = 0; i < 250; ++i)
    { asm ("nop; nop; nop; nop; nop; nop; nop; nop; nop; 
            nop; nop; nop; nop; nop; nop; nop; nop; nop; nop");
    }
}


/* --------------------------------------------------------------
 * Simple main. On startup LED will be on; after specified time
 * it is turned off, and processor will enter sleep mode.
 */
int main(int argc, char** argv)
{
  unsigned int counter;

   // Configure IO:
   //   GP0      = input (externally pulled high, button pulls down to wake)
   //   GP1, GP2 = LED output (drives high)
  TRISGPIO = 0xF9;
  GPIO = 6; // LED on after wakeup

   // Enable wakeup on pin change (GP0,1,3); disable pull-ups;
  OPTION = 0x40; // 0100'0000

  counter = 0; // timer counter

  while (1) 
    { ++counter;
      if (counter == 33333) // 9 ms per iteration; this makes about 5 minutes
        { GPIO = 0; // turn LED off

          delay(); // let drivers settle (this may not be necessary)

          GPIO; // dummy read state before sleep (required for proper function). 
          GPIO;
          asm("sleep");

           // pin 0 change will then reset chip, (re)starting main again.
          
        }
      delay();
      delay();
      delay(); // 9ms total per iteration
    }
}

This absolutely isn't something I'd put into production, as I don't feel that it is as resilient to external interference (EMI) as it could be (or even optimal solution to this problem actually). My hunch is that this may react "badly" to RF interference (not in sense that it'll cause fire or anything, more like waking up when not needed) but in this case it is not that big problem.

But for intended purpose - to make a toy last a bit longer as useful - it is good enough. That for now, that is more than enough - already forgotten (dead) toy became "hot" item again. Weird how doing something "useless" like this gives you that nice, warm feeling inside...


keskiviikko 23. huhtikuuta 2014

SailfishOS: Accessing GPS

I suspect there are many others that have wanted to use GPS on their Jolla phone application but have not been successful in their attempts. In that case this should help you a bit.

If you are in hurry, just skip to the end, DBus code is there in all its ugliness. Everything in between is mostly background.

At the moment SailfishOS' Qt is something between versions 5.1 and 5.2. For GPS (or more accurately, the positioning information in general) this is unfortunate as old QtLocation subsystem no longer exists and new QtPositioning isn't there yet. After numerous web seaches I came in conclusion that following options are available right now:
  • Older QtLocation (possibly with custom import module). Reading between the lines I got the impression that if you wish to publish your app on Jolla's official shop this is very much frowned upon there.
  • Import custom module based on QtPositioning and use it. Slightly better, but this may later bite you back when phone is updated and official (yet possibly slightly different, as API is not yet completely stable) system interferes with your custom solution. So this also is frowned upon.
  • Hack to the DBUS and obtain location from there. Also frowned upon, but apparently least of these options. Of course no one bothered to mention how to do it...
Well, I went for the last option anyway, planning to upgrade to QtPositioning when it becomes properly available. It's way easier anyway than all this DBus mess.

Now, if you have read what I have written about my experience on working on Qt (previously zilch but at least I had browsed quickly some docs in the past), QML (maybe I had heard of it somewhere, not sure) or DBus (at least I had heard of it) you may already have guess how easy my progress to the depths of DBus was.

Well, actually, it wasn't as bad as I first expected, browsing the lower level documentation. As I had map drawing system running already, so I was getting familiar with "the Qt way". And since Qt appears to have everything and kitchen sink included (for the better or the worse, depending on your view), I figured there might be DBus too... And what do you know, there is.

Now, with that hurdle passed, proceed to the next. SailfishOS uses actually older implementation of Geoclue, references found here. The older version is very badly documented and examples are just about eually good - unfortunately even those are using C API (not available here, at least without more custom modules) that doesn't translate direcly to Qt/DBus combination. And Qt's DBus subsystem is very picky about defining call signatures (damn you Geoclue for using almost completely unnecessary structs to pass data I don't even care about - but Qt does, just enough to not to co-operate with my efforts). So good luck there, especially since Qt documentation mentions structs, arrays and dictionaries in passing - but completely neglects to mention how they should be used.

Did I remember to  tell you how frustrating some things were?

Even Google isn't very helpful when trying to find something this obscure. But eventually, after hundreds of searches (no, I am not kidding there) with varying search terms I managed to scrape together enough information to write my own code. Other search providers were even less helpful.

Eventually I scraped together enough information to work on. So, I implemented everything according to Geoclue and... nothing. No position information. Based on all the examples I had I should have updates coming, but no. Que debugging information, and when trying to send "GetPosition" I get result in tune of "Can't be done as there are no location providers" (I don't remember the exact phrase used). Wut? But this Maps app here has position coming in... Lightbulb moment...

At this point I had managed to gain enough knowledge of DBus in general and Qt's abilities so I could started to get creative. On terminal you can use dbus-monitor to, well, monitor what's going on dbus. So I started logging everything (if you want to do this too, log in file - there will be lots of events across all subsystems), started Maps app, and then quit soon after starting and started reading the logs.

And what do you know, the Maps app actually doesn't seem to use the Geoclue.Position interface; it accesses directly the Hybris (that's the GPS - and GPS only - provider) for location information (the interface for that is org.freedesktop.Geoclue.Providers.Hybris - so far I haven't found any relevant interface documentation about it or even Providers in general). So insert a short (and very very boring) montage of software hacking in all its glory here and soon the GPS position updates started coming in. Whew!

So, now for the actual implementation. As my project is in C++ (except the UI), the GPS interface is too. It shouldn't be too difficult to build quick adapter to access this from QML either, but I won't go to details of that here.

So, first your project. To use DBus you must have line
QT += dbus
In your .pro file.

It is best to implement your receiver as a separate class that provides its own interface for rest of your app, making it easy to switch to QtPositioning later when it becomes available. So the header (vastly simplified, relevant includes are left as exercise for the reader, that shouldn't be too difficult)

class PositionSource : public QObject {
    Q_OBJECT
public:
    PositionSource(QObject *parent);
public slots:
    void positionChangedDBUS(QDBusMessage);
private:
    QDBusInterface *masterInterface, *clientInterface, *hybrisInterface, *hereInterface;
};

And Cpp (again, I'm skipping everything but the most interesting parts). Also the Blogger's editor doesn't seem to like <> tags, so it may have messed something up during edits.

PositionSource::PositionSource(QObject *parent) :
    QObject(parent)
{
    masterInterface = new QDBusInterface("org.freedesktop.Geoclue.Master",
                                         "/org/freedesktop/Geoclue/Master",
                                         "",
                                         QDBusConnection::sessionBus() );
    QDBusReply<qdbusobjectpath> createReply = masterInterface->call("Create");
    qDebug() << "create:" << createReply.value().path();

    if (createReply.value().path().length() < 5) { // just quick-and-dirty check 
        qDebug() << "Could not create geoclue client";
        return;
    }

    clientInterface = new QDBusInterface( "org.freedesktop.Geoclue.Master",
                                          createReply.value().path(),
                                          "",
                                          QDBusConnection::sessionBus() );

    QDBusMessage msg;

     // GeoClue has "SetRequirements" function where you can specify your
     // app's requirements. Note that if they are too strict (like you
     // ask for precision no position provider can do), GeoClue doesn't
     // seem to fall back to "lesser" provider but will fail to give you
     // position information at all.
     // I am not sure if that was reason for original problems with
     // Geoclue.Position interface (found out about that only later, by
     // reading actual geoclue sources) but proceed with caution if you
     // want to try that.

     // SetRequirements: 
     //   accuracy level: GeoclueAccuracyLevel-enum
     //   minimum update time
     //   require updates
     //   resources, another enum again; (1<<2) should be GPS, (1<<10)-1 "anyting"

    clientinterface->call("SetRequirements", 1,0, true, 1023);


     // This most likely isn't very relevant when using Hybris directly, but I kept it anyway.
    clientInterface->call("PositionStart");


    // Then, register Hybris provider.
    hybrisInterface = new QDBusInterface("org.freedesktop.Geoclue.Providers.Hybris",
                                        "/org/freedesktop/Geoclue/Providers/Hybris",
                                        "",
                                        QDBusConnection::sessionBus() );


    msg = hybrisInterface->call("AddReference");
    if (msg.type() != QDBusMessage::ReplyMessage) { // quick and dirty check
        qDebug() << "Couldn't access Hybris : " << msg;
        status = POS_UNKNOWN;
        return;
    }

    // SetOptions parameter appears to be: (I'm guessing this implies auto-detect)
    // I have no idea on how to actually create the providerOpts so Qt would accept it
    // (and Qt documentation is *wonderfully* vague about that), but I'm leaving this
    // here in case someone has good ideas)
    // This call doesn't seem to be necessary anyway since position is obtained anyway,
    // but on different hardware this might have different results.
    //   array [
    //      dict: "gps-baudrate", 0;
    //      dict: "gps-device",   "";
    //   ]

    /*
    msg = hybrisInterface->call("SetOptions", providerOpts);
    if (msg.type() != QDBusMessage::ReplyMessage) {
        qDebug() << "Couldn't set hybris options : " << msg;
    }
    */

     // These are just for general information
    msg = hybrisInterface->call("GetProviderInfo");
    qDebug() << "  Hybris provider info: " << msg;

    msg = hybrisInterface->call("GetStatus");
    qDebug() << "  Hybris status: " << msg;

     // Now, if you really wanted to, you could do same for org.freedesktop.Geoclue.Providers.Here,
     // to get information from it. But then again, why bother? (especially if you are concerned about
     // privacy).

     // Then connect the PositionChanged signal. I'm connecting also the Geoclue.Position, but
     // so far it has never been triggered.
     // Note that after cold-start it may take a long while before you start getting position fix,
     // especially if you are indoors.
    QDBusConnection::sessionBus().connect("org.freedesktop.Geoclue.Position",
                                          "/org/freedesktop/Geoclue/Position",
                                          "",
                                          "PositionChanged", this, SLOT(positionChangedDBUS(QDBusMessage))); 
    QDBusConnection::sessionBus().connect("org.freedesktop.Geoclue.Providers.Hybris",
                                          "/org/freedesktop/Geoclue/Providers/Hybris",
                                          "",
                                          "PositionChanged", this, SLOT(positionChangedDBUS(QDBusMessage)));
}

// The message slot. This only spits out the data, parsing is up to you.
void PositionSource::positionChangedDBUS(QDBusMessage msg)
{
     // expecing int,int,double,double,double - flags (which data is valid), time, lat, lon, altitude

    QList<QVariant> list = msg.arguments();

    qDebug() << "PositionChanged:" << msg;
}

If you monitor the Geoclue.Position interface, there seem to be messages being sent but they certainly aren't being received by this code. No idea why.

Also note that you should also call RemoveReference for Providers (and possibly for client) when you're done (so in your adapter destructor). Unfortunately there is no way to explicitly tell GeoClue (as in client or provider) that you're done and it should shut down (at least no documented way on DBus interfaces) - RemoveReference only tells it that it may shut down if it pleases it to do so. On phone it appears that even after asking interface to close the GPS stays active even when no one is using it, eating battery. Kinda stupid interface design if you ask me. 

The code above should be runnable on the phone, but may not be in emulator (I didn't actually try, oh well). Since this is untested copy-paste from my code there may be some errors, sorry about those in advance.

Now, looking back at that mess I can make an educated guess why Jolla folks haven't been exactly forthcoming with this information, as this pretty much is accessing very very unofficial and possibly undocumented subsystems for location information. In this context this means that it may vanish without warning, but until QtPositioning rolls in, I unfortunately don't really see another (good) way to do this.

Update:
It seems that you can actually skip GeoClue master/clients completely (everything up to (down to?) "PositionStart" call in above code) and only create/connect to HybrisInterface. This seems to make position information lock slower (may take several minutes, up from 20 seconds or so I experience earlier while inside), but then RemoveReference on shutdown will actually stop GPS (well, make the icon go away at least) and hopefully also stop excessive battery drain after shutdown.
 

tiistai 22. huhtikuuta 2014

Software guy in FPGA land

I have to admit it, I am primarily a software guy, have always been. I can take a random chip, look through its datasheet, build connecting electronics around it and make it dance with software (with some assistance from suitable MCU of course). But if you reverse the situation - that is, if I need to make a hardware module to do the dancing (in this context I mean FPGA) I'm lost. I am familiar enough with basics, but to actually implement something relatively simple (say, a simple controller that can take data from outside, store it in internal memory and run a sequence based on data) I seem to be facing a very steep cliff.

For example this little thing. Pen for scale; actual board size is 60x60mm (JTAG wires you can see behind the board go to small helper board I put in there to make development a bit easier).














I've had this sitting on my desk for almost a year now (mostly because the projects that actually do pay the bills have been a priority). This is an 8x8 RGB led matrix. What I hope makes it interesting is the fact that it is self-controlled, chainable (you can in theory chain dozens if not hundreds of these together in any shape you want, based on your current need) and it is trivially controllable by even tiniest of the MCUs (say, the PIC12 I wrote about earlier - with a little help from a shift register to extend output pin count, but an Arduino with simple adapter shield should do nicely).

The idea is that you "pre-load" data in by clocking RGB data (each component separately, with up to 10 bits in parallel for each; so loading first to LEDs is R10 - dataclock - G10 - dataclock - B10 - dclock - R10 - dclock - G10 ... and so on). Timing requirements are not strict so you can take your time calculating next value between data clocks. When you have your entire matrix loaded with data (that is, every LED in every module you have in chain), you can signal them all to switch data to new with "flip" signal pulse. So essentially you can load an image to them, flip, load new image (and you can take all the time you want), and flip again - no jitter, just instant image change. Very very simple. (some details omitted, they aren't that important right now)

This takes in 5v input (though I already found out that it can tolerate 12v, for short periods at least, it just gets really hot - that should teach me to use same power source for different projects and then forget to change) and with every LED at maximum brightness (white) single module uses about 1,5A. Typical use of course would be less, directly proportional to overall brightness.

Now, as you might have guessed, "the dance" here is ability to drive all the LEDs, load new data in background and then load new current scaler values when needed. Since I had some spare time now, I started with VHDL again (it was a long time in between, so even basics needed a quick refresh), and actually have made some progress. That is to say, it won't work. Something fishy when trying to access internal RAM. The fetch process itself appears to be running nicely, just the bits in RAM refuse to come out.

But at least it seems that during the period of inactivity the background processes in my head haven't been idle - when last working with it I was completely stumped on how to build process to access the RAM, now it seemed to be crystal clear from start.

Except that "doesn't work" part. But I'm working on it.