;SIC PROJECT 056 LOW-COST PCB MILLING MACHINE ;INITIAL VERSION FOR MIT COURSE 2 BACHELOR'S THESIS "Rapid Prototyping of Rapid Prototyping Machines" SUPERVISED BY NEIL GERSHENFELD, DIRECTOR, MIT CBA ;--REVISION HISTORY----------------------------------------------------------------------- ; ; --------------------------------------------------------------------------------- ; | DATE | MODIFICATIONS | NAME |FILENAME | ; |--------|---------------------------|-------------------|-----------------------| ; |03/09/08| CREATED |ILAN E MOYER |i0.smc.03.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |12/31/08| SPIFFIFIED |ILAN E MOYER |056-054.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |3/20/09 | ADDED HALF-STEPPING |ILAN E MOYER |056-054b.asm | I changed the format of motorpositions to allow 8 half-positions ; |--------|---------------------------|-------------------|-----------------------| ; |3/20/09 | FIXED SINGLE-STEP ISSUE |ILAN E MOYER |056-054c.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |11/29/09| MODIFIED FOR NETWORKING |ILAN E MOYER |056-054d.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |12/08/09| ADDED VM URL RESPONSE |ILAN E MOYER |056-054e.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |12/13/09| ADDED 3-AXIS MOTION |ILAN E MOYER |056-054f.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |01/06/10| REFACTORED FOR FABINABOX |ILAN E MOYER |076-001a.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |01/07/10| ADDED RX PULLUP, LEDS OFF |ILAN E MOYER |076-001a.asm | RX pullup is necessary to avoid tripping rcv watchdog. Also turned off ind leds after move. ; |--------|---------------------------|-------------------|-----------------------| ; |01/10/10| FIXED MOTION CODE |ILAN E MOYER |076-001b.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |01/12/10| ADDED STATUS RESPONSE |ILAN E MOYER |076-001c.asm | Also fixed push/pop temp3 and temp4 in motion interrupt. ; |--------|---------------------------|-------------------|-----------------------| ; |01/16/10| ADDED BACKLASH COMP. |ILAN E MOYER |076-001c.asm | Also added SEI/CLI when accessing 16 bit registers in main loop ; |--------|---------------------------|-------------------|-----------------------| ; |04/04/10| ADDED PROPER QUEUEING |ILAN E MOYER |076-001e.asm | ; |--------|---------------------------|-------------------|-----------------------| ; |04/26/10| CHANGED FABNET BAUD RATE |ILAN E MOYER |076-001f.asm | Changed to 38.4K to avoid issues with linux serial driver ; ---------------------------------------------------------------------------------- ; ; ; ; ;--HARDWARE CONFIGURATION (076-001 REV1)--------------------------------------------- ; ; ; ; ; ; ; ; ; X ; T ; X A ; X ; E _ I ; N R S ; A E ; B T R S P P P L ; L X X E C C C E ; E D D T 5 4 3 D ; --------------- ; LED| | Y AXIS LED ; BUTTON| | Z AXIS LED ; GND| | ADC7 ; VCC| ATMEGA88 | GND ; GND| | AREF ; VCC| | ADC6 ; XTAL1| | AVCC ; XTAL2| | SCK ; --------------- ; M X X Y Y Z M M ; O O I ; T S D S D S S S ; O T I T I T I O ; R E R E R E / ; S P P P Z ; ; E D ; N I ; A R ; B ; L ; E ; ; ;--PORT B ASSIGNMENTS-------------------------------------------------------------- ; ; PB0 = Y AXIS STEP ; PB1 = Y AXIS DIR ; PB2 = Z AXIS STEP ; PB3 = MOSI / Z AXIS DIR ; PB4 = MISO ; PB5 = SCK ; PB6 = XTAL1 ; PB7 = XTAL2 ; ;--PORT C ASSIGNMENTS-------------------------------------------------------------- ; ; PC0 = Z AXIS INDICATOR LED ; PC1 = Y AXIS INDICATOR LED ; PC2 = X AXIS INDICATOR LED ; PC3 = N/C ; PC4 = N/C ; PC5 = N/C ; PC6 = /RESET ;--PORT D ASSIGNMENTS-------------------------------------------------------------- ; PD0 = RXD ; PD1 = TXD ; PD2 = RS485 TX ENABLE ; PD3 = LED ; PD4 = BUTTON ; PD5 = MOTORS ENABLE ; PD6 = X AXIS STEP ; PD7 = X AXIS DIRECTION ;--INCLUDE FILES------------------------------------------------------------------- ; .DEVICE ATMega88 .include "m88def.inc" ;--DEFINITIONS--------------------------------------------------------------------- ;PORT DIRECTION MASKS ;PACKET LOCATIONS .equ rx_packet_location = 0x0100 ;SRAM start location for rx packet .equ tx_packet_location = 0x0200 ;SRAM start location for tx packet ;PAcKET OFFSETS .equ packet_startbyte = 0 .equ packet_srcaddress0 = 1 .equ packet_srcaddress1 = 2 .equ packet_srcport = 3 .equ packet_destaddress0 = 4 .equ packet_destaddress1 = 5 .equ packet_destport = 6 .equ packet_length = 7 .equ packet_payload = 8 ;PACKET STANDARD VALUES .equ packet_unicast_startbyte = 74 .equ packet_broadcast_startbyte = 138 ;NODE OFFSETS .equ node_address_location = 0x0300 ;SRAM start location for node address ;ANTI-BACKLASH VARIABLES .equ anti_backlash_location = 0x0302 .equ anti_max_steps = 0 ;max steps to be taken .equ anti_x_steps = 1 ;anti-backlash steps to be taken in each direction .equ anti_y_steps = 2 .equ anti_z_steps = 3 .equ anti_max_remaining = 4 ;max steps remaining .equ anti_x_remaining = 5 ;anti-backlash steps remaining in each direction .equ anti_y_remaining = 6 .equ anti_z_remaining = 7 ;MOTION CONTROL SRAM .equ motion_queue_read_frame = 0x030A ;motion control read frame number .equ motion_queue_write_frame = 0x030B ;motion control write frame number .equ motion_queue_read_pointer_0 = 0x030C ;SRAM address of read frame - byte 0 .equ motion_queue_read_pointer_1 = 0x030D ;SRAM address of read frame - byte 1 .equ motion_queue_write_pointer_0 = 0x030E ;SRAM address of write frame - byte 0 .equ motion_queue_write_pointer_1 = 0x030F ;SRAM address of write frame - byte 1 .equ motion_queue_base_address = 0x0310 ;start of motion queue .equ motion_queue_length = 14 ;with a 64 byte stack, 176 bytes avaliable / 12 per frame = 14 packets. .equ motion_frame_length = 12 ;length of each queue frame ;MOTION CONTROL OFFSETS .equ motion_key = 0 .equ motion_directions = 1 .equ motion_maxsteps_0 = 2 .equ motion_maxsteps_1 = 3 .equ motion_xsteps_0 = 4 .equ motion_xsteps_1 = 5 .equ motion_ysteps_0 = 6 .equ motion_ysteps_1 = 7 .equ motion_zsteps_0 = 8 .equ motion_zsteps_1 = 9 .equ motion_topvalue_0 = 10 .equ motion_topvalue_1 = 11 ;MOTION CONTROL BIT DEFINITIONS: .equ x_axis_direction_bit = 0 .equ y_axis_direction_bit = 1 .equ z_axis_direction_bit = 2 ;NODE VALUES .equ node_address0 = 165 .equ node_address1 = 134 ;RECEIVER WATCHDOG CONSTANTS .equ watchdog_trip = 253 ;PORTS: UI .equ button_input = PIND .equ led_output = PORTD .equ led_toggle = PIND ;PORTS: COMM .equ comm_port = PORTD .equ comm_dir = DDRD ;PORTS: MOTION CONTROL .equ motor_enable_ddr = DDRD .equ motor_enable_port = PORTD .equ x_axis_dir_ddr = DDRD .equ x_axis_dir_port = PORTD .equ x_axis_step_ddr = DDRD .equ x_axis_step_port = PORTD .equ x_axis_step_toggle = PIND .equ x_axis_ind_ddr = DDRC ;INDICATOR LED .equ x_axis_ind_port = PORTC .equ x_axis_ind_toggle = PINC .equ y_axis_dir_ddr = DDRB .equ y_axis_dir_port = PORTB .equ y_axis_step_ddr = DDRB .equ y_axis_step_port = PORTB .equ y_axis_step_toggle = PINB .equ y_axis_ind_ddr = DDRC .equ y_axis_ind_port = PORTC .equ y_axis_ind_toggle = PINC .equ z_axis_dir_ddr = DDRB .equ z_axis_dir_port = PORTB .equ z_axis_step_ddr = DDRB .equ z_axis_step_port = PORTB .equ z_axis_step_toggle = PINB .equ z_axis_ind_ddr = DDRC .equ z_axis_ind_port = PORTC .equ z_axis_ind_toggle = PINC ;PINS: UI .equ button = PD4 .equ led = PD3 ;PINS: COMM .equ rx_pin = PD0 .equ tx_pin = PD1 .equ tx_enable = PD2 ;PINS: MOTION CONTROL .equ motor_enable = PD5 .equ x_axis_dir = PD7 .equ x_axis_step = PD6 .equ x_axis_ind = PC2 .equ y_axis_dir = PB1 .equ y_axis_step = PB0 .equ y_axis_ind = PC1 .equ z_axis_dir = PB3 .equ z_axis_step = PB2 .equ z_axis_ind = PC0 ;DIRECTION MASKS .equ portb_directions = (1 << y_axis_step)|(1 << y_axis_dir)|(1 << z_axis_step)|(1 << z_axis_dir) .equ portc_directions = (1 << x_axis_ind)|(1 << y_axis_ind)|(1 << z_axis_ind) .equ portd_directions = (1 << tx_pin)|(1 << tx_enable)|(1 << led)|(1 << motor_enable)|(1 << x_axis_step)|(1 << x_axis_dir) ;PULLUP MASKS .equ portb_pullups = 0 .equ portc_pullups = 0 .equ portd_pullups = (1 << button)|(1 << rx_pin) ;REGISTERS .def numzero = r0 .def current_step_0 = r1 .def packetlength = r2 .def packetchecksum = r3 .def rcv_watchdog = r4 .def delta_a_0 = r5 ;error register a .def delta_b_0 = r6 ;error register b .def delta_c_0 = r7 ;error register c .def delta_x_0 = r8 ;delta_x * 2 .def delta_x_1 = r9 .def delta_y_0 = r10 ;delta_y * 2 .def delta_y_1 = r11 .def delta_z_0 = r12 ;delta_z * 2 .def delta_z_1 = r13 .def delta_max_0 = r14 ;delta_max .def current_key = r15 ;current buffer key position ; working registers .def temp1 = r16 .def temp2 = r17 .def temp3 = r18 .def temp4 = r19 .def packetposition = r20 .def delta_a_1 = r21 ;the high bytes are located in the upper 16 registers because they need ldi access. .def delta_b_1 = r22 .def delta_c_1 = r23 .def delta_max_1 = r24 .def current_step_1 = r25 ; FLAG REGISTERS .equ comm_status = GPIOR0 ;using general purpose IO register to conserve standard registers. .equ packet_received = 0 ;first bit of comm_status. .equ packet_inbound = 1 .equ packet_outbound = 2 .equ now_moving = 3 ;indicates that a move is in progress .equ wait_for_sync = 4 ;if set, reading from queue is paused until sync packet is received. Indicates that a sync motion packet is at the head of the queue. .equ sync_move = 5 ;if set, motion command is only executed upon sync. Also doubles as an indicator for enabling sync packet start. .equ anti_backlash = 6 ;if set, anti-backlash is enabled. .equ buffer_full = 7 ;if set, indicates that the buffer is full. .equ dir_change_flags = GPIOR1 ;stores directional changes for moves. .equ x_axis_dir_change = 0 .equ y_axis_dir_change = 1 .equ z_axis_dir_change = 2 ;SRAM .equ Memory_Start = 0x0060 ;--PROGRAM INITIALIZATION---------------------------------------------------------- .cseg .org 0 ;--INTERRUPT VECTOR TABLE---------------------------------------------------------- rjmp reset ; External Pin, Power-on Reset, Brown-out Reset and Watchdog System .dw 0 ; External Interrupt Request 0 .dw 0 ; External Interrupt Request 1 .dw 0 ; Pin Change Interrupt Request 0 .dw 0 ; Pin Change Interrupt Request 1 .dw 0 ; Pin Change Interrupt Request 2 .dw 0 ; Watchdog Time-out Interrupt .dw 0 ; Timer/Counter2 Compare Match A .dw 0 ; Timer/Counter2 Compare Match B rjmp isr_packet_timeout_100 ; Timer/Counter2 Overflow .dw 0 ; Timer/Counter1 Capture Event rjmp isr_move_gen_100 ; Timer/Counter1 Compare Match A rjmp isr_antibacklash_100 ; Timer/Coutner1 Compare Match B .dw 0 ; Timer/Counter1 Overflow .dw 0 ; Timer/Counter0 Compare Match A .dw 0 ; Timer/Counter0 Compare Match B .dw 0 ; Timer/Counter0 Overflow .dw 0 ; SPI Serial Transfer Complete rjmp isr_packet_receiver_100 ; USART Rx Complete rjmp isr_packet_transmitter_100 ; USART, Data Register Empty rjmp isr_packet_transmitter_100 ; USART, Tx Complete .dw 0 ; ADC Conversion Complete .dw 0 ; EEPROM Ready .dw 0 ; Analog Comparator .dw 0 ; 2-wire Serial Interface .dw 0 ; Store Program Memory Ready ;--INTERRUPT ROUTINES-------------------------------------------------------------- ;-- PACKET RECEIVER -- ; ;This interrupt routine stores data from an incoming packet into SRAM ; isr_packet_receiver_100: cli push ZL push ZH push temp1 push temp2 in temp2, SREG push temp2 push temp3 sts TCNT2, numzero ;clears timer0 mov rcv_watchdog, numzero ;resets watchdog counter ldi temp1, (0 << OCIE0B)|(0 << OCIE0A)|(1 << TOIE0) ;enables timer2 as watchdog for receiver sts TIMSK2, TEMP1 isr_packet_receiver_200: ;load byte into temp1, and store in SRAM lds temp1, UDR0 ldi ZH, high(rx_packet_location) ldi ZL, low(rx_packet_location) add ZL, packetposition adc ZH, numzero st Z, temp1 sbi comm_status, packet_inbound ;sets packet inbound flag isr_packet_receiver_300: ;check for packet length cpi packetposition, packet_length ;see if this byte contains the packet length brne isr_packet_receiver_400 mov packetlength, temp1 ;if YES, store the packet length in packetlength register isr_packet_receiver_400: ;checks for end-of-packet condition cpi packetposition, packet_length brlo isr_packet_receiver_500 ;checks if the packet length byte has been read yet. If YES, checks for end-of-packet cp packetposition, packetlength breq isr_packet_receiver_600 ;if this is end_of_packet, skips the checksum isr_packet_receiver_500: ;calculates the CRC of the packet mov temp3, temp1 eor temp1, packetchecksum ; IN PYTHON: crc = input^crc ldi ZH, high(crc_table*2) ;loads CRC table location into Z pointer ldi ZL, low(crc_table*2) add ZL, temp1 ;offsets Z pointer by value of temp1 adc ZH, numzero lpm packetchecksum, Z ;stores new checksum in packetchecksum inc packetposition rjmp isr_packet_receiver_exit isr_packet_receiver_600: ;check if packet is for us mov temp3, temp1 ;stores a copy of the received byte in temp3 ldi ZH, high(rx_packet_location+packet_startbyte) ;loads packet start byte into temp1 ldi ZL, low(rx_packet_location+packet_startbyte) ld temp1, Z cpi temp1, packet_broadcast_startbyte breq isr_packet_receiver_700 ;broadcast packet, skips address check. cpi temp1, packet_unicast_startbyte brne isr_packet_receiver_900 ;packet bad! ldi ZH, high(rx_packet_location+packet_destaddress0) ;load destination address byte 0 into temp1 ldi ZL, low(rx_packet_location+packet_destaddress0) ld temp1, Z ldi ZH, high(node_address_location) ;load node address byte 0 into temp2 ldi ZL, low(node_address_location) ld temp2, Z cp temp1, temp2 brne isr_packet_receiver_900 ;packet not destined for us! ldi ZH, high(rx_packet_location+packet_destaddress1) ;load destination address byte 0 into temp1 ldi ZL, low(rx_packet_location+packet_destaddress1) ld temp1, Z ldi ZH, high(node_address_location+1) ;load node address byte 0 into temp2 ldi ZL, low(node_address_location+1) ld temp2, Z cp temp1, temp2 brne isr_packet_receiver_900 ;packet not destined for us! isr_packet_receiver_700: ;check packet checksum cp temp3, packetchecksum ;see if checksum matches last byte brne isr_packet_receiver_900 ;checksum bad. For now, ditch packet. Later, this could dispatch a resend-request. isr_packet_receiver_800: ;packet is good, and destined for US! ldi temp1, (0 << OCIE0B)|(0 << OCIE0A)|(0 << TOIE0) ;disables timer0 interrupts sts TIMSK2, TEMP1 sbi comm_status, packet_received ;sets packet waiting flag clr packetposition clr packetchecksum cbi comm_status, packet_inbound ;clears packet inbound flag cbi comm_status, packet_outbound rjmp isr_packet_receiver_exit isr_packet_receiver_900: ;packet either not for us, or checksum is bad. Packet is tossed. ; sts UDR0, numzero ;REMOVE clr packetposition clr packetchecksum cbi comm_status, packet_inbound ;sets packet inbound flag ldi temp1, (0 << OCIE0B)|(0 << OCIE0A)|(0 << TOIE0) ;disables timer2 interrupts sts TIMSK2, TEMP1 isr_packet_receiver_exit: pop temp3 pop temp2 out SREG, temp2 pop temp2 pop temp1 pop ZH pop ZL sei reti ;-- PACKET TRANSMITTER -- ; ; This interrupt routine transmits bytes of a packet whenever they become avaliable. ; isr_packet_transmitter_100: cli push ZL push ZH push temp1 push temp2 in temp2, SREG push temp2 ldi temp1, (1< delta_max, skip to the sauce. Otherwise, check lsb cp delta_a_0, temp3 ;cp delta_a_0, delta_max_0 brlo isr_move_gen_300Y ;delta_a < delta_max, branch to check y axis isr_move_gen_350X: sub delta_a_0, temp1 ;delta_a = delta_a - 2*delta_max sbc delta_a_1, temp2 sbi x_axis_step_port, x_axis_step ;step in X axis sbi x_axis_ind_toggle, x_axis_ind ;toggle x axis indicator led isr_move_gen_300Y: ;check for a step in the X axis mov temp3, delta_max_0 mov temp4, delta_max_1 sub temp3, delta_y_0 ;presubtract error for next move. This avoids roll-overs. Needs reconstitution later! sbc temp4, delta_y_1 cp delta_b_1, temp4 ;cp delta_b_1, delta_max_1 brlo isr_move_gen_300Z ;delta_b < delta_max, branch to check z axis brne isr_move_gen_350Y ;delta_b > delta_max, skip to the sauce. Otherwise, check lsb cp delta_b_0, temp3 ;cp delta_b_0, delta_max_0 brlo isr_move_gen_300Z ;delta_b < delta_max, branch to check z axis isr_move_gen_350Y: sub delta_b_0, temp1 ;delta_b = delta_b - delta_max sbc delta_b_1, temp2 sbi y_axis_step_port, y_axis_step ;step in y axis sbi y_axis_ind_toggle, y_axis_ind ;toggle y axis indicator led isr_move_gen_300Z: ;check for a step in the X axis mov temp3, delta_max_0 ;presubtract error for next move. This avoids roll-overs. Needs reconstitution later! mov temp4, delta_max_1 sub temp3, delta_z_0 sbc temp4, delta_z_1 cp delta_c_1, temp4 ;cp delta_c_1, delta_max_1 brlo isr_move_gen_400 ;delta_c < delta_max, branch to move_gen_400 brne isr_move_gen_350Z ;delta_c > delta_max, skip to the sauce. Otherwise, check lsb cp delta_c_0, temp3 ;cp delta_c_0, delta_max_0 brlo isr_move_gen_400 ;delta_c < delta_max, branch to move_gen_400 isr_move_gen_350Z: sub delta_c_0, temp1 ;delta_c = delta_c - 2delta_max sbc delta_c_1, temp2 sbi z_axis_step_port, z_axis_step ;step in z axis sbi z_axis_ind_toggle, z_axis_ind ;toggle z axis indicator led isr_move_gen_400: ;post-add errors add delta_a_0, delta_x_0 ;delta_a = delta_a + 2*delta_x (delta_x premultiplied when packet was received). adc delta_a_1, delta_x_1 add delta_b_0, delta_y_0 ;delta_b = delta_b + 2*delta_y (delta_y premultiplied when packet was received). adc delta_b_1, delta_y_1 add delta_c_0, delta_z_0 ;delta_c = delta_c + 2*delta_z (delta_z premultiplied when packet was received). adc delta_c_1, delta_z_1 isr_move_gen_420: ;need 20 clock cycle duration on step lines before clearing (1 microsecond + 25% extra) nop nop cbi x_axis_step_port, x_axis_step ;reset x line, it's been 20 cycles between set and shortest path to here. nop nop nop nop cbi y_axis_step_port, y_axis_step ;reset y line, it's been 20 cycles between set and shortest path to here. nop nop nop nop nop cbi z_axis_step_port, z_axis_step ;reset z line, it's been 20 cycles between set and shortest path to here. isr_move_gen_500: ;check if move is over ldi temp1, 1 add current_step_0, temp1 ;increment current_step by 1 adc current_step_1, numzero cp current_step_1, delta_max_1 brne isr_move_gen_exit ;current_step != delta_max, move not over cp current_step_0, delta_max_0 brne isr_move_gen_exit ;current_step != delta_max, move not over rcall run_move isr_move_gen_exit: pop XH pop XL pop ZH pop ZL pop temp4 pop temp3 pop temp2 out SREG, temp2 pop temp2 pop temp1 sei reti ;--------Anti-Backlash Move Generator----------- ; ; This interrupt routine moves the motors a predetermined number of steps prior to a move to eliminate backlash. isr_antibacklash_100: cli push temp1 push temp2 in temp2, SREG push temp2 push temp3 push temp4 push ZH push ZL isr_antibacklash_200: ldi ZH, high(anti_backlash_location + anti_max_remaining) ;points Z to first byte of anti-backlash remaining parameters ldi ZL, low(anti_backlash_location + anti_max_remaining) ld temp4, Z+ ld temp1, Z+ ld temp2, Z+ ld temp3, Z+ in numzero, dir_change_flags ;temporarily steal numzero register, remember to restore later! isr_antibacklash_220: ;X Axis backlash compensation sbrs numzero, x_axis_dir_change rjmp isr_antibacklash_240 ;no direction change in X. Check Y. cpi temp1, 0 breq isr_antibacklash_240 ;done stepping in X sbi x_axis_step_port, x_axis_step ;take step in X sbi x_axis_ind_toggle, x_axis_ind ;toggle X axis indicator led dec temp1 isr_antibacklash_240: ;Y Axis backlash compensation sbrs numzero, y_axis_dir_change rjmp isr_antibacklash_260 ;no direction change in Y. Check Z. cpi temp2, 0 breq isr_antibacklash_260 ;done stepping in Y sbi y_axis_step_port, y_axis_step ;take step in Y sbi y_axis_ind_toggle, y_axis_ind ;toggle Y axis indicator led dec temp2 isr_antibacklash_260: ;Y Axis backlash compensation sbrs numzero, z_axis_dir_change rjmp isr_antibacklash_300 ;no direction change in Z. End stepping. cpi temp3, 0 breq isr_antibacklash_300 ;done stepping in Z sbi z_axis_step_port, z_axis_step ;take step in Z sbi z_axis_ind_toggle, z_axis_ind ;toggle Z axis indicator led dec temp3 isr_antibacklash_300: ;clear step pins nop nop nop nop nop nop nop nop nop nop nop nop nop nop ;been min. 20 clock cycles since X axis step was set cbi x_axis_step_port, x_axis_step ;clears X axis step pin nop cbi y_axis_step_port, y_axis_step ;clears Y axis step pin nop cbi z_axis_step_port, z_axis_step ;clears Z axis step pin clr numzero ;restore numzero to its rightful value isr_antibacklash_400: ;updates remaining steps cpi temp4, 1 ;check for end of compensation breq isr_antibacklash_500 ;compensation over, close up shop dec temp4 ldi ZH, high(anti_backlash_location + anti_max_remaining) ;points Z to first byte of anti-backlash remaining parameters ldi ZL, low(anti_backlash_location + anti_max_remaining) st Z+, temp4 ;store remaining max steps st Z+, temp1 ;store remaining x steps st Z+, temp2 ;store remaining y steps st Z+, temp3 ;store remaining z steps ldi temp2, (1 << PSRSYNC) ;prepare to reset the timer0/timer1 prescalar out GTCCR, temp2 ;resets the timer0/timer1 prescalar sts TCNT1H, numzero ;clear timer1 sts TCNT1L, numzero rjmp isr_antibacklash_exit ;done with routine for now isr_antibacklash_500: ;CONFIGURE TIMER1 MOVE GENERATION ldi temp1, (0 << ICNC1)|(0 << ICES1)|(0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(0 << CS10) ;configures as CTC on OCR1A, prescaler as clk/256 sts TCCR1B, TEMP1 ldi temp1, (1 << OCIE1A) ;prepare to re-enable OCR1A interrupt, disable this routine. ldi temp2, (1 << PSRSYNC) ;prepare to reset the timer0/timer1 prescalar out GTCCR, temp2 ;resets the timer0/timer1 prescalar sts TCNT1H, numzero ;clear timer1 sts TCNT1L, numzero sts TIMSK1, temp1 ;enable counter interrupts isr_antibacklash_exit: pop ZL pop ZH pop temp4 pop temp3 pop temp2 out SREG, temp2 pop temp2 pop temp1 sei reti ;--MAIN PROGRAM-------------------------------------------------------------------- reset: clr numzero ;CONFIGURE STACK ldi temp1, high(RAMEND) out SPH, temp1 ldi temp1, low(RAMEND) out SPL, temp1 ;CONFIGURE CLOCK ldi temp1, (1 << CLKPCE) sts clkpr, temp1 ;enables writing to the clock prescaler sts clkpr, numzero ;sets the clock prescaler to 1:1 ;INITIALIZE REGISTERS clr packetposition clr packetlength clr packetchecksum clr rcv_watchdog ;INITIALIZE PORTS ; set pull-ups. These get set first, when every pin is an input. ldi temp1, portb_pullups out PORTB, temp1 ldi temp1, portc_pullups out PORTC, temp1 ldi temp1, portd_pullups out PORTD, temp1 ; set directions. ldi temp1, portb_directions out DDRB, temp1 ldi temp1, portc_directions out DDRC, temp1 ldi temp1, portd_directions out DDRD, temp1 ; set initial values out comm_status, numzero sbi motor_enable_port, motor_enable ;disables motors at startup (low enable). ; initialize registers ;CONFIGURE USART0 ldi temp1, 0 ldi temp2, 25 ;19.6K @ 20MHz = 64, 115.2K @ 20MHz = 10, 115.2K @ 16MHz = 8, 76.8k @ 16MHz = 12, 38.4K @ 16MHz = 25 sts UBRR0H, temp1 ;38.4k baud at a clock of 16mhz sts UBRR0L, temp2 ldi temp1, (1<