Pen + LEDs = ???

Image

My roommate happened to throw out a broken pen this morning. I looked at it and thought I might be able to fix it, so I decided to save it from the trash. After taking it apart, it struck me that the blue grippy part might look cool lit up with an LED.

Image

Image

I took a random 10mm LED and stuck it in the back, and it fit perfectly. Now, I kinda want to turn this into a keychain light. I have an orange LED (for school spirit) and a bright white LED (for usefulness).

Image

My question to you is: which one should I use? They both look cool and I can’t decide which I like more. Here are some more cellphone photos for your viewing pleasure.

Image

Image

Image

Image

Google Docs and QR Codes

Google Docs is great. It allows you to create whatever you want and store it on the cloud so that you can edit it anywhere. Earlier today I needed to input a list of around 30 contacts from a Google spreadsheet into my phone. I did about 4 and then realized I really didn’t want to spend the next hour typing names and numbers. I did some googling and found a few references to embedding QR codes in spreadsheets, but none of them could be used for contacts (vCard format). It turns out that if I take the code that I found, it can be fairly easily modified to allow for vCards. First, I used an online QR code generator to make a sample contact code. This let me understand the format of a vCard.

Image

After a bit more wikipedia-ing and some research on html/url formatting, I rewrote the spreadsheet equation. When I entered it into a sample contact list, it worked!

Image

What’s great is that each code automatically updates as soon as one of its source cells is changed. For example, in the screenshot above, Carlos Danger doesn’t have an email address. After adding one, tho, his QR code automatically updates.

Image

Ultimately, this saves a load of time for anyone who needs to put a lot of contacts into their phone. It’s super easy to use, and it looks pretty! Pair it with Google Goggles and you’ve just freed up some time to go and do some other awesome thing. I might come back and explain this more in the future, but I’m quite busy with classes and, as always, really lazy. Here’s the code, tho, and please feel free to modify it however you like to make your spreadsheets that much more futuristic.

Example spreadsheet: Google Docs QR Contacts

YouTube video: Google Docs and QR Codes

=image("https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=BEGIN:VCARD%0AN:" & A2 & "%20" & B2 & "%0ATEL;CELL:" & C2 & "%0AEMAIL:" & D2 & "%0AEND:VCARD")

Dymaxion

Dymaxion is a form of polyphasic sleep where the user sleeps for a half hour (30 minutes) every 6 hours. For those of you who know calculus that means that the user sleeps for two hours out of every 24-hour period. The reason it works is that you basically trick your body into falling instantly into REM sleep. This means that you would ideally get two full hours of REM sleep a ‘day’. In a normal monophasic sleeping schedule the sleeper usually gets only 1.5 hours of REM sleep a night, so this is obviously an upgrade. While it is unclear what the other phases of sleep are actually good for, there is always the possibility that I might just drop dead some day because of sleep deprivation. I decided to start dymaxion about a week ago, and I’ve been keeping a simple text log of each nap and how they went. Here are the first 8 days:

			--------- Sleep Log ---------

_____________________________________________________________________________

Tuesday, May 28, 2013 - Day 1
	11:00-11:30 - Nap 1
		Minutes of sleep: 0
		Thoughts: N/A
	17:00-17:30 - Nap 2
		Minutes of sleep: 0
		Thoughts: N/A
	Summary:
		Total minutes of sleep: 0
		Thoughts: I had a strange schedule today because inductions were at 12:00
 		and then I had to go to the fab lab at 18:00. Slept a normal night, woke
 		up around 09:00, then took my first 'nap' at 11:00.

_____________________________________________________________________________

Wednesday, May 29, 2013 - Day 2
	00:00-00:30 - Nap 1
		Minutes of sleep: 0-15
		Thoughts: First time I may have slept. Not too tired, but at least it was
 		dark.
	06:00-11:30 - Nap 2
		Minutes of sleep: 330
		Thoughts: By the time it got to ~05:45 I was so tired I was nodding off. I
 		fell asleep like a rock at 06:00, and didn't wake up until 5.5 hours
 		later. My mom actually checked in on me several times and even though she
 		knew I should be awake she decided not to help me wake up. Thanks mom.
	12:00-12:30 - Nap 3
		Minutes of sleep: 0
		Thoughts: Pointless, as it was right after I slept in.
	18:00-18:30 - Nap 4
		Minutes of sleep: 0
		Thoughts: N/A
	Summary:
		Total minutes of sleep: 330-345
		Thoughts: Today was sort of a failure…and I'm quite tired.

_____________________________________________________________________________

Thursday, May 30, 2013 - Day 3
	00:00-00:30 - Nap 1
		Minutes of sleep: 0-15
		Thoughts: I don't think I slept at all.
	06:00-06:30 - Nap 2
		Minutes of sleep: 15-30
		Thoughts: Actually slept a lot!
	12:00-12:30 - Nap 3
		Minutes of sleep: 0
		Thoughts: N/A
	18:00-18:30 - Nap 4
		Minutes of sleep: 0
		Thoughts: N/A
	Summary:
		Total minutes of sleep: 15-45
		Thoughts: No mistakes today, and I actually slept some!

_____________________________________________________________________________

Friday, May 31, 2013 - Day 4
	00:00-00:30 - Nap 1
		Minutes of sleep: 0-15
		Thoughts: I might not have slept at all.
	02:00-05:00 - Nap 2
		Minutes of sleep: 180
		Thoughts: After Nap 1 I sat on the couch listening music and eating
 		cereal. I was really tired and couldn't think of anything to do, and I
 		guess I fell asleep somewhere around 02:00 with iTunes on shuffle. I woke
 		up at 05:00 when my mom came down stairs. I woke up instantly upon hearing
 		her coming down, and only realized I had been sleeping because I couldn't
 		remember the last 3 hours.
	06:00-06:30 - Nap 3
		Minutes of sleep: 0-15
		Thoughts: I might not have slept at all.
	12:00-12:30 - Nap 4
		Minutes of sleep: 0
		Thoughts: N/A
	18:00-18:30 - Nap 5
		Minutes of sleep: 0-15
		Thoughts: I don't think I slept at all.
	Summary:
		Total minutes of sleep: 180-225
		Thoughts: Overall I was very awake today. While I did have the extra nap,
 		I had an easier time sleeping after it.

_____________________________________________________________________________

Saturday, June 1, 2013 - Day 5
	00:00-00:30 - Nap 1
		Minutes of sleep: 5-20
		Thoughts: Probably some of the most sleep I've gotten in a half-hour nap.
 		Woke up and was wide awake and slightly more invigorated.
	06:00-07:00 - Nap 2
		Minutes of sleep: 60
		Thoughts: Fell asleep without earbuds, didn't hear alarm until mom woke me
 		up at 07:00.
	07:00-10:30 - Nap 3
		Minutes of sleep: 210
		Thoughts: After waking up at 07:00 I set my alarm for 07:30 and told
 		myself I'd sleep another half hour. Forgot to put earbuds in.
	12:00-12:30 - Nap 4
		Minutes of sleep: 0-15
		Thoughts: I might not have slept at all.

	Summary:
		Total minutes of sleep: 275-305
		Thoughts: I need to A) remember to use earbuds and B) get out of bed as
 		soon as I wake up.

_____________________________________________________________________________

Sunday, June 2, 2013 - Day 6
	00:00-00:30 - Nap 1
		Minutes of sleep: 5-20
		Thoughts: It's possible I didn't sleep at all.
	06:00-06:30 - Nap 2
		Minutes of sleep: 20-30
		Thoughts: After waking up I stupidly stayed in bed…until 12. I doubt I was
 		awake all that time, but I don't remember.
	12:00-12:30 - Nap 3
		Minutes of sleep: 15-30
		Thoughts: I had a vivid dream and slept a lot! Upon waking I felt very
 		refreshed and not at all tired.
	18:00-18:30 - Nap 4
		Minutes of sleep: 0-15
		Thoughts: I don't think I slept at all.
	Summary:
		Total minutes of sleep: 40-95
		Thoughts: Closest yet to a perfect day of dymaxion!

_____________________________________________________________________________

Monday, June 3, 2013 - Day 7
	00:00-00:30 - Nap 1
		Minutes of sleep: 0-15
		Thoughts: I don't think I slept at all.
	02:00-05:00 - Nap 2
		Minutes of sleep: 165
		Thoughts: This was an extra nap that was supposed to be half an hour
 		(until 02:30), but that didn't work out so well…
	05:50-06:30 - Nap 3
		Minutes of sleep: 30-40
		Thoughts: Slept early because tired.
	12:00-12:40 - Nap 4
		Minutes of sleep: 20-30
		Thoughts: Slept late because tired.
	18:00-18:30 - Nap 5
		Minutes of sleep: 0-15
		Thoughts: I might not have slept at all.
	Summary:
		Total minutes of sleep: 215-265
		Thoughts: I done fucked up.

_____________________________________________________________________________

Tuesday, June 4, 2013 - Day 8
	03:00-03:30 - Nap 1
		Minutes of sleep: 5-20
		Thoughts: Skipped 00:00 nap because I had to finish my Jinx Tshirt
 		submission, then decided to take one at 03:00.
	06:00-07:30 - Nap 2
		Minutes of sleep: 75-90
		Thoughts: Woke up at 06:30 then stayed in bed and fell back asleep until
 		07:30.
	12:00-2:00 - Nap 3
		Minutes of sleep: 105-120
		Thoughts: Woke up at 12:30, then passed out again.
	18:00-18:30 - Nap 4
		Minutes of sleep: 20-30
		Thoughts: Slept well.
	Summary:
		Total minutes of sleep: 205-260
		Thoughts: GODAMNIT

RSA Encryption

This year I took my school’s AP Calculus BC course. Instead of final exams for the second semester we were required to develop a final project and present it to the class. I, along with two classmates, decided to study RSA encryption. RSA, named for its three inventors, was created as a new form of public-key cryptography (I recommend you click that link and read through it, it’s incredibly interesting). As part of the project we were tasked with applying the mathematical concepts to something in the real world. I decided it would be a great idea to write a program capable of encoding and decoding messages using RSA encryption. I started working on the code during a long day election judging, but soon got stuck. I was using C++, the only language I know (yet), and I needed a way of storing large numbers. Now, my 64-bit laptop is at most capable of creating 64-bit unsigned integers. That works out to a maximum value of 18,446,744,073,709,551,615. While that is an incredibly large number, I soon realized that I would be working with much larger ones (think 2,917^3,697). I looked into various bignum libraries, but Xcode didn’t like that idea. I persisted for a few days, but alas, I did not succeed. I put the project on hold for a few weeks while I worked on schoolwork, but eventually realized I would have to write my own bignum functions.

Screen Shot 2013-05-12 at 1.09.56 AM

I created addition, multiplication, exponentiation, and modulation functions for use with big integers. To do so, I first had to convert my entire program over to using massive arrays (currently 10,000 digits). Once I had that accomplished, I set out to re-learn basic addition and multiplication. This was actually surprisingly hard as I have used calculators for everything since middle school and had forgotten how to do computations by hand. I spent a few intensive days chasing bugs, and it finally worked! With all the mathematics working, I then had to create a nice pretty UI to show off to my calc class. Even though constantly cout-ing information probably slows down the program, it was necessary both to please the crowd and to give a visual indicator that my computer hadn’t just frozen. Last Friday (5/10/13) was the day of the presentation and it went swimmingly. The class of mostly non-programmers thought the numbers flashing by looked cool, and the decoded message was the same as the original. Now here’s hoping I get a semi-decent grade for the semester ;) Cheers!

Screen Shot 2013-05-12 at 1.11.50 AM

Here are the three source files for your enjoyment. They compile fine with Xcode on a mac (with one warning about time(null)), but I can’t speak for any other OS. The highlighted section in bignum.cpp is the method I originally used for the modulo function. For some reason it only worked in some situations, and I believe my current code (the part just above it) isn’t very consistent either.

Code is released into the public domain and open-source.

#include "header.h"
#include <iostream>
using namespace std;

// Initialize message as an unsigned 64-bit integer
uint64_t nMessage = 0;

int main()
{
    srand(time(NULL));
    
    // Entire program contained within a loop
    while (true)
    {
        // Initialize all variables as unsigned 64-bit integers
        uint64_t nFactorP, nFactorQ;
        uint64_t nProduct;
        uint64_t nPhiN;
        uint64_t nPublicExponent;
        uint64_t nPrivateExponent = 0;
        
        // Find first prime
        for (nFactorP = rand() % 100 + 30; nFactorP > 1; nFactorP--)
        {
            int i;
            
            for (i = 2; i <= nFactorP / 2; i++)
            {
                if (!(nFactorP % i))
                    break;
            }
            
            if (i > nFactorP / 2)
                break;
        }
        
        // Find second prime
        for (nFactorQ = rand() % 100 + 30; nFactorQ > 1; nFactorQ--)
        {
            int i;
            
            for (i = 2; i <= nFactorQ / 2; i++)
            {
                if (!(nFactorQ % i))
                    break;
            }
            
            if (i > nFactorQ / 2)
                break;
        }
        
        // Find the product N of both primes P and Q
        nProduct = nFactorP * nFactorQ;
        
        // Find Phi of N (Euler's Totient Function) by multiplying (P - 1) by (Q - 1)
        nPhiN = (nFactorP - 1) * (nFactorQ - 1);
        
        // Find the public exponent E by finding a coprime of Phi of N
        for (nPublicExponent = rand() % 90 + 10; nPublicExponent > 1; nPublicExponent--)
        {
            if (gcd(nPublicExponent, nPhiN) == 1)
                break;
        }
        
        // Find the private exponent
        for (int i = 1; i < nPhiN; i++)
        {
            if (!((i * nPhiN + 1) % nPublicExponent))
            {
                nPrivateExponent = (i * nPhiN + 1) / nPublicExponent;
                break;
            }
        }
        
        // Print a bunch of info
        cout << "\nP = " << nFactorP << endl;
        cout << "Q = " << nFactorQ << endl;
        cout << "N = " << nProduct << endl;
        cout << "Phi of N = " << nPhiN << endl;
        cout << "Public Exponent = " << nPublicExponent << endl;
        cout << "Private Exponent = " << nPrivateExponent << endl;
        
        // Request a number to encode
        cout << "\nPlease enter a 1-3 digit number" << endl;
        cin >> nMessage;
        cout << "\nOriginal message = " << nMessage << endl;
        
        // Store all values in arrays
        short anPublicExponent[nArraySize] = {};
        uint64_t nPublicExponentTemp = nPublicExponent;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            int nRemainder = nPublicExponentTemp % 10;
            
            anPublicExponent[nArraySize - i - 1] = nRemainder;
            
            nPublicExponentTemp -= nRemainder;
            nPublicExponentTemp /= 10;
        }
        
        short anPrivateExponent[nArraySize] = {};
        uint64_t nPrivateExponentTemp = nPrivateExponent;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            int nRemainder = nPrivateExponentTemp % 10;
            
            anPrivateExponent[nArraySize - i - 1] = nRemainder;
            
            nPrivateExponentTemp -= nRemainder;
            nPrivateExponentTemp /= 10;
        }
        
        short anProduct[nArraySize] = {};
        uint64_t nProductTemp = nProduct;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            int nRemainder = nProductTemp % 10;
            
            anProduct[nArraySize - i - 1] = nRemainder;
            
            nProductTemp -= nRemainder;
            nProductTemp /= 10;
        }
        
        short anMessage[nArraySize] = {};
        uint64_t nMessageTemp = nMessage;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            int nRemainder = nMessageTemp % 10;
            
            anMessage[nArraySize - i - 1] = nRemainder;
            
            nMessageTemp -= nRemainder;
            nMessageTemp /= 10;
        }
        // Store all values in arrays
        
        // Encode message
        short *pMessageEncoded = bignumExpMod(anMessage, anPublicExponent, anProduct);
        
        // Print a bunch of info
        cout << "\n\nP = " << nFactorP << endl;
        cout << "Q = " << nFactorQ << endl;
        cout << "N = " << nProduct << endl;
        cout << "Phi of N = " << nPhiN << endl;
        cout << "Public Exponent = " << nPublicExponent << endl;
        cout << "Private Exponent = " << nPrivateExponent << endl;
        
        cout << "\nOriginal message = " << nMessage << endl;
        
        cout << "\nEncoded message = ";
        
        // Print encoded message
        bool bZero = false;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (*(pMessageEncoded + i))
                bZero = true;
            if (bZero)
                cout << *(pMessageEncoded + i);
        }
        cout << endl;
        
        // Request to decode
        cout << "\n\nType any character to decode" << endl;
        char chDecode;
        cin >> chDecode;
        
        // Store encoded message in array
        short anMessageEncoded[nArraySize] = {};
        
        for (int64_t i = 0; i < nArraySize; i++)
            anMessageEncoded[i] = *(pMessageEncoded + i);
        
        // Decode message
        short *pMessageDecoded = bignumExpMod(anMessageEncoded, anPrivateExponent, anProduct);
        
        // Print a bunch of info
        cout << "\n\nP = " << nFactorP << endl;
        cout << "Q = " << nFactorQ << endl;
        cout << "N = " << nProduct << endl;
        cout << "Phi of N = " << nPhiN << endl;
        cout << "Public Exponent = " << nPublicExponent << endl;
        cout << "Private Exponent = " << nPrivateExponent << endl;
        
        cout << "\nOriginal message = " << nMessage << endl;
        
        cout << "\nEncoded message = ";
        
        // Print encoded message
        bZero = false;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anMessageEncoded[i])
                bZero = true;
            if (bZero)
                cout << anMessageEncoded[i];
        }
        cout << endl;
        
        cout << "\nDecoded message = ";
        
        // Print decoded message
        bZero = false;
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (*(pMessageDecoded + i))
                bZero = true;
            if (bZero)
                cout << *(pMessageDecoded + i);
        }
        cout << "\n\n" << endl;
        
        // Ask if the user would like to restart the program
        char chLoop;
        cout << "\nWould you like to run again? (y/n)" << endl;
        cin >> chLoop;
        
        if (chLoop == 'n')
            exit(0);
    }
    
    return 0;
}

uint64_t gcd(uint64_t x, uint64_t y)
{
    // Function is recursive: it calls itself until x % y = 0
    if (!(x % y))
        return y;
    else
        return gcd(y, x % y);
}
#include "header.h"
#include <iostream>
using namespace std;

// Addition
short * bignumAdd(short anNumber1[], short anNumber2[])
{
    // Initialize sum array
    static short anSum[nArraySize] = {};
    
    // Initialize carry value to 0
    int nCarry = 0;
    
    // Add the two arrays and the carry from the previous digit
    for (int64_t i = nArraySize - 1; i >= 0; i--)
    {
        anSum[i] = anNumber1[i] + anNumber2[i] + nCarry;
        
        // Calculate carry for next time through the loop
        if (anSum[i] > 9)
        {
            nCarry = 1;
            
            anSum[i] = anSum[i] % 10;
        }
        else
            nCarry = 0;
    }
    
    // Return the sum
    return anSum;
}

// Multiplication
short * bignumMul(short anNumber1[], short anNumber2[])
{
    // Initialize product array
    static short anProduct[nArraySize] = {};
    
    // Calculate product using the grid method for multiplication
    for (int64_t i = nArraySize - 1; i >= 0; i--)
    {
        for (int64_t ii = nArraySize - 1; ii >= 0; ii--)
        {
            int nProduct = anNumber1[ii] * anNumber2[i];
            
            if ((ii + i - nArraySize + 1) > 0)
                anProduct[ii + i - nArraySize + 1] += nProduct;
        }
    }
    
    // Initialize carry value to 0
    int nCarry = 0;
    
    // Factor in the carries
    for (int64_t i = nArraySize - 1; i >= 0; i--)
    {
        anProduct[i] += nCarry;
        
        // Calculate carry for next time through the loop
        if (anProduct[i] > 9)
        {
            int nRemainder = anProduct[i];
            nRemainder -= (nRemainder % 10);
            
            nCarry = nRemainder / 10;
            
            anProduct[i] -= nRemainder;
        }
        else
            nCarry = 0;
    }
    
    // Return the product
    return anProduct;
}

// Exponentiation
short * bignumExp(short anBase[], short anPower[])
{
    // Initialize product and temporary arrays
    static short anProduct[nArraySize] = {};
    short anProductTemp[nArraySize];
    
    // Set temp array equal to the base
    for (int64_t i = 0; i < nArraySize; i++)
        anProductTemp[i] = anBase[i];
    
    // Loop multiplication portion while the power is greater than 1
    while (true)
    {
        // Decrement the power array by 1
        if (anPower[nArraySize - 1])
            anPower[nArraySize - 1] -= 1;
        else
        {
            anPower[nArraySize - 1] = 9;
            
            for (int64_t i = nArraySize - 2; i >= 0; i--)
            {
                if (anPower[i])
                {
                    anPower[i] -= 1;
                    break;
                }
                else
                    anPower[i] = 9;
            }
        }
        
        // Initialize stop variable to true
        bool bStop = true;
        
        // If all elements of the power array are zero, bStop stays true
        for (int64_t i = 0; i < nArraySize; i++)
            if (anPower[i] > 0)
                bStop = false;
        
        // If power array is 0, break the loop
        if (bStop)
            break;
        
        // Calculate the number of significant digits in the temp array
        int64_t nSize1 = 0;
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anProductTemp[i] > 0)
            {
                nSize1 = nArraySize - i;
                break;
            }
        }
        
        // Calculate the number of significant digits in the base array
        int64_t nSize2 = 0;
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anBase[i] > 0)
            {
                nSize2 = nArraySize - i;
                break;
            }
        }
        
        // Calculate which array is the longest (temp or base)
        int64_t nSize = 0;
        
        if (nSize1 < nSize2)
            nSize = nSize2;
        else
            nSize = nSize1;
        
        // Set product array to 0
        for (int64_t i = 0; i < nArraySize; i++)
            anProduct[i] = 0;
        
        // Calculate the product of the temp array and the base and store it in the product array (using grid method)
        for (int64_t i = nArraySize - 1; i >= nArraySize - nSize; i--)
        {
            for (int64_t ii = nArraySize - 1; ii >= nArraySize - nSize; ii--)
            {
                int nProduct = anProductTemp[i] * anBase[ii];
                
                if ((ii + i - nArraySize + 1) > 0)
                    anProduct[ii + i - nArraySize + 1] += nProduct;
            }
        }
        
        // Calculate the number of significant digits in the product array
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anProduct[i] > 0)
            {
                nSize = nArraySize - i;
                break;
            }
        }
        
        // Initialize carry value to 0
        int nCarry = 0;
        
        // Factor in the carries
        for (int64_t i = nArraySize - 1; i >= nArraySize - nSize - 1; i--)
        {
            anProduct[i] += nCarry;
            
            if (anProduct[i] > 9)
            {
                int nRemainder = anProduct[i];
                nRemainder -= (nRemainder % 10);
                
                nCarry = nRemainder / 10;
                
                anProduct[i] -= nRemainder;
            }
            else
                nCarry = 0;
        }
        
        // Set the temp array equal to the product array
        for (int64_t i = 0; i < nArraySize; i++)
            anProductTemp[i] = anProduct[i];
        
        // Calculate the number of significant digits in the product array
        int64_t nSize3 = 0;
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anProduct[i] > 0)
            {
                nSize3 = nArraySize - i;
                break;
            }
        }
        
        //Print info
        bool bZero = false;
        
        cout << "Multiplications left: ";
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anPower[i])
                bZero = true;
            if (bZero)
                cout << anPower[i];
        }
        cout << endl;
        
        bZero = false;
        
        cout << "Digits: " << nSize3 << "   Product: ";
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anProduct[i])
                bZero = true;
            if (bZero)
                cout << anProduct[i];
        }
        cout << endl;
        //Print info
    }
    
    // Return the product
    return anProduct;
}

// Modulation
short * bignumMod(short anDividend[], short anModulus[])
{
    // Initialize the remainder and temporary arrays
    static short anRemainder[nArraySize] = {};
    short anModulusTemp[nArraySize] = {};
    
    // Loop subtraction portion while the remainder is greater than 0
    while (true)
    {
        // Calculate the number of significant digits in the dividend array
        int64_t nSize1 = 0;
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anDividend[i] > 0)
            {
                nSize1 = nArraySize - i;
                break;
            }
        }
        
        // Calculate the number of significant digits in the modulus array
        int64_t nSize2 = 0;
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anModulus[i] > 0)
            {
                nSize2 = nArraySize - i;
                break;
            }
        }
        
        // Initialize stop variable to false
        bool bStop = false;
        
        if (nSize1 == nSize2)
        {
            // Check if the dividend is larger or smaller than the modulus
            for (int64_t i = nArraySize - nSize1; i < nArraySize; i++)
            {
                if (anDividend[i] - anModulus[i] > 0)
                    break;
                else if (anDividend[i] - anModulus[i] < 0)
                {
                    bStop = true;
                    break;
                }
            }
        }
        else if (nSize1 < nSize2)
            bStop = true;
        
        // If the dividend is smaller than the modulus, set the remainder equal to it and break the loop
        if (bStop)
        {
            for (int64_t i = 0; i < nArraySize; i++)
                anRemainder[i] = anDividend[i];
            break;
        }
        
        // If the modulus is shorter than the dividend then multiply it by 10 until it is one digit shorter than the dividend
        if ((nSize1 - nSize2) > 1)
        {
            for (int64_t i = 0; i < nArraySize - (nSize1 - nSize2 - 1); i++)
                anModulusTemp[i] = anModulus[i + (nSize1 - nSize2 - 1)];
            
            // Set the temp array equal to the modulus
            for (int64_t i = nArraySize - (nSize1 - nSize2 - 1); i < nArraySize; i++)
                anModulusTemp[i] = 0;
        }
        else
        {
            // If not, just set the temp array equal to the modulus
            for (int64_t i = 0; i < nArraySize; i++)
                anModulusTemp[i] = anModulus[i];
        }
        
        /*
        for (int64_t i = 0; i < nArraySize; i++)
            anModulusTemp[i] = anModulus[i];
        
        for (int64_t i = 1; i < nSize1 - nSize2; i++)
        {
            for (int64_t ii = nArraySize - nSize1 - 1; ii < nArraySize - 1; ii++)
            {
                anModulusTemp[ii] = anModulusTemp[ii + 1];
                
                if (ii == nArraySize - 2)
                    anModulusTemp[nArraySize - 1] = 0;
            }
        }
         */
        
        // Subtract the modulus from the dividend
        for (int64_t i = nArraySize - 1; i >= nArraySize - nSize1; i--)
        {
            if ((anDividend[i] - anModulusTemp[i]) < 0)
            {
                anDividend[i] += 10;
                anDividend[i - 1] -= 1;
            }
            
            anRemainder[i] = anDividend[i] - anModulusTemp[i];
        }
        
        // Set the dividend equal to the remainder
        for (int64_t i = 0; i < nArraySize; i++)
            anDividend[i] = anRemainder[i];
        
        // Calculate the number of zeros after the significant digits in the modulus array
        int64_t nSize3 = 0;
        for (int64_t i = nArraySize - 1; i >= 0; i--)
        {
            if (anModulusTemp[i] > 0)
            {
                nSize3 = nArraySize - i - 1;
                break;
            }
        }
        
        //Print info
        bool bZero = false;
        
        cout << "Modulus: ";
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anModulus[i])
                bZero = true;
            if (bZero)
                cout << anModulus[i];
        }
        cout << "*10^" << nSize3 << endl;
        
        bZero = false;
        
        cout << "Digits: " << nSize1 << "   Remainder: ";
        
        for (int64_t i = 0; i < nArraySize; i++)
        {
            if (anDividend[i])
                bZero = true;
            if (bZero)
                cout << anDividend[i];
        }
        cout << endl;
        //Print info
    }
    
    // Return the remainder
    return anRemainder;
}

// Exponentiation and subsequent modulation
short * bignumExpMod(short anBase[], short anPower[], short anModulus[])
{
    // Modulate the base first to speed up computation
    short *pMod = bignumMod(anBase, anModulus);
    short anMod[nArraySize] = {};
    
    for (int64_t i = 0; i < nArraySize; i++)
        anMod[i] = *(pMod + i);
    
    // Calculate the exponent
    short *pExp = bignumExp(anMod, anPower);
    short anExp[nArraySize] = {};
    
    for (int64_t i = 0; i < nArraySize; i++)
        anExp[i] = *(pExp + i);
    
    // Modulate the exponentiated number
    short *pExpMod = bignumMod(anExp, anModulus);
    static short anExpMod[nArraySize] = {};
    
    for (int64_t i = 0; i < nArraySize; i++)
        anExpMod[i] = *(pExpMod + i);
    
    // Return the final value
    return anExpMod;
}
#ifndef Calculus_RSA_Project_header_h
#define Calculus_RSA_Project_header_h

#include <iostream>

// Functions in main.cpp
uint64_t gcd(uint64_t, uint64_t);

// Functions in bignum.cpp
short * bignumAdd(short[], short[]);
short * bignumMul(short[], short[]);
short * bignumExp(short[], short[]);
short * bignumMod(short[], short[]);
short * bignumExpMod(short[], short[], short[]);

// Global variables
const uint64_t nArraySize = 10000;

#endif

An Arduino Micro Clone

Hello, my name is Jordi. I’m currently a high school senior, but I will be graduating in a few weeks, after which I will be attending university with a major in Electrical Engineering. I’ve been a long-time follower of the diydrones community and have made a few posts in the past. In August of last year I made a blog post entitled “Introducing Glowduino!”. I had created a board that was designed to control multicolored LEDs on various unmanned vehicles. I ordered the boards and assembled them, but made the stupid mistake of using a TQFP ATMega328 and not including an ICSP header. I had known this would be a problem, so I also designed some small breakout boards for programming. I simply pressed the chip onto the board to program it, and then soldered it to the Glowduino. Once everything was assembled I plugged it in and…it didn’t work. After a good deal of searching I realized that I had accidentally flashed the wrong Arduino bootloader to the chip. I was using a 16Mhz crystal, yet I flashed a 8Mhz crystal-less bootloader. I don’t have a hot-air rework station, and desoldering it didn’t work so well (believe me, I tried). With the board bricked and my hopes dashed, I put the project aside to focus on school work.

A month or two ago I decided to come back to the project and see if I could at least get it into a working state. I designed and ordered some breakouts for the various chips that are used on the project and began breadboarding the design (I know I know, I should have done that first :)) and writing some code. I soon realized that the entire concept behind Glowduino might be more successful if the system were more modular. This got me looking into viable Arduino-compatible microcontrollers, and I soon came across the Arduino Micro. While all of its features are very well suited to my needs, I didn’t really like the form factor, among a few other small things. For these reasons I decided to set out to create a ‘better’ Arduino Micro. I barely changed anything from the original design. The only changes I made were to include higher capacity regulators and to shrink the size of the board. I shrank the width by 0.1″ and the length by 0.3″. This meant that instead of having two rows of 17 pins it now has two rows of 16, and they are 0.5 inches apart (1 row closer together on a breadboard). I also rearranged the order of the pins to better match the larger Arduino Uno and Leonardo pinouts. All this came with a price, however, and no matter how hard I tried I simply could not route the board on two layers.

I only have the free version of Cadsoft’s Eagle which only allows the creation of 2-layer boards. I had heard of Kicad and it sounds awesome, but after weeks of trying to migrate all my libraries and design files over to it I realized that I would be forced to stay with Eagle for the time being. After laying this project on the shelf for a bit I remembered that I had a friend who owned the full professional Eagle software. I asked him if I could use it and he agreed, and after a long bit of routing, ripping up, and re-routing I had a 100% routed 4-layer board that could be purchased from OSHPark. This time, however, I didn’t immediately order the boards. Instead, I bought an ATMega32u4 and breakout from Futurlec and set to work breadboarding the project. I have made all the necessary connections and I am currently trying to get my usbasp to talk to the chip so that I can flash a bootloader. I haven’t made too much progress on this front yet, tho, as AP Tests are coming up, final projects for my classes are due soon, and I am acting in my school’s current musical.

In the above photos, the purple board is a breakout for the TLC5947. It is larger than my final Arduino clone will be :)

With the completion of this new microcontroller the Glowduino has been turned into a ‘shield’ for it. The idea is that the system will be super modular, with the option for more ‘shields’ in the future. In fact, it would be almost trivial to create an adapter for using preexisting Arduino shields with this microcontroller. Users could have the option of only installing one shield on each vehicle and simply plugging the microcontroller into whichever one they wish to use. Additionally, expansion boards could be designed that extend the Glowduino’s capabilities, such as the ability to control EL wire or LED matrixes (thank you Jonathan Lederer!).

I know I will at least make a few of these boards for my friends and I, but this is where I would like some feedback. Is this a good idea? Would you buy it? What ideas do you have for something you could do with it? Is there anything you’d like to see? What is a reasonable price-point? I’m completely into open-sourcing everything, so the design files, schematics, bill of materials etc. will all be released completely once the project is finished. I will be updating my flickr (which is currently quite sparse) with photos soon, here’s the link: Flickr Photostream. I would love to be able to actually build these in the future, and I very much appreciate your feedback. Thank you!

Original blog post: diydrones.com