Author: sebastien.lelong
Date: Mon Sep 29 01:47:56 2008
New Revision: 334

Added:
    trunk/unvalidated/include/peripheral/usart/serial_software.jal
    trunk/unvalidated/sample/by_device/16f88/serial_sw_echo.jal

Log:
issue 8: serial_software lib integration + a simple echo sample

Added: trunk/unvalidated/include/peripheral/usart/serial_software.jal
==============================================================================
--- (empty file)
+++ trunk/unvalidated/include/peripheral/usart/serial_software.jal      Mon Sep 
 
29 01:47:56 2008
@@ -0,0 +1,361 @@
+-- Title: Software RS232 library
+-- 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 BSD license  
(http://www.opensource.org/licenses/bsd-license.php)
+--
+-- Description: software RS232 library
+-- Library supports software RS232 send and receive procedure on any  
IO-pin.
+-- Both the inverted and non-inverted routines are available,
+-- so it should fit any hardware.
+-- Baudrate can be set between 110 and 230_400 (for 20 Mhz Xtal),
+-- for lower Xtal frequencies the maximum baudrate will be equally lower.
+-- Baudrates are optimized, so even the high baudrates shouldn't be a  
problem
+-- (my [Stef] standard = 115_200 Baud, which has never given me any  
problems).
+-- Interrupts should be disabled during transmissions.
+-- Transmission parameters are 8 databits, 2 stopbits, no parity, no  
handshake.
+--
+-- TODO: should transmission parameters be configurable ?
+-- (8 databits, 2 stopbits, no parity, no handshake)
+--
+
+
+procedure serial_sw_init() is
+       -- ouput/tx pin active or not according to invert
+       if serial_sw_invert then
+               serial_sw_tx_pin = high
+       else
+               serial_sw_tx_pin = low
+       end if
+end procedure
+
+
+;; Number of instructions per bit
+const _NINSTR = target_clock / (4 * serial_sw_baudrate)
+const _NINSTR2 = 5 + ( _NINSTR / 2)
+--  
-----------------------------------------------------------------------------
+
+
+;; Transmit parameters
+const OL_TX  = ( _NINSTR / ( 3 * 255 )) + 1
+const _IL_TX  = ( ( _NINSTR - ( 4 * OL_TX ) ) - 16 ) / ( 3 * OL_TX )
+
+;; because some corrections have to be made, declare InnerLoop counter as  
var
+var byte IL_TX = _IL_TX
+
+;; for small values, the value is truncated in stead of rounded, so add 1
+if _IL_TX < 10 then
+       IL_TX = _IL_TX + 1
+end if
+
+--  
-----------------------------------------------------------------------------
+-- For Xtal = 20_000_000, the following counter values are calculated (in  
Hex)
+--  Baud      olcnt    ilcnt     Ninstr
+--  110       3C       FB
+--  300       16       FA
+--  600       0B       FA
+--  1200      06       E5
+--  2400      03       E4
+--  4800      02       A9
+--  9600      01       A6
+--  14_400    01       6D
+--  19_200    01       50
+--  38_400    01       24
+--  57_600    01       16
+--  115_200   01       08        43
+--  230_400   01       01        22    NOT TESTED
+--
+-- Test sequence used: all possibilities
+
+
+
+-- receiving is optimized for 20 Mhz, 320_400 Baud
+--   Number of instructions = (3 * olval * Ilval) + (4 * olval) + 15
+-- 320kB  ==>  olval = ilval = 1
+-- next optimization for 20 Mhz, 115_200 Baud  olval = 1
+--   olval = 1   ==>   ilval = 8
+-- all other buadrates downto 1200 shouldnt be a problem now
+-- because of "IF-statement" this constant must be declared as a var
+
+var byte ilval
+var byte olval
+var byte ilval0
+
+if serial_sw_baudrate < 200_000 then
+       const _olval  = ( _NINSTR / ( 3 * 255 )) + 1
+       const _ilval  = ( ( _NINSTR - ( 4 * _olval ) ) - 15 ) / ( 3 * _olval )
+       const _ilval0 = ( ( _NINSTR2 - ( 4 * _olval ) ) - 5 ) / ( 3 * _olval )
+       
+       
+       ilval  = _ilval
+       olval  = _olval
+       ;due to rounding the next value can slightly below 1
+       if _ilval0 > 0 then
+               ilval0 = _ilval0
+       else
+               ilval0 = 1
+       end if
+       ilval0 = _ilval0
+       
+       -- test if baudrate valid for the chosen Xtal frequency
+       if _olval > 255 then
+               pragma error  -- baudrate too low for this Xtal
+       end if
+       if _olval == 0 then
+               pragma error  -- baudrate too high for this Xtal
+       end if
+       
+else
+       const _ilval = 1
+       const _olval = ((target_clock / (4 * serial_sw_baudrate)) - 15 ) / (4 + 
3  
* _ilval)
+       ilval = _ilval
+       olval = _olval
+
+end if
+
+-- For Xtal = 20_000_000, the following counter values are calculated (in  
Hex)
+--  Baud      olcnt    ilcnt     ILcnt0      Ninstr
+--  110       3C       FB        7C
+--  300       16       FA        7C
+--  600       0B       FA        7C
+--  1200      06       E5        72
+--  2400      03       E4        72
+--  4800      02       A9        55
+--  9600      01       A7        55
+--  14_400    01       6D        38
+--  19_200    01       50        2A
+--  38_400    01       25        14
+--  57_600    01       16        0D
+--  115_200   01       08        05          43
+--  230_400   ?        ?         ?           22    NOT TESTED
+--
+-- Test sequence used (Hex)
+--    01  02  04  08  10  20  40  80  00 FF  AA  55
+
+
+
+-- Waits untill a character is received.
+-- Interrupts will be disabled during this routine, but restored  
afterwards.
+-- Also here the code is doubled (inverting and non-inverting)
+-- and selection is done by a compiler-directive.
+procedure serial_sw_write(byte in data) is
+       var bit old_gie    ;status of interrupt enable on entrance
+       ;; jallib(seb): this is a way to act on tx pin
+       ;;var bit pp at serial_sw_out_port : serial_sw_out_nr
+       var bit pp is serial_sw_tx_pin
+       var bit data_bit at data : 0
+       
+       -- stop interrupts and be sure they are stopped
+       -- save old interrupt status
+       old_gie = INTCON_GIE
+       while INTCON_GIE loop
+               INTCON_GIE = false
+       end loop
+       
+       if serial_sw_invert then
+               pp = low
+               _usec_delay((1_000_000/serial_sw_baudrate)-2)
+               for 8 loop
+                       -- wait a whole bittime, less some usec for other 
actions
+                       pp = data_bit
+                       data = data >> 1
+                       _usec_delay((1_000_000/serial_sw_baudrate)-2)
+               end loop
+               -- add 2 stop bits
+               pp = high
+               _usec_delay((2_000_000/serial_sw_baudrate))
+               
+       else
+               -- invert the data
+               data = ! data
+               pp = high
+               _usec_delay((1_000_000/serial_sw_baudrate)-2)
+               for 8 loop
+                       -- wait a whole bittime, less some usec for other 
actions
+                       pp = data_bit
+                       data = data >> 1
+                       _usec_delay((1_000_000/serial_sw_baudrate)-2)
+               end loop
+               -- add 2 stop bits
+               pp = low
+               _usec_delay((2_000_000/serial_sw_baudrate))
+       end if
+       
+       -- restore old interrupt status
+       INTCON_GIE = old_gie
+
+end procedure
+
+
+-- Waits untill a character is received.
+-- Interrupts will be disabled during this routine, but restored  
afterwards.
+-- Also here the code is doubled (inverting and non-inverting)
+-- and selection is done by a compiler-directive.
+procedure serial_sw_read_wait(byte out data) is
+       var bit  ie_old    ;status of interrupt enable on entrance
+       var bit ready
+       ;; jallib(seb): this is a way to act on rx pin
+       ;;var bit pp at serial_sw_in_port : serial_sw_in_nr
+       var bit pp is serial_sw_rx_pin
+       
+       -- stop interrupts and be sure they are stopped
+       -- save old interrupt status
+       ie_old = INTCON_GIE
+       while INTCON_GIE loop
+               INTCON_GIE = false
+       end loop
+       
+       if serial_sw_invert then
+               -- wait for serial line inactive
+               while !pp loop end loop
+
+               ready = false
+               while !ready loop
+                       -- wait for startbit
+                       while pp loop end loop
+                       
+                       -- wait half a bit time, less 5 usec for other actions
+                       _usec_delay((1_000_000/(2*serial_sw_baudrate))-1)
+                       
+                       -- test if still startbit, otherwise restart
+                       if !pp then
+                               -- now fetch 8 bits
+                               for 8 loop
+                                       -- wait a whole bittime, less 5 usec 
for other actions
+                                       
_usec_delay((1_000_000/serial_sw_baudrate)-1)
+                                       -- shift new bit in
+                                       data = data >> 1
+                                       if pp then
+                                               data = data | 0x80
+                                       end if
+                               end loop
+                               ready = true
+                       else
+                               ready = false
+                       end if
+               end loop
+       else  ;NOT inverted
+               -- wait for serial line inactive
+               while pp loop end loop
+               
+               ready = false
+               while !ready loop
+                       -- wait for startbit
+                       while !pp loop end loop
+                       
+                       -- wait half a bit time, less 5 usec for other actions
+                       _usec_delay((1_000_000/(2*serial_sw_baudrate))-1)
+                       
+                       -- test if still startbit, otherwise restart
+                       if pp then
+                               -- now fetch 8 bits
+                               for 8 loop
+                                       -- wait a whole bittime, less 5 usec 
for other actions
+                                       
_usec_delay((1_000_000/serial_sw_baudrate)-1)
+                                       -- shift new bit in
+                                       data = data >> 1
+                                       if !pp then
+                                               data = data | 0x80
+                                       end if
+                               end loop
+                               ready = true
+                       else
+                               ready = false
+                       end if
+               end loop
+       end if
+       
+       -- restore old interrupt status
+       INTCON_GIE = ie_old
+       
+end procedure
+
+
+--  
-----------------------------------------------------------------------------
+-- Here the serial_sw_write procedure is declared as a pseudo variable
+-- so you can use it in the following way:
+-- {{{
+--    serial_sw_write = 0x33
+-- }}}
+procedure serial_sw_data'put(byte in data) is
+       serial_sw_write(data)
+end procedure
+
+-- Here the serial_sw_read_wait procedure is declared as a pseudo variable
+-- so you can use it in the following way
+-- {{{
+--    Data = serial_sw_write
+-- }}}
+function serial_sw_data'get() return byte is
+       var byte data
+       serial_sw_read_wait( data )
+       return data
+end function
+
+-- Waits untill a character is received or time out is reached.
+-- Interrupts will be disabled during this routine, but restored  
afterwards.
+-- Also here the code is doubled (inverting and non-inverting)
+-- and selection is done by a compiler-directive.
+function serial_sw_read(byte out data) return bit is
+       var bit ie_old    ;status of interrupt enable on entrance
+       ;; jallib(seb): this is a way to act on rx pin
+       ;;var bit pp at serial_sw_in_port : serial_sw_in_nr
+       var bit pp is serial_sw_rx_pin
+       
+       if serial_sw_invert != pp then
+               return false
+       end if
+
+       -- stop interrupts and be sure they are stopped
+       -- save old interrupt status
+       ie_old = INTCON_GIE
+       while INTCON_GIE loop
+               INTCON_GIE = false
+       end loop
+       
+       if serial_sw_invert then
+       -- wait for startbit
+               while pp loop end loop
+               
+               -- wait half a bit time, less 5 usec for other actions
+               _usec_delay((1_000_000/(2*serial_sw_baudrate))-1)
+               
+               -- now fetch 8 bits
+               for 8 loop
+                       -- wait a whole bittime, less 5 usec for other actions
+                       _usec_delay((1_000_000/serial_sw_baudrate)-1)
+                       -- shift new bit in
+                       data = data >> 1
+                       if pp then
+                               data = data | 0x80
+                       end if
+               end loop
+       else  ;NOT inverted
+               -- wait for startbit
+               while !pp loop end loop
+               
+               -- wait half a bit time, less 5 usec for other actions
+               _usec_delay((1_000_000/(2*serial_sw_baudrate))-1)
+               
+               -- now fetch 8 bits
+               for 8 loop
+                       -- wait a whole bittime, less 5 usec for other actions
+                       _usec_delay((1_000_000/serial_sw_baudrate)-1)
+                       -- shift new bit in
+                       data = data >> 1
+                       if !pp then
+                               data = data | 0x80
+                       end if
+               end loop
+       end if
+       
+       -- restore old interrupt status
+       INTCON_GIE = ie_old
+       
+       return true
+
+end function
+
+

Added: trunk/unvalidated/sample/by_device/16f88/serial_sw_echo.jal
==============================================================================
--- (empty file)
+++ trunk/unvalidated/sample/by_device/16f88/serial_sw_echo.jal Mon Sep 29  
01:47:56 2008
@@ -0,0 +1,58 @@
+-- Title: Sample using software implemented USART.
+-- Author: Sebastien Lelong, Copyright (c) 2008, all rights reserved.
+-- Adapted-by:
+-- Compiler: >=2.4g
+--
+-- This file is part of jallib (http://jallib.googlecode.com)
+-- Released under the BSD license  
(http://www.opensource.org/licenses/bsd-license.php)
+--
+-- Description: this sample shows how to setup a simple software serial  
communication link.
+-- It echoes every received char.
+--
+
+-- select chip
+include 16f88
+-- set all IO as digital
+enable_digital_io()
+
+-- We'll use internal oscillator. It work @ 8MHz
+pragma target clock            8_000_000
+pragma target OSC              INTOSC_NOCLKOUT
+-- no watchdog, please
+pragma target WDT              disabled
+
+-- ok, now setup serial
+-- setup speed. Standard values are: 57_600, 19_200, 9_600, 2_400, ...
+-- Note: as it's a software implementation, not all baudrates can work with
+-- our 8MHz clock. For instance, 19200 gives too much errors. We'll a lower
+-- baudrate here.
+const serial_sw_baudrate = 2_400
+-- because it's a software implementation, we also need to define
+-- tx and rx pins. How clever we are: we use the same pin as in hardware,
+-- so it works out of the box with any board having an USART module...
+var volatile bit serial_sw_tx_pin is pin_B5
+var volatile bit serial_sw_rx_pin is pin_B2
+-- and we also need to specify direction
+pin_B5_direction = output
+pin_B2_direction = input
+-- finally, how levels are understood ? Inverted or not ?
+-- Note in hardware serial, it's inverted. Since we're talking to a PC
+-- we need to invert the signal
+const serial_sw_invert = true
+-- now we can use serial_software module
+include serial_software
+-- initialize the whole with our parameters
+serial_sw_init()
+
+-- inform user PIC is ready !
+serial_sw_write("!")
+
+-- let's build our loop
+var byte char  -- will store received char
+forever loop
+       if serial_sw_read(char)
+       then
+               serial_sw_write(char)   -- that's the echo...
+       end if
+end loop
+

--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to