Archive for the ‘Uncategorized’ Category

External monitor with Ubuntu NVidia driver and HP OMEN 15-ek0062la – 15.6″ (1M1L9LA)

19/02/2023

This laptop has an NVidia TU117M [GeForce GTX 1650 Ti Mobile].

External monitors do not work with the recommended nvidia driver, but do work with nvidia-driver-470. It might be necessary to run sudo prime-select nvidia.

Implementing JTAG in IPython Notebook with the FT232

17/09/2015

I had an ATMEGA162 lying around and nothing to program it with, so I implemented the JTAG programming protocol connecting the ATMEGA to the PC with an FT232 USB to serial adapter. To make this an amenable experience I used IPython Notebook, which allowed me to quickly test code snippets, see the output, and finally convert everything into a .py file. You can download the original IPython notebook, read the finished program or follow the implementation process on this post, painstakingly converted to wordpress HTML.

We’re using synchronous bitbang mode on the FT232R, which batches communications for extra speed. The procedure is:

  1. Build the waveform
  2. Output the whole thing
  3. Read the response

For every byte clocked out, the response will have a byte with the state of the input pins before the output pins changed. The JTAG interface shifts bits out of TDO on the rising edge of TCK. Therefore, if we send a rising edge on byte N then we must read TDO on the response byte N+1.

Atmega162 datasheet p. 250:

Programming through the JTAG interface requires control of the four JTAG specific pins: TCK,
the JTAG Interface TMS, TDI, and TDO. Control of the Reset and clock pins is not required

pinout

Let’s connect the JTAG pins to FT232 data pins, leaving D0 and D1 free for serial communications later.

    FT232   ATMEGA  PIN
    --------------------
    D4      TMS     26
    D2      TDI     28
    D3      TDO     27
    D5      TCK     25
    GND     GND     20
from pylibftdi import BitBangDevice
from pylibftdi.driver import BITMODE_SYNCBB
TMS = 1 << 4
TDI = 1 << 2
TDO = 1 << 3
TCK = 1 << 5
dev = BitBangDevice(bitbang_mode=BITMODE_SYNCBB)
dev.direction = TMS | TDI | TCK

First we test the driver, wiring and my understanding of this state diagram

tapcontroller

by reading the device identification register. The 1s and 0s in the state diagram show how the state transitions depend on TMS at the clock edge.

stream = [0]
def clock_in(bits):
    """Output bits then raise TCK. 
    Returns index of (input state after the rising TCK edge) in the response array."""
    stream.append(bits)
    stream.append(bits | TCK)
    return len(stream)

# Take TAP controller from Test-Logic-Reset to Run-Test/Idle
for ii in range(2):
    clock_in(0)
# Take TAP to Shift-IR
for tms in [1,1,0,0]:
    clock_in(tms * TMS)
# Shift IDCODE (0x1) into IR
for ir in [1,0,0,0]:
    clock_in(ir * TDI)
# MSB of IR is shifted with TMS high
stream[-2] |= TMS
stream[-1] |= TMS
# Take TAP to Run-Test/Idle, then Shift-DR
for tms in [1,0,1,0,0]:
    clock_in(tms * TMS)
# Shift out 32 bits of ID register
for ii in range(32):
    retindex = clock_in(0)
stream[-1] |= TMS
for tms in [1,0]:
    clock_in(tms * TMS)
clock_in(0)
dev.flush()
dev.write(bytearray(stream))
ret = dev.read(len(stream)); len(ret)
''.join(['01'[rr & TDO != 0] for rr in ret[retindex:retindex-64:-2]])

‘01111001010000000100000000111111’

We can check this string against the datasheet:

idcode

Everything matches, including the version 0x7 = revision H.

Let’s package the previous sequence into a general use function.

from math import ceil
from enum import Enum
class AVR_JTAG(Enum):
    # (instruction register value, number of bits in selected data register)
    IDCODE        = (0x1, 32)
    PROG_ENABLE   = (0x4, 16)
    PROG_COMMANDS = (0x5, 15)
    PROG_PAGELOAD = (0x6, 1024)
    PROG_PAGEREAD = (0x7, 1032)
    AVR_RESET     = (0xC, 1)
    BYPASS        = (0xF, 1)
def jtag_command(instruction, data):
    """Set the instruction register, shift in bits from data, return the output bits
    data[0] holds the least significant bits"""
    if not isinstance(instruction, AVR_JTAG):
        raise ValueError("instruction must be member of AVR_JTAG")
    irvalue = instruction.value[0]
    nbits = instruction.value[1]
    if isinstance(data, int):
        data = data.to_bytes(ceil(nbits/8), 'little')
    stream = [0]
    IR_LENGTH = 4
    def clock_in(bits):
        """Output bits then raise TCK. 
        Returns index of (input state after the rising TCK edge) in the response array."""
        stream.append(bits)
        stream.append(bits+TCK)
        return len(stream)
    # Take TAP controller from Test-Logic-Reset to Run-Test/Idle
    for ii in range(2):
        clock_in(0)
    # Take TAP to Shift-IR
    for tms in [1,1,0,0]:
        clock_in(tms * TMS)
    # Shift IDCODE (0x1) into IR
    for bit in range(IR_LENGTH):
        clock_in((irvalue & 1) * TDI)
        irvalue >>= 1
    # MSB of IR is shifted with TMS high
    stream[-2] |= TMS
    stream[-1] |= TMS
    # Take TAP to Run-Test/Idle, then Shift-DR
    for tms in [1,0,1,0,0]:
        clock_in(tms * TMS)
    # Shift out nbits of data register
    # data[0] is LSB
    retindex = None
    for bit in range(nbits):
        byte = int(bit / 8)
        if byte < len(data):
            ret = clock_in(TDI*bool(
                (data[byte] >> (bit%8)) & 1))
        else:
            # Pad with zeros
            ret = clock_in(0)
        if bit == 0:
            retindex = ret
        #data[int(bit / 8)] >>= 1
    # MSB of DR is shifted with TMS high
    stream[-2] |= TMS
    stream[-1] |= TMS
    # Take TAP to Run-Test/Idle
    for tms in [1,0]:
        clock_in(tms * TMS)
    clock_in(0)
    dev.flush()
    # Return buffer
    bytes = bytearray(ceil(nbits / 8))
    CHUNK_SIZE = 256
    read = []
    for offset in range(0, len(stream), CHUNK_SIZE):
        written = dev.write(bytearray(stream[offset:offset+CHUNK_SIZE]))
        read.append(dev.read(written))
    ret = b''.join(read)
    for bit in range(nbits):
        bytes[int(bit / 8)] |= bool(ret[retindex + 2 * bit] & TDO) << (bit % 8)
    return bytes
idregister = jtag_command(AVR_JTAG.IDCODE, bytearray(4))

Let’s try reading a page from Flash (p. 261)

flashread

As a check, I’ll read one page with page commands and with byte commands, and see if they match.

jtag_command(AVR_JTAG.AVR_RESET, 1)
jtag_command(AVR_JTAG.PROG_ENABLE, 0xA370)
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2302) # Enter Flash Read
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0700) # Load Address High Byte
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0300) # Load Address Low Byte
page = jtag_command(AVR_JTAG.PROG_PAGEREAD, 0)[1:]
page2 = bytearray(len(page))
for address in range(int(len(page2)/2)):
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0700)
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0300+address)
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3200)
    page2[2*address] = jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3600)[0]
    page2[2*address+1] = jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700)[0]
page == page2

True

Now let’s write a program to blink a LED. We’ll just have a 2 byte counter and output the MSB on PORTB. Since we’re not setting the direction, the port pins will toggle between high-impedance and a 20kΩ pull-up. This means we can connect the LED directly between the port pin and ground.

; FILE blink.S
#include <avr/io.h>
loop: adiw r24,1 ; Add 1 to r25:r24
out _SFR_IO_ADDR(PORTB), r25 ; Write MSB to PORTB
rjmp loop ; Repeat

We automate assembly and linking with Make:

# FILE Makefile
CC=avr-gcc
LD=avr-ld
ASFLAGS=-mmcu=atmega162 -Wa,--gen-debug
LDFLAGS=-nostdlib

OBJ=blink

all: $(OBJ)

.PHONY: dump clean

dump:
LANG=EN avr-objdump -d $(OBJ)

clean:
rm -rf $(OBJ)

Assemble and link blink.S

$ make
avr-gcc -mmcu=atmega162 -Wa,--gen-debug -nostdlib blink.S -o blink

We can look at the machine code using avr-objdump:

$ avr-objdump -d blink
LANG=EN avr-objdump -d blink

blink: file format elf32-avr

Disassembly of section .text:

00000000 <__ctors_end>:
0: 01 96 adiw r24, 0x01 ; 1
2: 98 bb out 0x18, r25 ; 24
4: fd cf rjmp .-6 ; 0x0 <__ctors_end>

Our program boils down to the machine code 0x019698bbfdcf. Let’s write it to Flash, following the instructions in the datasheet (p. 260)

from time import sleep
program = 0xcffdbb989601 # Reversed byte order due to endianness
jtag_command(AVR_JTAG.AVR_RESET, 1)
jtag_command(AVR_JTAG.PROG_ENABLE, 0xA370)
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2380) # Chip Erase
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3180) # Chip Erase
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3380) # Chip Erase
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3380) # Chip Erase
sleep(10e-3) # Wait for chip erase
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2310) # Enter Flash Write
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0700) # Load Address High Byte
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0300) # Load Address Low Byte
jtag_command(AVR_JTAG.PROG_PAGELOAD, program)
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700) # Write Flash Page
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3500) # Write Flash Page
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700) # Write Flash Page
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700) # Write Flash Page
sleep(5e-3) # Wait for Flash write
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2302) # Enter Flash Read
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0700) # Load Address High Byte
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0300) # Load Address Low Byte
pagenew = jtag_command(AVR_JTAG.PROG_PAGEREAD, 0)[1:]
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2300) # Exit Programming Mode
jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3300) # Exit Programming Mode
jtag_command(AVR_JTAG.PROG_ENABLE, 0)
jtag_command(AVR_JTAG.AVR_RESET, 0)
# Verify
int.from_bytes(pagenew[:int(program.bit_length()/8)], 'little')==program

True

The program works, although it’s blinking almost too fast to tell.

We’d like to avoid typing machine code by hand. Let’s have a function read the output’s .text section and write that into Flash:

from elftools.elf.elffile import ELFFile
def program_elf(file, verify=True):
    """Write executable into atmega162 program memory. Example:
    
        >>> program('elffile')
    """
    elf = ELFFile(open(file, 'rb'))
    program = elf.get_section_by_name(b'.text').data()
    jtag_command(AVR_JTAG.AVR_RESET, 1)
    jtag_command(AVR_JTAG.PROG_ENABLE, 0xA370)
     # Chip Erase
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2380)
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3180)
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3380) 
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3380)
    sleep(10e-3) # Wait for chip erase
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2310) # Enter Flash Write
    PAGE_BYTES = int(1024 / 8)
    for offset in range(0, len(program), PAGE_BYTES):
        address = offset >> 1 # Flash words are 2 bytes
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0700 | (address>>8) & 0xff) # Load Address High Byte
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0300 | address & 0xff) # Load Address Low Byte
        jtag_command(AVR_JTAG.PROG_PAGELOAD, program[offset:offset+PAGE_BYTES])
         # Write Flash Page
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700)
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3500)
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700)
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700)
        sleep(10e-3) # Wait for Flash write
    if verify:
        jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2302) # Enter Flash Read
        for offset in range(0, len(program), PAGE_BYTES):
            address = offset >> 1 # Flash words are 2 bytes
            jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0700 | (address>>8) & 0xff) # Load Address High Byte
            jtag_command(AVR_JTAG.PROG_COMMANDS, 0x0300 | address & 0xff) # Load Address Low Byte
            read = jtag_command(AVR_JTAG.PROG_PAGEREAD, 0)[1:]
            if read[:len(program)-offset] != program[offset:offset+PAGE_BYTES]:
                raise RuntimeError('Verification failed at offset {}: wrote {}, read {}'.format(
                    offset, program[offset:offset+PAGE_BYTES], read))
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2300) # Exit Programming Mode
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3300) # Exit Programming Mode
    jtag_command(AVR_JTAG.PROG_ENABLE, 0)
    jtag_command(AVR_JTAG.AVR_RESET, 0)
program_elf('/home/ignamv/programacion/avr/blinkc', verify=True)

Now it’s time for the fuses, so we can set the clock source and other configuration bits. This is straight from page 262 of the datasheet:

def poll_fuse_write_complete():
    while True:
        if jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700)[1] & 2:
            break
def program_fuses(fuses, extended_fuses):
    if not isinstance(fuses, int):
        raise TypeError('Expected int for fuses')
    jtag_command(AVR_JTAG.AVR_RESET, 1)
    jtag_command(AVR_JTAG.PROG_ENABLE, 0xA370)
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2340) # Enter Fuse Write
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x1300 | (extended_fuses & 0xff)) # Load Data Low Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3b00) # Write Fuse Extended Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3900) # Write Fuse Extended Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3b00) # Write Fuse Extended Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3b00) # Write Fuse Extended Byte
    poll_fuse_write_complete()
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x1300 | ((fuses >> 8) & 0xff)) # Load Data Low Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700) # Write Fuse High Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3500) # Write Fuse High Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700) # Write Fuse High Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700) # Write Fuse High Byte
    poll_fuse_write_complete()
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x1300 | (fuses & 0xff)) # Load Data Low Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3300) # Write Fuse High Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3100) # Write Fuse High Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3300) # Write Fuse High Byte
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3300) # Write Fuse High Byte
    poll_fuse_write_complete()
def read_fuses_locks():
    jtag_command(AVR_JTAG.AVR_RESET, 1)
    jtag_command(AVR_JTAG.PROG_ENABLE, 0xA370)
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x2304) # Enter Fuse/Lock Bit Read
    jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3a00) # Read fuses and lock bits
    extended = jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3e00)[0] # Read fuses and lock bits
    high = jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3200)[0] # Read fuses and lock bits
    low = jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3600)[0] # Read fuses and lock bits
    lock = jtag_command(AVR_JTAG.PROG_COMMANDS, 0x3700)[0] # Read fuses and lock bits
    return extended, high << 8 | low, lock
extended, fuses, lock = read_fuses_locks()
print([hex(d) for d in [extended, fuses, lock]])

[‘0xff’, ‘0x99ff’, ‘0xff’]

Future posts might cover linking and linker scripts, because you really shouldn’t write unlinked object files to Flash.

We have oscillation! Buffered VCO from Experimental Methods in RF Design

09/09/2015

To begin playing with RF I need a signal source, so I built a buffered VCO from Experimental Methods in RF Design[1]. It took a few tries to get a barely functional toner transfer with my clothes iron, so I’m thinking of using UV next time.

layout
dcreceiver
IMG_20150908_115700

I’ll have to look into that saturation at the top of the signal. Also the tuning range is quite narrow (the original design tuned over 50kHz), but I’ll know for sure once I finish the analog front end for my frequency counter.

[1]W. H. Hayward, R. Campbell, and B. Larkin, Experimental Methods in RF Design, Revised 1st Edition edition. Newington, CT: Amer Radio Relay League, 2009.

Automatically place footprints to match schematic in Kicad

03/09/2015

When you first start Kicad’s PCB editor pcbnew and read a netlist, all of the components are piled up in one place. I wrote a script that takes the schematic and pcb files and moves the footprints to match their placement in the schematic. This is a nicer starting point to route your PCB. To run it, just download the script and drag your project into the script icon (more detailed instructions in the link above).

schematic pcb

You do need to open pcbnew and read the netlist in order to generate the initial .kicad-pcb file.

Pulse testing JFETs

27/08/2015

JFETs show up all over Wes Hayward’s books1 2, mostly on oscillators. For those only familiar with bipolars and MOSFETs, an N-channel JFET is like an N-channel MOSFET except:

  • The threshold voltage is negative: Vt = -Vp
  • The gate-source junction is a diode that must never be forward biased.

I bought a bunch of J310 N-channel JFETs. However, the specs on these parts are all over the place:

specs
So I decided to measure Idss and Vp. Turns out that the J310 will destroy itself if saturated at Idss, so the test has to be fast. I hooked up an HP8112 pulse generator to the gate and biased the drain with a small resistor to ensure saturation:
JFET pulse testing circuit
I extracted the parameters from the oscilloscope capture with a short IPython notebook:

import scipy as sp
import scipy.optimize
%matplotlib inline
from matplotlib import pyplot as plt

Vg = sp.loadtxt('jfets/DS0000.CSV', skiprows=14, delimiter=',', usecols=(0,)) / (2**8) * 10 * 2.
for ii in range(1, 4):
    Vd = sp.loadtxt('jfets/DS{:04d}.CSV'.format(ii), skiprows=14, delimiter=',', usecols=(0,)) / (2**8) * 10 * .5
    #Vd = Vd[Vg > -6]
    #Vg = Vg[Vg > -6]
    Vcc = 12
    Rd = 22
    Id = (Vcc - Vd) / Rd
    Id -= sp.mean(Id[Vg < -7])
    plt.figure(figsize=(3,3))
    plt.plot(Vg, Id*1e3, '.', color=(.5,.5,.5), label='Measured')
    def Idsat(Vg, Idss, Vp):
        return Idss * (1. - sp.maximum(Vg, Vp) / Vp)**2
    def ferror(x, Vg, Id):
        Vp, Idss = x
        return Id - Idsat(Vg, Idss, Vp)
    (Vp, Idss), _ = sp.optimize.leastsq(ferror, [-4, 55e-3], (Vg[Vg > -6], Id[Vg > -6]))
    plt.title('I$_{{dss}}$={:.0f}mA, V$_p$={:.1f}V'.format(Idss*1e3, Vp))
    Vg2 = sp.linspace(min(Vg), max(Vg), 200)
    plt.plot(Vg2, 1e3*Idsat(Vg2, Idss, Vp), 'r-', linewidth=2)
    plt.xlabel('V$_{gs}$ (V)')
    plt.ylabel('I$_d$ (mA)')
    plt.xticks(range(-8,1,4))
    plt.yticks(range(0,50,20))
    plt.tight_layout()
    plt.savefig('jfets/device{:02d}.png'.format(ii), dpi=300)

The three devices I tested are clustered pretty close on both parameters:
device01

device02

device03
[1]W. H. Hayward, R. Campbell, and B. Larkin, Experimental Methods in RF Design, Revised 1st Edition edition. Newington, CT: Amer Radio Relay League, 2009.
[2]W. H. Hayward and D. Demaw, Solid state design for the radio amateur. American Radio Relay League, 1986.

Run applications from RAM in Stellaris Launchpad

02/01/2015

I made a program to load applications to RAM and run them in the Stellaris Launchpad. On reset, it reads an SREC file from the serial port and copies it to RAM. It points the vector table to the load location (so interrupts work normally) and jumps to the application’s main() function.

The first problem was reserving RAM for the loaded application. To do this, I modified my linker script by splitting the RAM into two sections, and keeping the loader in the first section.

Afterwards, the application has to be linked so that it will run from RAM. This means using another linker script that puts it on the second section of RAM. It also places the vector table at the beginning so that the loader knows where it is.

The loader itself is a minimal SREC parser which implements the records that showed up in my SREC files.

To play around with the loader, it’s possible to make SREC files from the SDK example projects. This requires changing the entry point and linker script in the Makefile. For example, to compile project0 we change
SCATTERgcc_project0=project0.ld
ENTRY_project0=ResetISR

to
SCATTERgcc_project0=../linkprogram.ld
ENTRY_project0=main

. Then we have to change the startup script in startup_gcc.c . Normally the reset routine would copy data from Flash to RAM to initialize variables, but this isn’t necessary when running from RAM. So comment out ResetISR and change the reset vector to (void (*)(void) main.

After these changes, the AXF file generated by make will be good for running from RAM. To get the SREC file, use objdump and sed to strip the header:

arm-none-eabi-objcopy -S -O srec --srec-len=8 project0/gcc/project0.axf project0/gcc/project0.srec
# Strip header
sed -i /^S0/d project0/gcc/project0.srec

I’ve automated this last step with a rule in the Makefile. This works successfully with usb_dev_mouse, project0, qs-rgb and probably all the other example projects.

Minecraft stronghold finder

18/02/2014

I wrote a simple app to triangulate Strongholds in Minecraft. Instead of wasting a bunch of Eyes of Ender trying to get to a Stronghold, you can just do a couple of throws and get a good estimate of its position.

You can check out the app or look at the source code

Python bindings for Ngspice

17/02/2014

I wrote a set of Python bindings for the Ngspice simulation engine. It’s meant to add the clarity and power of Python to electronics simulations. For instance, you can simulate a circuit while varying different parameters and produce highly customized plots of your results, while minimizing your exposure to SPICE syntax.

More details on the project page.

Build your own Wigner-Seitz cells

18/08/2013

I made templates you can print out to build the Wigner-Seitz cells for hexagonal, body-centered cubic and face-centered cubic crystals. Check out the ideal result:

hexagonal_thumb bcc_thumb fcc_thumb

And the actual result:

Hexagonal photoBCC photoFCC photo

You can print these out to build your own:

I used blender to model the cells in 3D and UV-unwrapped them into svg files. These I edited with inkscape to add the edge tabs.

Deploying Flask to Apache2 on Ubuntu 13.04

09/07/2013

I had some trouble deploying a Flask app with Apache2, so here’s a minimum working configuration.

Virtual environment setup

virtualenv appname
cd appname
source bin/activate
pip install flask
mkdir -p src/appname www
echo "site.addsitedir(os.path.join(base, 'src'))" >> bin/activate_this.py
echo "from .appname import *" > src/appname/__init__.py
cat > src/appname/appname.wsgi <<EOF
activate_this = '/path/to/virtualenv/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

from appname import app as application
EOF
cat > src/appname/appname.py <<EOF
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Success?"

if __name__ == '__main__':
    app.run()
EOF

Virtual host configuration

<VirtualHost *:80>
    ServerName host.name
    ServerAlias www.host.name
    DocumentRoot /path/to/virtualenv/www
    <Directory /path/to/virtualenv/www>
        Order allow,deny
        Allow from all
    </Directory>
    WSGIScriptAlias /connote /path/to/virtualenv/src/connote/connote.wsgi
    WSGIDaemonProcess host.name processes=2 threads=15
    WSGIProcessGroup host.name
    <Directory /path/to/virtualenv/src/connote>
        Order allow,deny
        Allow from all
    </Directory>
    ErrorLog /path/to/virtualenv/var/error.log
    LogLevel debug
</VirtualHost>