Thursday, January 28, 2010

Turning the AVR butterfly into an ISP

First step to building my synthesizer - constructing an AVR programmer. Due to the lack of a parallel port on my laptop, building a parallel programmer was out of the question. Hence I present here a (serial) In System Programmer (ISP).

An ISP comes with one caveat, however - the AVR 910 protocol (used for ISPing AVR devices) is too complex to simply use bitbanging over RS-232. Most programmer designs get around this by using a programmed AVR to translate messages sent over RS-232 (from the host computer) into AVR 910 (sent to the target system). Yep. They use a programmed AVR to build an AVR programmer. Can you spell circular dependency?

So in order to build an ISP, there are a few options
  1. Use a parallel programmer to bitbang the AVR used in the ISP
  2. Buy a commercial AVR programmer
  3. Borrow someone else's AVR programmer
For me, (1) is ruled out due to my lack of parallel port. (2) is ruled out due to the state of my finances. And I don't know anyone who owns an AVR programmer.

There is, however, one further option, which is to turn Atmel's AVR butterfly demonstration board into an ISP. The AVR butterfly comes with several useful features, usefully for this project, a built in RS-232 level converter. Even more interestingly, it is also self programmable, due to its preloaded bootloader.

This basically means that an AVR programmer is not required to program the butterfly. Since I have a spare butterfly lying around the home (they were given out to first year electrical engineering students a couple of years back at my uni) it seems a good candidate for my ISP.

The code for the programmer, as well as the makefile and some basic schematics are here. The design is based on Atmel's AVR 910 application note, though it adds several features, notably support for a wider variety of AVR targets. It should be compatible with the "avrisp" driver in avrdude.

So happy building. Finally, I should note that I do not intend for this to be a permanent programmer - I have ported the above code to the atmega8, and will actually be building a standalone ISP later - but I will be using this butterfly programmer to bootstrap it.

Saturday, January 23, 2010

Out, out damned bot!

Recently, our university club's website was used as a citation in a wikipedia article. On the plus side, this has increased our website's google pagerank quite substantially. On the downside, our small punBB based forum is now receiving much greater attention from the spambots.

So here I present two very simple modifications to punBB that have helped to stem the spambot tide. The first is integrating the captcha service provided by recaptcha into the punBB registration form. To use this service, you will need to register. You will also need to insert your recaptcha public and private keys into the mod code provided below.

The second method employs the spambot blacklist at http://www.stopforumspam.com/. It will check the email and ip address of any newly registered forum user, denying them registration if they are found to be on the blacklist.

Finally, I recommend turning on punBB's email validation feature.

While extremely simple, these measures seem to have reduced the number of spambot registrations on our forum quite substantially.

The mod code is below. As I have ranted about previously, the university's hosting server only has php4, so some parts of the code are a little kludgy (php4 lacks decent exception handling). Note also, that the code has only been tested on punBB 1.2.16, though it should work fine on any other version in the 1.2 series.

Instructions
  1. Register an account with recaptcha, and then register your site's domain. Take note of your private and public keys
  2. Download recaptchalib.php, and upload it to the root directory of your punBB forum.
  3. Open the punBB file "register.php". Locate (around line 80) the lines
     else if (isset($_POST['form_sent']))
    {

    After, add the following code, remembering to insert your recaptcha private key where required:
     1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     //Validate CAPTCHA entry
    require_once('recaptchalib.php');
    $privatekey = "INSERT YOUR RECAPTCHA PRIVATE KEY HERE";
    $resp = recaptcha_check_answer ($privatekey,
    $_SERVER["REMOTE_ADDR"],
    $_POST["recaptcha_challenge_field"],
    $_POST["recaptcha_response_field"]);

    if (!$resp->is_valid) {
    message ("You have failed the human test. Please re-enter the CAPTCHA. Unless you are a bot. If that is the case, then bugger off!" .
    "(reCAPTCHA said: " . $resp->error . ")");
    } //end validate CAPTCHA entry

    //check the users ip and email against the www.stopforumspam.com database. This code is really awkward, since it has to run on php4.
    //check ip
    $xml_string = file_get_contents('http://www.stopforumspam.com/api?ip='.get_remote_address());
    if ($xml_string){ //make sure we degrade gracefully if stopforumspam.com is offline
    if (strpos($xml_string, "<appears>yes</appears>")) //phps string handling is terrible, and normally we can't write code like this. This is ok, since if a match occurs, it will never be at the zeroeth character - the response from stopforumspam always begins with <response success="true">
    message("You are trying to register from an ip address that has been used by a spambot. If you are a legitimate (human) user, please email us, so we can sort out your registration. If you are a spambot, then kindly die in a hole.");
    }

    //check email address
    $email = strtolower(trim($_POST['req_email1']));
    $xml_string = file_get_contents('http://www.stopforumspam.com/api?email='.$email);
    if ($xml_string){ //make sure we degrade gracefully if stopforumspam.com is offline
    if (strpos($xml_string, "<appears>yes</appears>")) //phps string handling is terrible, and normally we can't write code like this. This is ok, since if a match occurs, it will never be at the zeroeth character - the response from stopforumspam always begins with <response success="true">
    message("Your email address seems to belong to a spammer. Please die in a hole. Thank you for your co-operation.");
    }

  4. Scroll down to about line 310, and find the following lines:
     1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <div class="inform">
    <fieldset>
    <legend><?php echo ($pun_config['o_regs_verify'] == '1') ? $lang_prof_reg['E-mail legend 2'] : $lang_prof_reg['E-mail legend'] ?></legend>
    <div class="infldset">
    <?php if ($pun_config['o_regs_verify'] == '1'): ?> <p><?php echo $lang_register['E-mail info'] ?></p>
    <?php endif; ?> <label><strong><?php echo $lang_common['E-mail'] ?></strong><br />
    <input type="text" name="req_email1" size="50" maxlength="50" /><br /></label>
    <?php if ($pun_config['o_regs_verify'] == '1'): ?> <label><strong><?php echo $lang_register['Confirm e-mail'] ?></strong><br />
    <input type="text" name="req_email2" size="50" maxlength="50" /><br /></label>
    <?php endif; ?> </div>
    </fieldset>
    </div>.



    After, add the following code, remembering to substitute in your own recaptcha public key where required:
     1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <div class="inform">
    <fieldset>
    <legend>Human Test (CAPTCHA)</legend>
    <div class="infldset">
    This is to ensure you are not a horrible spambot. Please complete the CAPTCHA below
    <?php
    //display reCAPTCHA
    require_once('recaptchalib.php');
    $publickey = "INSERT YOUR RECAPTCHA PUBLIC KEY HERE";
    echo recaptcha_get_html($publickey);
    ?>
    </div>
    </fieldset>
    </div>

  5. Save the modified version of register.php, and upload it to your hosting server
If anyone has any feedback on the above modifications/wants to unleash the bile against spambots, feel free to leave a comment.

Thursday, January 21, 2010

A five octave, 6 voice synthesizer

After about 2 years of cogitation, I've finally decided to do it - build a synthesizer. And finish it by the end of the year.

I'd originally intended to build an analogue synth, in the mould of the mini-moog. On further investigation, it transpired that the price/feature ratio of such a design was not particularly good. So, being a poor (and hungry) uni student, I'll be going with the cheaper (digital) option.

Basically, I want the synthesizer I design to have the following features
  1. polyphony - must be able to play at least three notes simultaneously
  2. the ability to split the keyboard, so that each half can be mapped to a different voice
  3. pitch bending
  4. analogue controls for setting the attack, levels of each harmonic, etc - I find digital controls clunky
  5. 16 bit, 44kHz sound output, or better
  6. Additive synthesis
  7. Total cost to manufacture of less than $200
And now, finally, I have a (concept) design which meets all these requirements.

The design will be based around Atmel's atmega8 microcontroller. Actually, in order to meet the performance requirements, it will be based around seven of them. On the surface, using seven low performance, 8 bit micros, seems a little silly, particularly when there are plenty of excellent ARM based products out there, of similar price, but with vastly superior performance. However, there were several reasons for choosing the AVR product.
  1. The atmega8 is really cheap (about $3)
  2. Programmers for AVRs are really easy (and cheap) to build, driving down the total cost of the project (I don't own a JTAG based programmer, which is what most of the ARM based micros seem to require, and such programmers are quite expensive)
  3. The documentation for the AVR family is excellent
  4. AVR studio, supplied free by Atmel, is an excellent embedded IDE, and I am familiar with it
  5. using multiple CPUs allows for a more modular design
So there. I've rationalized away my choice. Probably another reason would be that I'm much more familiar with AVR than ARM. On the downside, using this AVR based design means having to deal with communication and synchronization between multiple CPUs, which tends to be a process fraught with (enormous) difficulty.

But anyway, it's too late to change now (otherwise I'll never get this project finished). I'll keep udating this blog with my progress on this project, mainly as a way of keeping myself motivated. Hopefully, by this time next year there'll be plenty of photos of the finished synth up here, as well as a full set of schematics, firmware and pcb-layout.

Thursday, January 7, 2010

A sudoku solver in C

The title's pretty self explanatory. I wrote this program for two reasons - firstly, as an exercise in C programming, but also because I was having trouble with a particular sudoku puzzle at the time.

The program should be able to find a solution to any solvable puzzle. For the case of puzzles solvable using only elimination (no "guessing" required), the solution is unique. For solutions which require "guessing", the uniqueness of the solution cannot be guaranteed.

http://dl.dropbox.com/u/1614464/sudosolve.c