Assignment

- Modify an existing PCB board design to include a button
- Read the AT44 data sheet
- Modify an assembly language program to have the button do something
- Modify a C program to have the button do something

How to do this on a Mac running OSX 10.5.8 (Leopard) and using USB->serial cables (dasa) to program the AVR:

If you are using an intel mac running leopard (NOT snow leopard), you might find it handy to have the assembler to compile assembly language so you don't have to use windows/bootcamp. We found this hard to find, so we have made our own assembler by downloading pascal and compiling the source code of the assembler found here:

gerd's avr assembler

Here is the compiled assembler that you should just be able to use:

gavrasm.zip

To modify the board, it seemed easiest to do this directly in cad.py by editing the drawing code in the "define board" section like this:

#
# define board
#

width = 1.1
height = 1.02
x = 1
y = 1
z = -.005
w = .016
mask = .004

pcb = PCB(x,y,width,height,mask)

IC1 = ATtiny44_SOICN('IC1\nt44')
pcb = IC1.add(pcb,x+.54,y+.6,z)

J1 = header_ICP('J1')
pcb = J1.add(pcb,IC1.x+.05,IC1.pad[7].y-.24,z,angle=0)

button= button_6mm('B1')
pcb=button.add(pcb,IC1.pad[14].x+.22,IC1.pad[14].y-.09,z,angle=0)

pcb= wire(pcb,w,
   IC1.pad[14],
   button.pad[1])

pcb= wire(pcb,w,
   IC1.pad[12],
   button.pad[2])
  

I chose to fab my board on the vinyl cutter, and the resulting board looked like this:

To modify the assembly language code to talk to/from the button, you must define some terms (using .equ), then initialize the button (using the sbi and cbi commands), then insert a couple lines of code that skip the next command under certain circumstances (the sbis command).

Here is the modified assembler code that simply checks whether the button is pushed and outputs the state of the bit (nothing fancy):

;
; hello.echo.44.asm
;
; 115200 baud serial echo and LED hello-world program
;
; Neil Gershenfeld
; CBA MIT 10/12/09
;
; (c) Massachusetts Institute of Technology 2009
; Permission granted for experimental and personal use;
; license for commercial sale available from MIT.
;

.include "tn44def.inc"

.equ led_pin = PB2; LED pin
.equ led_port = PORTB; LED port
.equ led_dir = DDRB; LED dir
.equ txpin = PA6; transmit pin
.equ rxpin = PA7; receive pin
.equ comm_port = PORTA; comm port
.equ comm_dir = DDRA; comm direction
.equ comm_pins = PINA; comm pins
.equ button_pin=PA1; button receive pin
.equ button_port = PORTA; buttons port
.equ button_dir= DDRA; button direction
.equ button_pins = PINA; button pins
.def bitcnt = R16; bit counter
.def temp = R17; temporary storage
.def temp1 = R18; temporary storage
.def txbyte = R19; transmit byte
.def rxbyte = R20; receive byte

;
; print
; 
.macro print
   ldi zl,low(@0*2)
   ldi zh,high(@0*2)
   rcall print_db
   .endmacro

.cseg
.org 0
rjmp reset

;
; half_bit_delay
; serial half bit delay
;
half_bit_delay:
   ldi temp, 25; 115200 baud (20 MHz clock /1)
   half_bit_delay_loop:
      dec temp
      brne half_bit_delay_loop
   ret
;
; putchar
; assumes no line driver (doesn't invert bits)
;
putchar:
   ldi bitcnt, 10; 1 start + 8 data + 1 stop bit
   com txbyte; invert everything
   sec; set start bit
   putchar0:
      brcc putchar1; if carry set
      sbi comm_port, txpin; send a '0'
      rjmp putchar2; else	
   putchar1:
       cbi comm_port, txpin	; send a '1'
       nop; even out timing
   putchar2:
       rcall half_bit_delay; bit delay
       rcall half_bit_delay; " 
       lsr txbyte; get next bit
       dec bitcnt; if not all bits sent
       brne putchar0; send next bit
   ret;
;
; getchar
; assumes no line driver (doesn't invert bits)
;
getchar:
   ldi bitcnt, 9; 8 data + 1 stop bit
   getchar1:
      sbis comm_pins, rxpin; wait for start bit
      rjmp getchar1
   rcall half_bit_delay; delay to middle of bit
   getchar2:
      rcall half_bit_delay; bit delay
      rcall half_bit_delay; "
      clc; clear carry
      sbis comm_pins, rxpin; if RX pin high skip
         sec; otherwise set carry
      dec bitcnt
      breq getchar3; return if all bits read
      ror rxbyte; otherwise shift bit into receive byte
      rjmp getchar2; go get next bit
   getchar3:
      ret
;
; blink_delay
; LED blink delay
;
blink_delay:
   ldi temp, 255
   blink_delay_loop:
      ldi temp1, 255
      blink_delay_loop1:
         dec temp1
         brne blink_delay_loop1
      dec temp
      brne blink_delay_loop
   ret
;
; blink
; blink the LED
;
blink:
   sbi led_port, led_pin
   rcall blink_delay
   cbi led_port, led_pin
   ret
;
; print_db
; prints a null-terminated .db string
;
print_db:
   print_loop:
      lpm
      mov txbyte,R0
      cpi txbyte,0
      breq return
      rcall putchar
      adiw zl, 1
      rjmp print_loop
   return:
      ret
;
; main program
;
reset:
   ;
   ; set fuse low byte to 0x7E for 20 MHz resonator
   ;
   ; set clock divider to /1
   ;
   ldi temp, (1 << CLKPCE)
   ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0)
   out CLKPR, temp
   out CLKPR, temp1
   ;
   ; set stack pointer to top of RAM
   ;
   ldi temp, high(RAMEND)
   out SPH, temp
   ldi temp, low(RAMEND)
   out SPL, temp
   ;
   ; init comm pin
   ;
   sbi comm_port, txpin
   sbi comm_dir, txpin
   ;
   ; init LED pins
   ;
   cbi led_port, led_pin
   sbi led_dir, led_pin
   ;
   ; init button pins
   ;
   sbi button_port, button_pin
   cbi button_dir, button_pin
   ;
   ; start main loop
   ;
   loop: 
     rcall getchar
      print message
         message: .db "received character: ",0
      mov txbyte, rxbyte
      rcall putchar

      ldi txbyte,49
      sbis button_pins, button_pin
      ldi txbyte,48
      rcall putchar

      ldi txbyte,10
      rcall putchar
      rcall blink
      rjmp loop

Once this code is modified, you must then reassemble it using whatever assembler you can. If you're running an intel mac, you can either use bootcamp or parallels and do this in windows using one of the compilers listed on the class webpage, or you can use the process I describe above to assemble it on the mac. I did the latter, and issued the following command:

gavrasm hello.echo.44.asm

This assembles the program and creates a hex file that can be sent to the AT44.

Programming the AT44

Now, you can hook up your cables in the same configuration as the hello world board. TAKE GREAT CARE TO PUT YOUR HEADERS ON CORRECTLY OR YOU COULD FRY PART OR ALL OF YOUR BOARD! The 6-pin programming header should be exactly like the last assignment, and the 4-pin communications header is rotated 90 degrees - with no modifications to the one given to us in class, this meant that my two cables came out parallel to each other on one side of the board:

Hook up the one of the USB->serial cables to the computer. Open a terminal and find out what port it's on. Modify Neil's avrdude command from the first week - make sure you include the right port and AT44 instead of AT45 and the real name of your hex file.