Revision: 1167 Author: jsuijs Date: Wed Aug 5 23:15:29 2009 Log: delay calibrate project http://code.google.com/p/jallib/source/detail?r=1167
Added: /trunk/project/delay_calibrate /trunk/project/delay_calibrate/delay_calibrate.jal /trunk/project/delay_calibrate/serial_hardware_hacked.jal ======================================= --- /dev/null +++ /trunk/project/delay_calibrate/delay_calibrate.jal Wed Aug 5 23:15:29 2009 @@ -0,0 +1,261 @@ +-- delay_calibrate.jal +-- +-- This program calls delays and uses timer1 to measure how long they take. +-- The target clock can be changed to any desired value, without the need +-- to change the real clock of the target. This works since both the timer +-- (used for measuring) and the cpu (executing the delay) use the same clock. +-- the constant hacked_target_clock must be set at the real clock rate to +-- calculate the proper baudrate of the serial port. + + + +include 16f88 + +;-- +;-- This setup assumes a 20 MHz resonator or crystal +;-- is connected to pins OSC1 and OSC2. +pragma target OSC HS -- HS crystal or resonator +pragma target clock 20_000_000 -- oscillator frequency +pragma target WDT disabled -- no watchdog +pragma target LVP disabled -- no low-voltage programming +pragma target CCP1MUX RB3 -- ccp1 pin on B3 + +-- +-- This setup uses the internal oscillator +;pragma target OSC INTOSC_NOCLKOUT -- HS crystal or resonator +;pragma target clock 8_000_000 -- oscillator frequency +;pragma target WDT disabled -- no watchdog +;pragma target LVP disabled -- no low-voltage programming +;pragma target CCP1MUX RB3 -- ccp1 pin on B3 +;OSCCON_IRCF = 7 -- set prescaler to 1 (8 MHz) + + +;@jallib section serial +const serial_hw_baudrate = 115_200 +const hacked_target_clock = 20_000_000 + +-- setup serial (see echo.jal for more details);@jallib section serial +include serial_hardware_hacked +serial_hw_init() + +include print +include ndelay + +;var word TMR1 at TMR1L + +t1con = 0x01 ; TMR1ON, prescaler 1 (1 tick = 0.2 us) + + +procedure aap (byte in abc) is + var volatile word xyz = abc +end procedure + +var volatile word noot +var volatile byte mies + +;aap(noot) +; +;aap(1000) +; +;noot = mies +;mies = noot + +const byte m1[] = "Test " +const byte m2[] = " us, measured " +const byte m3[] = " us" + +procedure report_delay( word in setpoint, word in interval) is + + if (interval > 32768) then + interval = 0 - interval + end if + + ; calculate tick time in 100ns steps + var dword tick = target_clock + tick = 40_000_000 / tick + case ((t1con & 0x30) / 0x10) of + 1 : block + tick = tick * 2 + end block + + 2 : block + tick = tick * 4 + end block + + 3 : block + tick = tick * 8 + end block + + end case + + print_string(serial_hw_data, m1) + + print_dword_dec(serial_hw_data, setpoint) + + print_string(serial_hw_data, m2) + print_word_dec(serial_hw_data, (interval * tick) / 10) + serial_hw_data = "." + print_word_dec(serial_hw_data, (interval * tick) % 10) + + + print_string(serial_hw_data, m3) + +; print_byte_dec(serial_hw_data, tick) + + print_crlf(serial_hw_data) + +end procedure + + + +var word pre_timer +var word post_timer +forever loop + + const byte str0[] = "Target clock: " + print_string(serial_hw_data, str0) + + print_dword_dec(serial_hw_data, target_clock) + + const byte str1[] = " ----------------------------\r\nTest us delays\r\n" + print_string(serial_hw_data, str1) + + t1con = 0x00 ; TMR1 off, prescaler 1 (1 tick = 0.2 us @ 20 MHz, 32k = 6,5 ms ) + + pre_timer = TMR1 + T1CON_TMR1ON = true + -- no delay + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(0, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_1us() + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(1, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_2us() + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(2, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_5us() + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(5, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_9us() + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(9, post_timer - pre_timer) + + const byte str2[] = "Test 10us delays\r\n" + print_string(serial_hw_data, str2) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(1) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(10, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(2) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(20, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(5) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(50, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(10) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(100, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(20) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(200, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(50) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(500, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(100) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(1000, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_10us(200) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(2000, post_timer - pre_timer) + + const byte str3[] = "Test 1ms delays\r\n" + print_string(serial_hw_data, str3) + + t1con = 0x30 ; TMR1 off, prescaler 8 (1 tick = 1.6 us @ 20 MHz, 32k = 52 ms ) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_1ms(1) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(1_000, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_1ms(2) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(2_000, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_1ms(5) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(5_000, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_1ms(10) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(10_000, post_timer - pre_timer) + + pre_timer = TMR1 + T1CON_TMR1ON = true + delay_1ms(20) + T1CON_TMR1ON = false + post_timer = TMR1 + report_delay(20_000, post_timer - pre_timer) + + delay_100ms(10) + +end loop ======================================= --- /dev/null +++ /trunk/project/delay_calibrate/serial_hardware_hacked.jal Wed Aug 5 23:15:29 2009 @@ -0,0 +1,266 @@ +-- Title: USART hardware control +-- Author: Stef Mientki, Copyright (c) 2002..2006, all rights reserved. +-- Adapted-by: Sebastien Lelong. +-- Compiler: >=2.4g +-- +-- This file is part of jallib (http://jallib.googlecode.com) +-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html) +-- +-- Description: USART hardware control. +-- Routines for sending and receiving through the PIC-usart, +-- both asynchrone and synchrone are supported. +-- Baudrate can simply be set through a human constant, +-- because the baudrate depending registers are calculated by this unit. +-- Baudrate is calculated, starting at the high baudrate flag, +-- which will ensure the highest possible accuracy. +-- +-- TODO: should this be configurable ? +-- Transmission parameters are 8 databits, 1 stopbit, no parity, no handshake. +-- + +if (defined(usart_hw_serial) == false) then + const bit usart_hw_serial = true -- default is async mode (not sync) +end if + +procedure _calculate_and_set_baudrate() is + const max_deviation = 5 -- maximum % deviation of the realized baudrate + + if usart_hw_serial then + -- SPBRG = ( Fosc / ( 4 * Baudrate ) ) -1 + -- first try high baudrate, will generate highest accuarcy + -- to get the right rounding (5 + 10*f(x)) /10 + const usart_div =((5 + ( ( 10 * hacked_target_clock ) / ( 16 * serial_hw_baudrate )) ) / 10 ) - 1 + + -- special case if divider is 0, + -- test if deviation is not too much + if usart_div <= 0 then + if (100 * (serial_hw_baudrate - (hacked_target_clock / 16) )) / serial_hw_baudrate >= max_deviation then + pragma error -- asynchronous baudrate is too high + end if + end if + + -- if divider small enough, + -- calculate divider and set high-speed + const real_baud = hacked_target_clock / 16 / (usart_div + 1) + if usart_div <= 255 then + if (real_baud > serial_hw_baudrate) then + if (100 * (real_baud - serial_hw_baudrate) / serial_hw_baudrate >= max_deviation) then + pragma error -- asynchronous baudrate deviation is too large + end if + else + if (100 * (serial_hw_baudrate - real_baud) / serial_hw_baudrate >= max_deviation) then + pragma error -- asynchronous baudrate deviation is too large + end if + end if + + if usart_div >= 0 then + SPBRG = usart_div + else + SPBRG = 0 + end if + TXSTA_BRGH = true + -- try the low-speed mode + else + const usart_div_low = ((((10 * hacked_target_clock) / ( 64 * serial_hw_baudrate )) + 5 ) / 10) - 1 + -- here divider will never be 0 + -- but special case to consider, + -- if baudrate is just a little too low + if (usart_div_low > 255) & (100 * ((hacked_target_clock / (64 * 256 )) - serial_hw_baudrate)) / serial_hw_baudrate < max_deviation then + SPBRG = 255 + TXSTA_BRGH = false + -- now calculate divider and set high-speed / low-speed bit + elsif usart_div_low <= 255 then + if usart_div_low >= 0 then + SPBRG = usart_div_low + else + SPBRG = 0 + end if + TXSTA_BRGH = false + else + pragma error -- asynchronous baudrate is too low + end if + end if + + else -- synchronous mode + const usart_div_sync = ( hacked_target_clock / ( 4 * serial_hw_baudrate )) - 1 + + -- special case if divider is 0 or negative + -- test if baudrate is a little bit too high + if usart_div_sync <= 0 then + if (100 * (serial_hw_baudrate - (hacked_target_clock / 4 ) )) / serial_hw_baudrate >= max_deviation then + pragma error -- synchronous baudrate is too high + end if + end if + + -- special case to consider, + -- if baudrate is just a little too high + if (usart_div_sync > 255) & (100 * ((hacked_target_clock / (4 * 256) ) - serial_hw_baudrate)) / serial_hw_baudrate < max_deviation then + SPBRG = 255 + elsif usart_div_sync <= 255 then + if SPBRG >= 0 then + SPBRG = usart_div_sync + else + SPBRG = 0 + end if + else + pragma error -- synchronous baudrate is too low + end if + end if + +end procedure + + + +-- Initializes the serial port, calculates baudrate registers. +procedure serial_hw_init() is + -- Calculate and Load baudrate generator + _calculate_and_set_baudrate() + + -- disable all USART interrupts + PIE1_RCIE = false + PIE1_TXIE = false + + -- Enable transmitter : TXSTA_TXEN=1 (preserve TXSTA_BRGH) + TXSTA_TXEN = true + + -- Enable serial port : RCSTA_SPEN=1 + -- Enable receiving : RCSTA_CREN=1 + RCSTA = 0x90 + +end procedure + + +-- Disables USART so ports can be used (temporary) for other purposes. +-- USART can be enabled again by calling serial_hw_enable() +procedure serial_hw_disable() is + -- wait till running transmissions are finished + while !TXSTA_TRMT loop end loop + -- Disable Serial port: + RCSTA_SPEN = false +end procedure + + +-- Enables USART +procedure serial_hw_enable() is + -- Enable Serial port + RCSTA_SPEN = true +end procedure + + +-- ----------------------------------------------------------------------- +-- serial_hw_write - write char to serial port, blocking +-- ----------------------------------------------------------------------- +-- Asynchronuous serial send routine, using the TX pin +-- Sends byte X (8 bit with no parity) to the serial port +-- First checks (and waits if necessary) if transmit buffer is empty +-- ----------------------------------------------------------------------- +procedure serial_hw_write(byte in data) is + -- wait until TXREG is empty + while ! PIR1_TXIF loop end loop + -- then put new byte in TXREG (prepare for transmission) + TXREG = data +end procedure + + +-- like Serial_H_write, but then with a word as input +-- The MSB is outputed first +procedure serial_hw_write_word(word in data) is + var byte DX[2] at data + -- can be blocked by debugging + while ! PIR1_TXIF loop end loop + TXREG = DX[1] + asm nop -- this is necessary for damned good optimized compilers + -- loading of the TXREG doesn't immediatly set PIR1_TXIF !!!! + while ! PIR1_TXIF loop end loop + TXREG = DX[0] +end procedure + + +-- ----------------------------------------------------------------------- +-- _serial_hw_read - internal use only! +-- ----------------------------------------------------------------------- +-- (using this inline function for serial_hw_data'get saves a stack level) +-- Returns true if a character was received, otherwise returns false. +-- Overrun error flag is cleared. +-- ----------------------------------------------------------------------- +function _serial_hw_read(byte out data) return bit is + pragma inline + + -- test if byte available, and if so, + -- get byte and transport to outer world + if PIR1_RCIF then + data = RCREG + PIR1_RCIF = false -- [email protected] 12-sept-08 + else + return false ;result = false + end if + + if RCSTA_OERR then + RCSTA_CREN = false + RCSTA_CREN =true + end if + + return true +end function + + +-- ----------------------------------------------------------------------- +-- serial_hw_read - read char if available (non-blocking) +-- ----------------------------------------------------------------------- +-- Returns true if a character was received, otherwise returns false. +-- Overrun error flag is cleared. +-- ----------------------------------------------------------------------- +function serial_hw_read(byte out data) return bit is + return _serial_hw_read(data) +end function + + +-- Here Serial read and write are definied as pseudo variables +-- so you use them as normal vars, like +-- * wait for character being received, +-- * then echo the inverted character +-- {{{ +-- serial_hw_data = ! serial_hw_data +-- }}} +-- +-- these procedures will wait till they can perform their action +-- therefore it's better to use to following construct +-- {{{ +-- -- if charater received, echo the inverted character +-- if serial_hw_data_available then +-- serial_hw_data = ! serial_hw_data +-- end if +-- -- do other things +-- }}} +-- +procedure serial_hw_data'put(byte in data) is + serial_hw_write(data) +end procedure + + +function serial_hw_data'get() return byte is + var byte data + while ! _serial_hw_read(data) loop end loop + return data +end function + + +-- ----------------------------------------------------------------------- +-- raw interface +-- ----------------------------------------------------------------------- + +-- some variables made available under a general (pic-independant) name +var volatile bit serial_hw_data_available is PIR1_RCIF +var volatile bit serial_hw_data_ready is PIR1_TXIF + +-- These are real raw procedures, declared as pseudo variables +-- the user is totally responsible for testing the transmit/receive +-- flag before using these functions +procedure serial_hw_data_raw'put(byte in data) is + TXREG = data +end procedure + +function serial_hw_data_raw'get() return byte is + return RCREG +end function + --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "jallib" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/jallib?hl=en -~----------~----~----~----~------~----~------~--~---
