1. Clock Speed of a PIC Using an Oscilloscope

    May 3, 2012 by uzimonkey

    I got my first PIC chips in the mail the other day, and I’ve been working with them a bit. They’re surprisingly complex for such tiny, cheap things. One obstacle you’ll encounter when first starting is configuring the clock source. At first, you write a small program that sets the TRISB register and twiddles the PORTB bits and hope to see and LED light up.

    So, first roadblock. Nothing happens at all when you do this on the chips I got (PIC18F14K50). You have to enable the internal clock source with the correct fuse bits. Luckily, you don’t have to know which bits directly, Microchips C compiler lets you configure these things via pragmas with mnemonics. And, since each chip has its own set of values with different names and bits in the configuration memory, there’s a GUI in the mplabx IDE that lets you simply select which options you want.

    So you enable the internal oscillator and get things to work, but how fast is it running? It’s pretty easy to tell with an oscilloscope. Write a program that sets PORTB to output, then alternatively to 0xff, 0×00, 0xff, 0×00, etc. Do this a few times without a loop, and then put all that into an infinite loop. Build the project and look at the disassembly to confirm that it’s really only taking one instruction every time it sets PORTB, and it is. Look at one of the PORTB pins on your oscilloscope and you’ll see something like this.

    20120503-201329.jpg

    What I’ve done here is enabled the 16MHz oscillator, configured it to use the /2 divider and the 4x PLL. So it should be oscillating at 32MHz. What you see on the scope is a single pulse from the port. The beginning of the pulse rise to the beginning of the pulse fall is one instruction. It’s taking 2 and a half time divs with each div being 0.05 microseconds, or a 0.125 microsecond pulse. 1 / 0.000000125 is only 8MHz, what gives? Each instruction takes 4 clock cycles on the PIC, it isn’t pipelined. This is exactly what we hoped to see here.

    I’m glad I have s scope here, because confirming that you really are setting the oscillator bits correctly is difficult without it. My next task is to get the 12MHz crystal oscillator hooked up and working, and then dive into the USB library. I feel that I’m most of the way there already.


  2. A Proper Reset Circuit

    April 17, 2012 by uzimonkey

    As I’m playing with my Z80 tester, I notice something.  Sometimes the Z80 will start up without needing to be reset, and other times it will not.  What’s needed is a proper reset circuit.  In order to start up, the Z80 needs to be reset for a few clock cycles.  I found a neat circuit here (at the bottom) that not only does that (in a very obvious way) but solves another problem.

    First off, you can play with the circuit using this Java-powered simulator.  I really love this simulator, it’s a lot like a SPICE simulation except you can see what’s going on.  It might not be the best or more accurate simulation out there, but it’s certainly useful to visualize what’s happening.

    When the circuit is first powered up, the capacitor will charge.  As it’s charging and conducting initially, it’s pulling the output to ground.  As it charges, its conductance goes down and eventually it will stop conducting at all.  At some point during that, it will fall below the threshold for the first NOT gate and the output will be reversed.  This arrangement is, in essence, a time-sensitive voltage divider.  As the circuit is being powered, the larger resistor is on top, so the output of the divider will tend toward ground.  After some time, it will tend toward the supply voltage.  The value of the resistor and capacitor define how long the pulse will be, but for fast clocks it probably won’t matter, the Z80 only needs a few cycles to reset.

    The NOT gates are there for two reasons.  First, as a Schmitt trigger and buffer.  As this capacitor changes the tendency of the voltage divider, its output voltage will fluctuate.  This is not what we want, we want a nice clean reset pulse.  So we transfer this input into the digital domain by using a NOT gate.  A single buffer would work, but there’s another reason for this “double NOT.”  The Z80 resets low, it resets when the reset pin is pulled to ground.  Many other chips are reset high.  There’s no common convention here, so we really have two outputs here.   The first (between the two NOT gates) are for chips that reset high.  The next (on the far left) are for chips that reset low.

    And of course the switch and resistor on the right bring the input of the first NOT to ground, forcing a reset.  What’s a microcomputer without a manual reset switch?  Note that this circuit won’t work with the Z80 tester.  It produces a very short pulse reset pulse, you’ll need to use a larger resistor and capacitory in order to make a longer reset pulse.


  3. Z80 test circuit

    April 14, 2012 by uzimonkey

    The following is a simple Z80 test circuit from z80.info.  It doesn’t do much, it just executes NOPs and, consequently, increments the program counter which appears on the address bus.  The data bus is tied low with those 8 resistors so the Z80 will always read 0×00, which just happens to be a NOP.  The chip on the left is a NAND Schmitt trigger used as a very slow clock source (I didn’t measure, maybe 5Hz).  The big chip is of course the Z80, the button to its right is a reset button.  Supposedly when the Z80 starts it must be reset or it can be in utterly unknown states, but in this case I really don’t think it’s necessary.  The 3 green LEDs on the right are the 3 lowest bits of the address bus, right now it’s showing 0×08.  Oh, and a few of the control pins are tied high, or else it just glitches out.

    This is but the first step toward the Z80 microcomputer.  I have a ROM programmer (in the background there), I have a working Z80, I just need to wire them up.  However, I’ve hit a few snags I really didn’t anticipate.  My breadboard is too small to fit another ZIF socket so it’s on the smaller board stuck on with mounting tape, and I don’t have nearly enough jumper wires.  The Z80 has 16 address pins, 8 data pins and 10 or so control pins.  To wire that up just to the ROM is going to take most of those, and again to RAM will take that many again.  Rather than buy them from China, and have them come in random lengths and colors, I’m going to make them from cannibalized wire from a VGA cable and component leads.  That alone will probably take a few hours.  And there no way around it, I need to order another breadboard.

    20120414-221818.jpg


  4. Successfully Reading an EEPROM

    April 3, 2012 by uzimonkey

    There was about an hour that, after I got the ZIF socket all wired up, I thought nothing was working.  I wrote a program to iterate through the 16 bit address space and read every byte out of the chip.  But it wasn’t working.  It was just returning junk, and different junk every time.  Something was really wrong.

    I went over the code many times, and everything looked right.  I abandoned the proxy program and wrote a program directly for the Arduino that did the same thing, and it was returning the same things (only worked much faster, since the Ruby program waited for 1 second every time it read from the serial port, for some reason).  It was just…  broken.  Until I realized that the EEPROM chip has 17 address lines, it’s a 128K flash chip.  I’d left the A16 line floating, and it was causing all kinds of trouble.  Tie that to ground and…  all I get is 0xff every time I try to read a byte.

    But this is not a bad thing.  These EEPROM chips don’t work as you’d might expect.  When you erase them, you erase the entire chip.  Once erased, the cells are in a third state.  Not 1 or 0, but empty.  And in this state if you try to read then, they’ll always read 1.  So these chips, it seems, have just been erased.  An erased chip should read all 0xff bytes.  And these are new chips, so it makes perfect sense.

    So I dig around for more chips.  There are a ton of these chips all over the place.  They all follow the same JEDEC standards, so they have the same pinout, control pins and write commands.  About the only difference you’ll see is in older chips, it takes longer to erase and it needs a higher voltage.  But all the ones I have just need 5v to erase, that’s one problem I don’t have to solve.  If you want some of these chips to play with, you can find them on PC motherboards.  They’re the BIOS chips, and are socketed for easy removal.  I find a chip with a BIOS label on it and to my astonishment, it all works perfectly.  I’m currently dumping the BIOS image (or at least the first 64k of it), which is going quite slow 1 byte at a time.

    How do I know this is a BIOS image and not just line noise?  I don’t, really.  But it’s the same every time I read it.  I also cheated a bit and have another chip that I wrote an ASCII message to, and that reads correctly.  You can see that message on my screen below.  But it’s still an unholy mess of wires.  It’ll be hell to solder, but I’m going to make it easier.  I’m going to get an Arduino Mega (and Arduino with a shitton more pins) so these shift registers won’t be necessary.  There are at least 16 pins on each side too, so all that’s needed is to solder a few jumper wires in straight lines.  It’s a bit pricey for this project, but I get an Arduino Mega out of the deal too.  Sounds good to me!


  5. Progress on the Flash Programmer

    April 2, 2012 by uzimonkey

    I’ve made some progress on the Arduino flash programmer, the first step in making the Z80 microcomputer. Flash programmers are expensive, you’ll probably end up spending $100 on one (though it’ll work out of the box and much faster). In my case, it just doesn’t make sense to buy one. So, I’m making one with the Arduino.

    The problem is that there aren’t enough IO pins on the Arduino for all 16 address lines (there are actually 17 on the chip, highest will be tied to ground). So I’m using 2 shift registers to make 3 pins on the Arduino into 16 address pins. This works, but it takes a whole lot of wiring. Not only do the 16 address lines need to be wired from the shift registers, but several lines on the 595 chips need to be tied high or low, the clock and latch pins need to be wired together and to the Arduino, the Q7′ pin to the input pin on the second chip, etc. Lots of wires, but it works.

    Another important thing I did here is to write a program for the Arduino that simply listens on the serial port for commands from the PC and does Arduinoish things based on the input. For example, my Ruby program can write to the serial port a command to change pin modes, set pin outputs and read pin inputs. This lets me use Ruby to do my testing and do the actual programs. That’s a big plus, as it’s much faster to do this.

    Part of my problem here is that it all needs to be tested. I did something similar once before, and I got it all wrong. This time, testing is important. So I wrote a Ruby program that shifts a single bit through the shift registers and hooked up an LED (which you might be able to see in the picture). This is just used to doublecheck and triplecheck that the correct pins are going to the correct address pins. I’m 95% sure it’s all right, so I’m ready to move forward.

    20120402-230245.jpg


  6. Hardware is always fun

    April 2, 2012 by uzimonkey

    There’s always something about hardware that’s just fun to mess with. I dusted off my Arduino and I’m going to program this EEPROM chip. It’s not really hard to do, except there are not enough pins on the Arduino. The flash chip needs 16 or so address pins, 8 data pins and 3 control pins. I think, I can’t remember exactly. Once I finish this part, I’ll have to look that up.

    Why not just use a serial EEPROM or flash chip? Because I’m going to make a minimal z80 computer. This will be the ROM chip, and it needs to sit right on the address bus. But this is seriously a major hurdle to get this working. It’s not that this task is so hard, it’s that making a single computer is so easy. Once you understand how to clock the z80, how the memory works (and by that I mean how to trigger the enable pin on the correct chip) and how to interface it with something, then the rest is easy.

    If I wanted to get really carried away, I could cannibalize my old C64 or VIC 20 to give it a case and keyboard. I don’t know what I would do about video, I have no idea how to produce a video signal other than with direct digital synthesis and a rather fast micro controller. But it’s not too hard to generate rs232 with a UART and use a pc as a monitor. But I doubt I’ll do any of that. I’ll probably just get some 7 segment display or LCD display hooked up to it and fool around with it a bit.

    20120402-014645.jpg

    And yes, that is a cat mug.


  7. Elementary Cellular Automata

    February 3, 2012 by uzimonkey

    I’ve started looking into some things for a new game (how many times have you said that?) and I got onto the topic of cellular automata. It’s pretty interesting, you can model some rather complex things with shockingly simple rules.  This is a demo of the classic 1-dimensional elementary cellular automata.  Each generation is defined by the state of the previous generation with each generation begin displayed as a row on the image and will stack up into a (usually) pyramid shape.

    There are 255 rules.  The rule is itself a bitfield.  If the cell and its 3 neighbors are interpreted as an integer (3 bits, the left neighbor being the most significant, right being least significant), is 1 << bits set in the rule number?  If so, this generation’s cell is true, otherwise it’s false.  You get some surprisingly, sometimes chaotic and in a few cases fractal results.  It’s fun to play around with, plus I got to work with the canvas element on a lower level than I’m accustomed to.

    So here is an interactive demo.  Set the rule number (from 0 to 255) and hit start.  Some interesting rules to try are 18, 22, 26, 30, 41, 45, 54, 60, 73, 90, 105, 106 , 110, and 150.


  8. Making a Timelapse of a Single Window

    January 8, 2012 by uzimonkey

    I’ve wanted to make timelapses of a single window.  Timelapses are nice, but seeing the whole desktop is not exactly useful.  You waste a lot of space and see a lot of irrelevant things (like Reddit).  There was no program available that will take screenshots of individual programs on a timer, and especially only if they’re the active window, so I wrote one.  It’s written in Ruby and needs the win32-api and win32screenshot gems.  Maybe more, you figure it out.  But at any rate, here is the program.  Use or abuse as you wish.

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    
    require 'win32/api'
    require 'win32/screenshot'
    require 'optparse'
     
    Win32::GetForegroundWindow = Win32::API.new('GetForegroundWindow', 'V', 'L', 'user32')
    Win32::GetWindowText = Win32::API.new('GetWindowText', 'LPI', 'I', 'user32')
    Win32::GetWindowThreadProcessId = Win32::API.new('GetWindowThreadProcessId', 'LP', 'L', 'user32')
     
    def get_active_window
        Win32::GetForegroundWindow.call
    end
     
    def get_window_title(hwnd)
        buf = 0.chr * 260
        Win32::GetWindowText.call(hwnd, buf, 256)
     
        return buf.rstrip
    end
     
    def get_window_pid(hwnd)
        pid = [0].pack('L')
        Win32::GetWindowThreadProcessId.call(hwnd, pid)
        return pid
    end
     
    options = {}
    option_parser = OptionParser.new do|o|
        o.banner = "
    This will take a screenshot of a single window on a timer if and
    only if that window is the active window.  So you can use this to
    make timelapses of a single window without having to worry about
    other windows getting in the way, or about pausing the timelapse
    program while you take a Reddit break (every 5 minutes) or spend
    shameful amounts of time looking at documentation googling for every
    little problem that comes up instead of trying to solve it yourself.
     
    Usage:
      timelapse.rb --title Blender --output D:\Timelapse --interval 10
    ".rstrip.strip
     
        options[:title] = nil
        o.on('-t', '--title TITLE', 'Title of window to capture') do|title|
            options[:title] = title
            options[:title_regexp] = Regexp.new(title, Regexp::IGNORECASE)
        end
     
        options[:output] = nil
        o.on('-o', '--output OUTPUT', 'The output directory') do|output|
            options[:output] = output
        end
     
        options[:interval] = nil
        o.on('-i', '--interval SECONDS', 'Number of seconds between screenshots') do|interval|
            options[:interval] = interval.to_i
        end
    end
     
    option_parser.parse!
     
    if options.values.include?(nil)
        puts option_parser.help
        exit
    end
     
    screenshots = Dir.glob("#{options[:output]}/screenshot*.png")
    if screenshots.empty?
        counter = 0
    else
        counter = screenshots.last.scan(/\d+/).last.to_i + 1
    end
     
    this_pid = get_window_pid(get_active_window)
     
    loop do
        active_window = get_active_window
        if( get_window_pid(active_window) != this_pid && get_window_title(active_window) =~ options[:title_regexp])
            puts "Taking screenshot at #{Time.now}"
            Win32::Screenshot::Take.of(:foreground).write("#{options[:output]}/screenshot#{counter}.png")
            counter += 1
        end
     
        sleep options[:interval]
    end
    require 'win32/api'
    require 'win32/screenshot'
    require 'optparse'
    
    Win32::GetForegroundWindow = Win32::API.new('GetForegroundWindow', 'V', 'L', 'user32')
    Win32::GetWindowText = Win32::API.new('GetWindowText', 'LPI', 'I', 'user32')
    Win32::GetWindowThreadProcessId = Win32::API.new('GetWindowThreadProcessId', 'LP', 'L', 'user32')
    
    def get_active_window
    	Win32::GetForegroundWindow.call
    end
    
    def get_window_title(hwnd)
    	buf = 0.chr * 260
    	Win32::GetWindowText.call(hwnd, buf, 256)
    
    	return buf.rstrip
    end
    
    def get_window_pid(hwnd)
    	pid = [0].pack('L')
    	Win32::GetWindowThreadProcessId.call(hwnd, pid)
    	return pid
    end
    
    options = {}
    option_parser = OptionParser.new do|o|
    	o.banner = "
    This will take a screenshot of a single window on a timer if and
    only if that window is the active window.  So you can use this to
    make timelapses of a single window without having to worry about
    other windows getting in the way, or about pausing the timelapse
    program while you take a Reddit break (every 5 minutes) or spend
    shameful amounts of time looking at documentation googling for every
    little problem that comes up instead of trying to solve it yourself.
    
    Usage:
      timelapse.rb --title Blender --output D:\Timelapse --interval 10
    ".rstrip.strip
    
    	options[:title] = nil
    	o.on('-t', '--title TITLE', 'Title of window to capture') do|title|
    		options[:title] = title
    		options[:title_regexp] = Regexp.new(title, Regexp::IGNORECASE)
    	end
    
    	options[:output] = nil
    	o.on('-o', '--output OUTPUT', 'The output directory') do|output|
    		options[:output] = output
    	end
    
    	options[:interval] = nil
    	o.on('-i', '--interval SECONDS', 'Number of seconds between screenshots') do|interval|
    		options[:interval] = interval.to_i
    	end
    end
    
    option_parser.parse!
    
    if options.values.include?(nil)
    	puts option_parser.help
    	exit
    end
    
    screenshots = Dir.glob("#{options[:output]}/screenshot*.png")
    if screenshots.empty?
    	counter = 0
    else
    	counter = screenshots.last.scan(/\d+/).last.to_i + 1
    end
    
    this_pid = get_window_pid(get_active_window)
    
    loop do
    	active_window = get_active_window
    	if( get_window_pid(active_window) != this_pid && get_window_title(active_window) =~ options[:title_regexp])
    		puts "Taking screenshot at #{Time.now}"
    		Win32::Screenshot::Take.of(:foreground).write("#{options[:output]}/screenshot#{counter}.png")
    		counter += 1
    	end
    
    	sleep options[:interval]
    end

  9. The Running Man

    January 7, 2012 by uzimonkey

    This took much longer than I’d like to admit, but the results are looking good.  My next game will feature a running man and I thought it best to start by drawing him.  I wanted a high quality running animation and that’s not something I’m capable of doing in pixel art.  So, back to blender.  Rig up a model and make a running animation.  It’s kind of tricky to get right, but this is looking pretty good.  He looks a bit robotic, but I think that’s because he doesn’t move his back at all as he’s running.  That can be fixed, I’d say the running animation is 90% done, and that’s (surprisingly) a large portion of the assets (as far as hours required) finished.  The code for this should be a snap too!


  10. Not Dead

    January 5, 2012 by uzimonkey

    It’s been a while, and I have nothing useful for anyone today, but I’m just saying that I’m not dead.  I’m busy learning the things I’ll need for the next Ludum Dare in about 3 months.  I’m continuing to work in Blender, right now I’m working on modelling and rigging characters so I can do something a bit more organic and animated next time.  I’m also working on music.  I’m learned to play the piano a bit and in a while I’ll start working on composing.  I don’t think I’ll actually be performing and recording for LD, but it’ll certainly help when it comes to working in MilkyTracker.

    But I’ve come up with a plan for some small games.  Once I can model a character reasonably well I’ll do the assets I’ll need for the first one (mostly the run cycle) and putting the rest together should be a snap with ImpactJS.