Oct 17

Law Abiding Citizen

A few weeks ago, I came across this comment on Reddit about Law Abiding Citizen, and how some people think that the ending was bad.  So I would just like to say that first of all, I do like the ending as it stands(see the parent comment).  It fits with the movie, especially since earlier in the movie Clyde explicitly told Nick that his objective wasn’t to kill him, it was to teach him a lesson.  It’s a bit hard to teach somebody a lesson if they are dead!

However, the two alternative endings are interesting, so here are some thoughts on how those might play out:

The same ending happens, but during the meeting with the city officials the Mayor basically sanctions higher ups to stop Shelton by any means necessary because of how politically damaging it is becoming. She basically gives the go ahead to have them kill him and make it look like an accident, but unbeknownst to them the same feed Shelton was watching in prison is being live-streamed to media new outlets around the world, thereby showing the world that the people that swore to uphold justice will wilfully abandon their morals to save themselves, thus “bring the whole fuckin’ diseased, corrupt temple down…”.

This would be kinda cool, in a revenge sort of way, to perhaps show that corruption goes all the way up.  But I don’t really see how this could be a good ending with teaching Nick a lesson – I think it would have to end with the feed going out, but the bomb still going off, to show that once you break the rules there are consequences.

The original ending plays out the same, except at the end Foxx is sitting at his daughters recital pleased as punch that he beat Butler, even though it was by straight up murdering him letting him die, and his tie suddenly tightens and chokes him to death (the same method that was foreshadowed by the CIA agent earlier in the film). Clyde still dies, but Foxx learns that even the DA is not exempt from ‘action without consequence’ so it’s a little easier to swallow.

So what would also make this very cool would be to have an ending similar to Inception.  You don’t show the actual act, you have the tie start to visibly tighten and then show Nick’s hand going up to his neck to play with the tie – and then cut out. Again though, I don’t think that this fits with the theme of teaching Nick a lesson, since it’s hard to teach him a lesson if he’s dead.  It would be a cool ending though.

Apr 28

English sentences and punctuation

Barbara Bush died a few days ago, and The Onion had this to say about it:

Barbara Bush Passes Away Surrounded By Loved Ones, Jeb

This got me thinking a bit, how can we change the meaning of this sentence just by making some very minor edits to it?  As it stands right no, the comma at the end of the headline make two different groups, Barbara Bush’s loved ones and Jeb.  These groups are separate, and the headline would be the same if the comma was replaced with an ampersand(&).  What happens if we change the comma to a colon though?

Barbara Bush Passes Away Surrounded By Loved Ones: Jeb

As a headline in this case, this is saying that Jeb stated Barbara passed away.  There’s no relationship between Jeb and her loved ones.  Now what would happen if we add more people to the end?

Barbara Bush Passes Away Surrounded By Loved Ones: Jeb, George

By having more than one person here, we are now defining who the loved ones are of Barbara.  At least that’s what first comes to mind for me.

 

Anyway, I just thought that this was interesting.  And quite possibly confusing to people who are just learning English, as the punctuation makes a big difference in this case.

Apr 09

Bitcoin Mining for a Useful Purpose?

So I was thinking about this the other day when I came across this article on Slashdot that points out that GPU prices are high due to the demand for Bitcoin(and other cryptocurrencies) mining.  This got me thinking, what’s the point for this?  What if we could do something useful(well, more useful) than mining for virtual currency?  I’ve been running BOINC for probably about 12+ years now, doing calculations for SETI@Home.  Originally, I wasn’t even using the BOINC client, SETI@Home had their own standalone software that has now been superseded by BOINC.  Which given that the original software was used until 2005, means that I have probably actually been doing this for 15+ years at this point(logging into the SETI website indicates I have been a member since December 2005)…

But I digress.  The question really is, could we mine cryptocurrency as part of the normal BOINC process?  It seems like this would have a number of benefits for people:

  • For mining people, they can still mine coins
  • For projects on BOINC, they gain computing power from people wanting to mine coins at the same time
  • This could result in more computing power for a “good” cause as well, instead of what is(in my mind at least) a rather useless endeavor

I’m not exactly sure how this would work, as I don’t really know anything about blockchain.  Could perhaps Ethereum be used to provide people with “compute credits” that would allow this scheme to work?  It could also provide a good way of storing the calculation results, and have them verifiable.

Feb 19

Intergalactics Source Code

Does anybody out there have the original source code to the Java game Intergalactics?  I was able to pull the (compiled) client off of SourceForge, but without a server it’s not too useful.  I did start updating the client to work properly over the summer along with a new server implementation, but it would still be interesting to get all of the original source code.

Anyway, if you do happen to have the original code, I would be grateful.  Intergalactics was always a nice fun timewaster.  It wasn’t too complicated but it did require a certain amount of strategy.

Dec 09

APT Repo is now live

Today, I created an APT repo for my projects.  At the moment, this hosts only CSerial, however the intention is to put some other projects up at some point.  Note that because CSerial is built as both amd64 and armhf in the same repository, you may need to give the exact version to APT when installing: apt-get install cserial-dev=version

Versions can be seen by using the following APT command: apt-cache policy cserial-dev

There are actually two APT repos: one for nightly builds, and one for the releases.  As of right now, nothing is in the releases, as I need to fix a few bugs before that happens.

Everything in these APT repos is built from Jenkins.

The main website can be seen here: http://apt.rm5248.com/

Sep 03

The Demise of Juicero

As you may have heard recently, Juicero is shutting down.  While not entirely unexpected, their business model just seemed insane to start with.  As recounted in some of the Slashdot comments, Juicero went through $100+ million dollars in funding.

This brings up an obvious question:

HOW DO YOU SPEND THIS MUCH MONEY?

Really.  Over 100 million dollars to create a device that does nothing but squeeze juice?  Give me only ten million and I will fail faster for you!  I’m not quite sure what these guys were doing with all that money(although AvE’s video seems enlightening), but I’m beginning to think that they were simply trying to go too far at once.  Instead of making a small, feasible product at first, they went and sunk a whole lot of money into design and not a whole lot into making an actually reasonable device.  This is just insane the amount of money spent on this.

From the VC point of view, probably what they were thinking is “continuous revenue stream”, which would be reasonable from their view of getting money back.  While the premise may have good, the actual execution was very lacking.  After all, “aim for the stars, hope not to get the exact polar opposite of what you were actually trying to accomplish.”

Jul 21

NTP Woes

For the past year or so, I’ve been battling trying to get NTP fed from GPSD.  This has proven to be somewhat harder than I imagined.  GPSD is supposed to feed NTP directly from shared memory, however this was not happening.  I haven’t been trying to do this the entire time, but it’s been a problem for at least a year!

The simple situation is as follows: I have a device that has a GPS receiver on it in order to get the time.  NTP is also running to sync the time whenever it connects to the internet(for most of the time, we are not on the network).  This is also a very vanilla Debian 8 (Jessie) system on an ARM processor, so we’re not custom-compiling any of the standard packages.  The GPS is also a hotplug, so we have a udev rule that calls gpsctl with the proper TTY when the USB is activated:

(udev match options here) SYMLINK+="gps%n", TAG+="systemd", ENV{SYSTEMD_WANTS}="gpsdctl@%k.service"

According to all of the literature on the web, we should just be able to do this by adding the following to /etc/ntp.conf:

#gpsd SHM
server 127.127.28.0 prefer
fudge 127.127.28.0 refid GPS flag1 1

(note that we are setting flag1 here, as the system that this is running on has no clock backup).

This allows NTP to read from a shared memory address that is fed by GPSD.  You can check this with ntpq -p:

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 SHM(0)          .GPS.            0 l    -   64    0    0.000    0.000   0.000
-altus.ip-connec 193.11.166.20    2 u    7   64    1  189.620    6.525   5.288
+ks3370497.kimsu 131.188.3.222    2 u    5   64    1  186.252   17.282  14.504
+head1.mirror.ca 195.66.241.10    2 u    5   64    1  186.503   15.792  14.691
*de.danzuck.eu   192.53.103.103   2 u    4   64    1  155.953    8.786  13.366

As you can see, in this situation there is no connection to the SHM segment, but we are synced with another NTP server.  However, we can verify that GPSD is running and getting GPS data by running the ‘gpsmon’ program(in the ‘gpsd-clients’ package).

The other important thing to note about the SHM segement is that the ‘reach’ value is always 0, and will never increase.  You can also check the output of NTP trying to reach it with:

 ntpq -p 127.127.28.0

This was very confusing to me: how are we not talking with the SHM segment?  This would also seem to work on some systems, but not other systems.  No matter how long I left it running, NTP would never get any useful data from the SHM segment.  Finally, I stumbled across a link, which I can’t find now, that said that GPSD must be started before NTP.  I then tried that on my system, by stopping my software(which is always reading from GPSD), stopping NTP and then stopping GPSD.  I then started GPSD, NTP, and my software(which will also initialize the GPS system to start sending commands).  This causes NTP to consistently sync with GPSD.

Do this like the following:

$ systemctl stop your-software
$ systemctl stop ntp
$ systemctl stop gpsd
$ .. make sure everything is dead..
$ systemctl start gpsd
$ systemctl start ntp
$ systemctl start your-software

For reference, here’s the ntp.conf that I am using(we only added the SHM driver from the standard Debian install):

# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help

driftfile /var/lib/ntp/ntp.drift


# Enable this if you want statistics to be logged.
#statsdir /var/log/ntpstats/

statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable


# You do need to talk to an NTP server or two (or three).
#server ntp.your-provider.example

#gpsd SHM
server 127.127.28.0 prefer
fudge 127.127.28.0 refid GPS flag1 1

# pool.ntp.org maps to about 1000 low-stratum NTP servers.  Your server will
# pick a different set every time it starts up.  Please consider joining the
# pool: <http://www.pool.ntp.org/join.html>
server 0.debian.pool.ntp.org iburst
server 1.debian.pool.ntp.org iburst
server 2.debian.pool.ntp.org iburst
server 3.debian.pool.ntp.org iburst


# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
# details.  The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions>
# might also be helpful.
#
# Note that "restrict" applies to both servers and clients, so a configuration
# that might be intended to block requests from certain clients could also end
# up blocking replies from your own upstream servers.

# By default, exchange time with everybody, but don't allow configuration.
restrict -4 default kod notrap nomodify nopeer noquery
restrict -6 default kod notrap nomodify nopeer noquery

# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1
restrict ::1

# Clients from this (example!) subnet have unlimited access, but only if
# cryptographically authenticated.
#restrict 192.168.123.0 mask 255.255.255.0 notrust


# If you want to provide time to your local subnet, change the next line.
# (Again, the address is an example only.)
#broadcast 192.168.123.255

# If you want to listen to time broadcasts on your local subnet, de-comment the
# next lines.  Please do this only if you trust everybody on the network!
#disable auth
#broadcastclient

TL;DR Having trouble feeding NTP from GPSD when you have a good GPS lock?  Make sure that GPSD starts before NTP.

Apr 09

QTest Project Setup

Recently, I was looking into how to setup a Qt project with unit tests.  The Qt-esque way to do this is to use the QTest framework within Qt in order to do this.  While not a bad framework, the problem is that there isn’t a good way to integrate it within your project.  What I mean with that is that you must link with the QTest library and have a special main() method in order to run the tests.  This brings up two problems:

  1. How do we run the tests if we have only one executable?
  2. How do we only link with QTest at certain times(e.g. we don’t want to link with QTest when we send the executable out)

Searching for a solution to the problem, one thing that some people did was to create a .pri file with the source files to compile into two projects: one for the main application, and one for the unit tests.  The disadvantages to this are that it makes it hard to work with Qt Creator to add in the files, as it can’t add them in automatically to the SOURCES and HEADERS list.  So that’s not good.

The other solution that I came across was to add in the files to each project.  However, this adds in a lot of overhead, and you must be sure to add in the files to both projects when something changes.  So that’s not good either.

The solution that I came up with was to have three separate projects:

  • One project for the main code of our project.  This gets built as a static library.
  • One project to run the main code of our project.  This is the normal executable.
  • One project to run the unit tests.  This links with QTest, and doesn’t get installed by default.

This is basically the same project setup as described here, although it wasn’t until after I had created my project that I realized it was the exact same thing(I did come across the link at first, but didn’t understand it at the time since it wasn’t using QTest).

With this project setup, you can edit the main code in Qt creator, do anything that you want, and still have everything link and test in a clean manner(no need to link with QTest in your main executable!)

The code for the same project is up on github, to give you a general overview of how it all fits together.

Feb 04

Microchip Harmony and Bootloaders

I’ve been messing around with a Digilent Max32, and have been using Microchip’s MPLAB Harmony framework to program the device.  The framework is rather nice, but it can be a little confusing at times.  It took me a while to figure out how to work the bootloader on it, so this post will go into how to setup your projects.

Prerequisites:

  1. PIC32 based device.  In our case, this will be the Max32, but any PIC based device should work fine.
  2. MPLAB X, Microchip’s dev platform based on Netbeans.
  3. Microchip XC32 compiler.  This should be a part of your MPLAB X install, but if not you can download it from Microchip’s website.  I am using version 1.42.
  4. PIC Programmer.  I have an ICD3, but it should be possible to use a PICKit programmer as well.

Part I: Install Harmony

Before we can mess around with Harmony, we need to install the latest version.  In our case, we will be using the current beta version of 2.0.

  1. Download the new Harmony Configurator from Microchip’s website.
  2. Go to the ‘Downloads’ tab, and download the proper version for your system

    Step 1 and 2 – Download Harmony and Configurator

  3. Run the installer for Harmony.  Make sure that you remember where you installed it, you will need this information later.
  4. In MPLAB X, go to Tools->Plugins.

    Plugins location

  5. Go to the ‘Downloaded’ tab
  6. Click ‘Add Plugins’
  7. Browse to where you downloaded the Harmony plug-in to, and select it.

    How to install the downloaded plugin

  8. The plugin will now show up in your Plugins window.  Click the ‘Install’ button.
  9. The plugin will install.  Once it does, you will have to restart MPLAB X.

Part II: Create Bootloader project

Note that before you come here, you must have MPLAB X Harmony and the proper Harmony plugin installed.

  1. Create a new project by going to File->New Project.
  2. Select ’32-bit MPLAB Harmony Project’ and click ‘Next’

    Basic project configuration

  3. Fill in all of the information on this screen.  Don’t forget to set the PIC device that you are using.
  4. If the Harmony configurator does not open up for you automatically, go to Tools -> Embedded -> MPLAB Harmony Configurator

    Open up the Harmony Configurator if it closes

  5. Under the ‘Application Configuration’ section, we want to create an application(we will call it max32_bl) and click ‘Generate application code for selected Harmony components’.  We want to generate code for the bootloader in this area.

    Bootloader configuration #1

  6. Under the ‘Harmony Framework Configuration’ section, select ‘Bootloader Library’.  We will be using the USART bootloader.  Under the ‘Bootloader or Applicaton?’ section, select ‘Bootloader’.  Also select ‘Ports’ under ‘System Services’

    Bootloader configuration #2

  7. Click the ‘Generate Code’ button on the Configurator screen.  We will have a number of new C/H files for us to edit.  Also, there is now a custom linker script for us under the ‘Linker Files’ folder.
  8. Now that code has been generated, there are a few things that we want to do to make it clear what is happening.  First, we don’t need the legacy bootloader options.  So under ‘Header Files’, go to app/system_config/default/system_config.h, and comment out the preprocessor macros BOOTLOADER_LEGACY and BTL_SWITCH

    Delete/comment out these macros

  9. The first thing for us to edit in the code is to open up our max32_bl.c file.  This file contains generated code for us to modify.  The first thing is that we need to move the line that says
    BOOTLOADER_ForceBootloadRegister(MAX32_BL_Bootloader_ForceEvent);

    to be in the

    MAX32_BL_Initialize

    function.  Otherwise, the bootloader code will not call our ForceEvent function.

  10. Now, let’s add a splash screen.  For now, we can simply add a simple function to print out to the UART, and then call that function once in the MAX32_BL_Tasks function, in the MAX32_BL_STATE_INIT case statement of our switch.  Here’s the simple UART printing function:
    static void writeStringToUART( const char* string ){
     int pos = 0;
     
     while( string[ pos ] != 0 ){
     while( DRV_USART0_TransmitBufferIsFull() ){}
     DRV_USART0_WriteByte( string[ pos++ ] );
     }
    }
  11. You should now be able to program your device with the bootloader.  Open up a terminal with a terminal emulator such as Putty, and if you have done everything correctly you should see a splash screen whenever you reset the processor.  On the MAX32, this is accomplished by pressing the reset switch.
  12. Let’s also make sure that we can get to the bootloader manually.  To do this, we will have to configure one pin on the chip as a GPIO input, with a pull-up resistor.  Go back to the Harmony Configurator screen, and go to the ‘Pin Settings’ tab.

    Pin settings

  13. Choose a pin to use as an input.  In my case, I chose RG6.  This corresponds to pin 52 on the Max32 board.  I will also enable the pull up resistor on this pin, so that when the pin is shorted to ground the bootloader will start.
  14. Go back to our max32_bl file, and modify MAX32_BL_Bootloader_ForceEvent to look like the following(change your pin if you used a different one).
    int MAX32_BL_Bootloader_ForceEvent(void)
    {
     int rg6 = PLIB_PORTS_PinGet (PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_6);
     
     if( !rg6 ){
     writeStringToUART( "Button held, forcing bootloader\n" );
     return 1;
     }
     
     /* Check the trigger memory location and return true/false. */
     if (*(uint32_t *)MAX32_BL_BOOTLOADER_TRIGGER_MEMORY_ADDRESS == 0xFFFFFFFF)
     return (1);
     else
     return (0);
    }
  15. Build and re-flash your device.  When you short pin RG6 to GND, the string “Button held, forcing bootloader” should now print out on your console when the bootloader starts.

Here’s the entire file for reference:

/*******************************************************************************
  MPLAB Harmony Application Source File
  
  Company:
    Microchip Technology Inc.
  
  File Name:
    max32_bl.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It 
    implements the logic of the application's state machine and it may call 
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files 
// *****************************************************************************
// *****************************************************************************

#include "max32_bl.h"

#include <stdio.h>

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.
    
    Application strings and buffers are be defined outside this structure.
*/

MAX32_BL_DATA max32_blData;
#define MAX32_BL_BOOTLOADER_TRIGGER_MEMORY_ADDRESS					0x9D000000		

static void writeStringToUART( const char* string ){
    int pos = 0;
    
    while( string[ pos ] != 0 ){
        while( DRV_USART0_TransmitBufferIsFull() ){}
        DRV_USART0_WriteByte( string[ pos++ ] );
    }
}

static void writeIntAsCharToUART( int i ){
    while( DRV_USART0_TransmitBufferIsFull() ){}
    DRV_USART0_WriteByte( i + 48 );
}

static void waitForUARTFlush(){
    while( !PLIB_USART_TransmitterIsEmpty( USART_ID_1 ) ){}
}

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************
/******************************************************************************
  Function:
    static void MAX32_BL_Bootloader_ForceEvent (void)
    
   Remarks:
    Sets a trigger to be passed to force bootloader callback.
	Run bootloader if memory location == '0xFFFFFFFF' otherwise jump to user 
	application.
*/ 
int MAX32_BL_Bootloader_ForceEvent(void)
{
    int rg6 = PLIB_PORTS_PinGet (PORTS_ID_0, PORT_CHANNEL_G, PORTS_BIT_POS_6);
    
    if( !rg6 ){
        writeStringToUART( "Button held, forcing bootloader\n" );
        return 1;
    }
    
    /* Check the trigger memory location and return true/false. */
    if (*(uint32_t *)MAX32_BL_BOOTLOADER_TRIGGER_MEMORY_ADDRESS == 0xFFFFFFFF)
        return (1);
    else
		return (0);
}

/* TODO:  Add any necessary callback functions.
*/

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************


/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void MAX32_BL_Initialize ( void )

  Remarks:
    See prototype in max32_bl.h.
 */

void MAX32_BL_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    max32_blData.state = MAX32_BL_STATE_INIT;

    
    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
    BOOTLOADER_ForceBootloadRegister(MAX32_BL_Bootloader_ForceEvent);
}

static void printSplash(){    
    writeStringToUART( "MAX32 Bootloader\n" );
    writeStringToUART( "Version " );
    writeIntAsCharToUART( MAJOR_VERSION );
    writeStringToUART( "." );
    writeIntAsCharToUART( MINOR_VERSION );
    writeStringToUART( "\n" );
    writeStringToUART( __DATE__ );
    writeStringToUART( " " );
    writeStringToUART( __TIME__ );
    writeStringToUART( "\n" );
    
    waitForUARTFlush();
}

/******************************************************************************
  Function:
    void MAX32_BL_Tasks ( void )

  Remarks:
    See prototype in max32_bl.h.
 */

void MAX32_BL_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( max32_blData.state )
    {
        /* Application's initial state. */
        case MAX32_BL_STATE_INIT:
        {
            bool appInitialized = true;
       
        
            if (appInitialized)
            {
            
                max32_blData.state = MAX32_BL_STATE_SERVICE_TASKS;
                
                //print splash screen.  this will happen only once
                printSplash();
            }
            break;
        }

        case MAX32_BL_STATE_SERVICE_TASKS:
        {
        
            break;
        }

        /* TODO: implement your application state machine.*/
        

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}

 

/*******************************************************************************
 End of File
 */

Part III: Create our main program

Now that we have our bootloader setup, we need to create the main program that will get loaded by the bootloader.

  1. Create a new project by going to File->New Project.
  2. Select ’32-bit MPLAB Harmony Project’ and click ‘Next’
  3. Fill in all of the information on this screen.  Don’t forget to set the PIC device that you are using.
  4. If the Harmony configurator does not open up for you automatically, go to Tools -> Embedded -> MPLAB Harmony Configurator
  5. Under the ‘Application Configuration’ section, we want to create an application(we will call it max32_program) and click ‘Generate application code for selected Harmony components’.  We want code for the Timer and USART to give us some code to work with.

    Main program configuration #1

  6. Under the ‘Harmony Framework Configuration’ section, select ‘Bootloader Library’.  We will be using the USART bootloader.  Under the ‘Bootloader or Applicaton?’ section, select ‘Application’

    Main program configuration #2

  7. Under the ‘Harmony Framework Configuration’ section, also make sure that you have drivers for the timer and USART 0 selected.  The USART should be running at the same baud rate as the bootloader.
  8. Go to the ‘Pin Settings’ page as we did before.  For the MAX32, pin RC1 is an output that drives an LED.  We will use RG6 as an input as we did before on the botloader.  Setup those settings.

    Pin diagram for the main program

  9. Click ‘Generate code’
  10. Your project is now created with some basic information.  Since we set up our timer to use interrupts, we now have a TimerCallback function in mainapp.c.  Let’s modify it to toggle the RC1 LED every time the timer is called.  The code will now look like this:
    static void TimerCallback ( uintptr_t context, uint32_t alarmCount )
    {
     static int state = 0;
     PLIB_PORTS_PinWrite (PORTS_ID_0, PORT_CHANNEL_C, PORTS_BIT_POS_1, state);
     state = !state;
    }
  11. Build your project.  The hex file that is generated is what you want to send to the bootloader.  Note that this hex file can’t be sent as-is, you must convert it to binary and use Microchip’s protocol.  See the next section for some discussion.

Part IV: Bootloading

Now that we have our bootloader and a program, we should try to actually load information onto the device using the bootloader.  To do this, we will need a program to write the information.  You can use either Microchip’s version in AN1388, or I wrote a version that is cross-platform compatible using my CSerial library.

Whichever method you use, once you have built the actual program you need to send the hex file across to get the bootloader to write the data.  If everything has gone correctly, you will then be able to re-set the board and have your application running.

One more tip: If you can program the entire chip at once(e.g. you have an ICD3), if you set the bootloader project as a loadable of your main project you can flash both projects to the chip at the same time.  Since they get flashed in different locations, there’s no conflict.  Note that this won’t work with the lower-end programmers.

 

This tutorial probably skims over a few steps, but it should at least be enough to get people started and working with Harmony and its bootloader.  Questions? Add a comment and I will see about expanding upon either this post or a later one.

Jan 21

Thoughts on Star Wars and Jedi

So I saw Rogue One last week, and I found it to be quite interesting.  It wasn’t my favorite movie, but it was a good lead in to A New Hope.  Once I got back home, I had to look up the crawl for A New Hope, which of course I did on TV tropes.  Looking at the TV tropes page for A New Hope, there is this one section that I feel is somewhat out of place:

  • Admiral Motti’s description of the Force as a “sad devotion to that ancient religion” seems downright bizarre, given that its existence was treated as common knowledge in the Prequel Trilogy, a timeframe in which Motti would likely have been alive (albeit very young). This is largely because when the film was written Lucas envisioned exact knowledge of the Force and Jedi powers to be something which only a select few had knowledge of, which was gradually contradicted by the Expanded Universe novels and comics, and then jettisoned altogether by The Phantom Menace. Some later novels, such as the Republic Commando novels, took some steps to try and square the two perspectives, but with limited success.

The “sad devotion to that ancient religion” actually seems like it could be a plausible thing for him to say, even though the bullet point goes on to say that this was contradicted with later works.  Why would this work?  Well, let’s do some basic math here and get some rough estimates of how many people there are.

First order of business: How many Jedi are there?  The movies don’t say for certain, but the Jedi temple seems to be quite large.  Making grand assumptions here, let’s also assume that it is large enough to fit every Jedi at once in it.  Given that it seems to encompass an entire city block at least, let us say that the Jedi temple can fit 100,000 people.  (According to scifi.stackexchange.com, there were about 10,000 Jedi at the time of Order 66).  Regardless, 10,000 vs 100,000 Jedi will make no difference here in a moment.

Next question: How large is Coruscant?  Assuming that it is the same size as Earth, and has a population density at least as high as the highest city on Earth(according to Wikipedia, that is Manila at 41,515 people/km²).  According to Wolfram|Alpha, the Earth is 5.1×10^8 square kilometers.  Now, multiplying these two numbers together we get a population of ~2.1×10^13.  According to Wookieepedia, there is more than 1 trillion(1×10^12) people on Coruscant.  If I am doing the math correctly here, my estimate for the number of people on Coruscant is (one order of magnitude * 2 ) from what Wookiepedia says.

Now that we have our numbers(both unofficial and estimated), let’s do some quick math here to figure out about how many Jedi there are per-person on Coruscant.

Number of Jedi Population of Coruscant People-per-Jedi
10,000 1×10^12 100,000,000
10,000 2.1×10^13 2,100,000,000
100,000 1×10^12 10,000,000
100,000 2.1×10^13 210,000,000

Now, obviously these numbers are rather rough estimates.  But at a minimum, there are ten million people on Coruscant per Jedi!

Now, back to the original question: Why is the statement “sad devotion to that ancient religion” completely plausible in my mind?  Because given the ratio of people to Jedi on Coruscant alone, it is likely that you could go an entire lifetime without seeing a real Jedi.  Don’t forget as well, there are more planets than just Coruscant.  Basically, the number of Jedi for the population of the galaxy is laughably small.  If you combine the lack of population with potentially a good PR campaign, it is completely plausible that a person could grow up in the galaxy and never see a Jedi, only hear about them, and then be convinced that Jedi are bad people who were controlling the fate of the galaxy in their hands and/or they were just pretending.  Reportedly, there was a minister in Pakistan who fooled the entire government for 6 years that he wasn’t an actual minister(note: I can’t find any other sources to this from Western media, so I don’t know the veracity of this).

So, to conclude: It is reasonable to assume that because there were so few Jedi for the entire population of the galaxy, any effort to discredit them could be very effective at wiping their knowledge from the population’s memory.