PICNIC

Programming Tips

■Programming Tips

0. About troubles with the PIC16F877A Version ←NEW

1. Materials for Programming

2. PICNIC Firmware Outline

3. Programming Tips

 

→Click here if you have some questions and comments.

←Back to the table of contents

Updated April 29, 2005 21:57

 


●About troubles with the PIC16F877A Version (Added on 2004/4/29)


Since the cause and solution are found about a series of troubles about PIC programming of IT technical exercise, they are written below. Please confirm what kind of PIC microcomputer you have in your hand and do the training.

<The cause why writing error occurs>
About the PIC microcomputer attached to the PICNIC kit shipped by the Tristate, PIC16F877-20/P is changed to PIC16F877A-1-/P at some point. For this reason, the rented PIC writer ver.3 (writing software ver. 2.9.5) was not compatible with this 877A.

<How to solve the troubles>
There are two kinds of methods.
(1) Do the training from the beginning to the end by using PIC16F877-20/P attached to the extended option kit. Without using 877A attached to the PICNIC kit
(2) Purchase the kit additionally for upgrading the write-in vessel ROM to ver.4 from the Akizuki Electronics.

<Conclusion>
By the following combination, it can write normally.
- Writing software ver2.9.5 + Writer ver.3 + PIC16F877-20/P
- Writing software ver2.9.21 (latest) + ROM for upgrading Writer ver.4 + PIC16F877/877A


●Information materials for programming

Microchip PIC seriesPeripheral LSI data sheetBooks, Other project sites and FAQ


6.1.1 Microchip PIC Series

→Links to all related information are here

Microchip site

Microchip U.S
Microchip Japan branch


6.1.2 Peripheral LSI Data Sheet

→Links to all related information are here

Ethernet-NIC (Realtek RTL-8019AS)
Serial-EEPROM (ATMEL 93C46)
Direct reading temperature sensor IC in Centigrade (NS LM35(DZ))
LCD display panel (SUNLIKE SC1602BSLB Hitachi HD44780)


6.1.3 Books, Other project sites and FAQ

→Links to all related information are here

Books

PIC microcomputer practical use handbook (Published by CQ)
Logic control with a PIC microcomputer (Published by CQ)
Microchip reference book list

Other project sites and FAQ

Eric's PIC Page
PIC is fun
Microchip FAQ list
Page of PIC FAQ

●PICNIC Firmware Outline

Built-in protocol stackDownloadOutline of each blockAbout operationInitial setting sequence


6.2.1 Built-in Protocol Stack

The protocol stacks mounted in the firmware of this PICNIC are as follows.

- Ethernet frame transceiver processing
- ARP reception processing
- IP reception processing
- ICMP reception processing
- UDP reception processing
- TCP reception processing
- HTTP reception processing


6.2.2 Download

Please download the firmware (ver1.2) for MPASM assembler of PICNIC ver.2 from the following sites.

Assembly source file (v12.asm)

Assembled HEX file (v12.hex) Listing file (v12.lst) Error file (v12.err)

※Reference: Include header file for PIC16F877 P16F877.inc


6.2.3 Outline of Each Block

In the whole firmware, there are 7380 lines of codes.
Roughly the blocks are constituted as follows.


Line 21-37: Definition of various constants
Line 42-53: EEPROM memory domain
Line 61-466: Definition of various environment variables for protocol stacks

Line 470: Starting point of the program (ORG 0)
Line 482-621: Interruption routine (Reception processing, Timeout)
Line 628-815: Various functions (Control TCP frame number, Error return)

Line 820-889: Main loop

Line 902-1018: Ethernet frame reception processing (RTL8019AS buffer control)
Line 1025-1068: ARP protocol processing
Line 1172-1341: IP protocol processing (Received buffer control)
Line 1349-1434: ICMP protocol processing
Line 1441-1565: UDP protocol processing (Parallel port output control)
Line 1571-1682: DHCP (BOOTP) protocol processing (Concerned about getting IP address)
Line 1690-2323: TCP protocol processing (Only server function, packet output routine included)

Line 2328-2393: A/D conversion input processing
Line 2398-2500: Pre-processing routine of input-output state
Line 2504-2558: Short message analysis processing
Line 2563-2764: Creation of a network socket, checksum calculation

Line 2771-3032: About the initialization of RTL8019AS
Line 3037-3214: Checksum calculation, packet transmission processing (NIC level)
Line 3221-3344: Creation of Ethernet frame, IP frame

Line 3352-3578: UDP → parallel I/O control, A/D conversion function
Line 3584-3560: UDP checksum calculation
Line 3655-3873: Serial interface control

Line 3879-4024: Socket control
Line 4030-4290: Ethernet broadcast processing

Line 4295-4369: About writing data to EEPROM
Line 4555-4577: Initialization of EEPROM
Line 6063-6130: Library related to EEPROM
Line 7266-7306: Set EEPROM default value

Line 4379-4548: URL specified CGI analysis processing
Line 4583-4643: Change of parallel I/O output value by the URL parameter

Line 4651-4919: Start-up routine (Related to setup at the time of power supply)
Line 4625-5036: Library related to LCD display
Line 5042-5292: Various operation library function groups

Line 5297-5404: Bootstrap mode and initialization routine
Line 5411-5944: About serial terminal operation command
Line 7015-7054: Bootstrap mode and terminal display
Line 7311-7374: Bootstrap mode and data for command analysis

Line 5952-6056: Notification processing of the present socket status (Now unused)

Line 6139-6266: Processing that displays the acquired IP address on the LCD panel
Line 6431-6697: Processing of IP address acquisition from DHCP server

Line 6273-6424: Serial port → UDP transmission processing
Line 6703-7009: UDP reception → serial port output, LCD panel display

Line 7061-7258: Storing area for the response massage and its format that are in web browser HTML format


6.2.4 About the operation

It is almost not necessary to change the already mounted various protocol stacks by the user side. The change in the page displayed on a web browser for control starts from line 7061. The portion of storing area for the response massage and its format that are in web browser HTML format will be changed.

Since there is limitation of Ethernet frame length, all HTML format texts cannot be sent at a time. So text is sent by dividing it into four blocks(4 transition changes from ESTAB0 to ESTAB9). This sending processing is mounted as the sequencer of TCP packet processing which starts from the 1690th line.

In the timer interruption routine, automatic reset function is mounted for recovery from disconnection of an Ethernet cable, network disruption, and the freezing state of various protocol processing. For example, after freezing about 15 seconds it is designed so that it will return to the LISTEN state of TCP compulsorily.

Only the GET method of HTTP protocol is mounted.
It exists as a simple HTTP server and at first the parameter(after ?) in URL sent by the request from a web browser is analyzed, and save the control information in EEPROM inside PIC and then control of various kinds of external interfaces is performed. Then, the present information in the PICNIC (the above-mentioned HTML text) is sent to the browser.

<Reference>
Hyper Text Transfer Protocol (HTTP) specifications, 1.0 edition
The connection state transition diagram of TCP


6.2.5 Initial Setting Sequence

Start-up routine of the firmware, i.e. the sequence of start: (Related to setup at the time of power supply, from line 4651 ~ ) is as follows.

(1) Copy the required data (IP address setup etc.) to RAM for initial setting from the built-in EEPROM

(2) Initialize the LCD liquid crystal display panel

(3) Initialize EthernetNIC (RTL8019AS) and load CONFIG register to NIC

(4) Acquire the MAC Address from the exterior serial EEPROM 93C46

(5) The MAC Address acquired in (4) is written to the PAR register of NIC

(6) Check the operation mode (usual or bootstrap) by checking the state of jumper SW. Then, it enters the main routine of the selected mode.

(7) If the acquisition of IP address (IP=0.0.0.0) from the DHCP server is required, send the DISCOVER message of the DHCP protocol by broadcast.

※After the above-mentioned processing is completed, it will be in the state waiting for frame receiving.

 

●Programming Tips

1. The Available Program Memory
2. Correspondence with Program Module on Firmware, and Memory Use Domain
3. Present Storage Value of EEPROM Data Domain
4. The Processing of Rewriting "default" Value in EEPROM

5. Message Creation of Web Control Screen
6. Acquisition of Short Messages as "In", "Out", "High" "Low" etc.
7. Escape Sequence Embedding to DA and Word Alignment
8. Value Embedding Directions Start from Higher Rank of Word Alignment

9. Display the Value of Room Temperature Sensor (RA5)
10. How to Display the temperature in Degree Fahrenheit (°F) instead of the Present Centigrade (°C)

11. Internal Timer & Interruption
12. Real-Time Clock (RTC)

13. CGI ? Parameter Command Perth and Writing in EEPROM
14. Processing when IP Address is obtained by DHCP (Notes)
15. The Mechanism of Displaying the "Transmitting Packet Numbers"

16. Processing Related to Internal Timer and Interruption of v12.Asm
17. Mounting Error about ADCON0 Control Register of ad_in Module


6.3.1 The Available Program Memory

In total, 8192 bytes of program memory are available.
Address space is 0x0000 -- 0x1FFF (13 bit)

For v12.asm(ver1.2.0.0), the status of memory use of the machine language after assembling is as follows.

PAGE#0 : 0x0000-0x07FF : 0x0000--0x07EA Using
PAGE#1 : 0x0800-0x0FFF : 0x0820--0x0FED Using
PAGE#2 : 0x1000-0x17FF : 0x1000--0x1240、0x1300--0x151C、0x1700--0x17FF Using
PAGE#3 : 0x1800-0x1FFF : 0x1800--0x190A、0x1A00--0x1B9D、0x1D00--0x1D9F
0x1F00--0x1FC1 Using

We understand that there is almost no vacant domain.

While adding other functions, some of the existing following functions should be deleted and then we get empty memory space (bank). The code of an additional function is put into the empty program memory space.

Line 1441-1565: UDP protocol processing (parallel port output control)
Line 1571-1682: DHCP(BOOTP) protocol processing (Related about obtaining IP address)
Line 3352-3578: UDP -> parallel I/O control, A/D conversion function
Line 3584-3560: UDP checksum calculation
Line 3655-3873: Serial interface control

Line 5297-5404: Bootstrap mode and initialization routine
Line 5411-5944: Related to serial terminal operation command
Line 7015-7054: Bootstrap mode and terminal display
Line 7311-7374: Bootstrap mode and data for command analysis

Line 6431-6697: Processing of obtaining IP address from the DHCP server

Line 6273-6424: Serial port -> UDP transmission processing
Line 6703-7009: UDP reception -> serial port output, LCD panel display


6.3.2 Correspondence with Program Module on Firmware, and Memory Use Domain (V1.2.0.0)

<Program memory>

PAGE 1
Program start 0x0000--0x07EA

PAGE 2
Control of parallel I/F 0x0820--0x0FED
(32 bytes from 0x0800 to 0x081F are not used)

PAGE 3
Transmission of serial received data 0x1000--0x1240
Bootstrap mode 0x1300--0x13FB

For web browsers -- message #1 0x1400--0x151C
For web browsers -- message #2 0x1700--0x190A PAGE3-->4へ跨っている
For web browsers -- message #3 0x1A00--0x1B9D
For web browsers -- message #4 0x1D00--0x1D9F

※Relative specification of display domain for every 0x0300. db 0,0 (0000h) is block terminating discernment data string.

default_values_begin:
EEPROM data initial value 0x1F00 -- 0x1FC1 Initial values of IP address etc.

<EEPROM memory>

EEPROM domain 0x2100--0x21FF (Initial values of IP address etc.)

IP address 0x2100 (192.168.0.200)
Net mask 0x2104 (255.255.255.0)
Default gateway 0x2108 (0.0.0.0)
Firmware Version 0x210C (1.2.0.1)
HTTP port number 0x2110 (80d)
LCD port number 0x2112 (10000d)
PARALLEL port number 0x2114 (10001d)
SERIAL port number 0x2116 (10002d)

Hereafter, empty domain is 0x2118--0x21FF

 


6.3.3 Present Storage Value of EEPROM Data Domain

Example of EEPROM data for IP:192.168.0.200, PORT:80 : (256 bytes 0x0000 -- 0x00FF)

0000:C0 A8 00 C8 FF FF FF 00 00 00 00 00 01 02 00 01 ・・・・・・・・・・・・・・・・
0010:00 50 00 00 27 11 27 12 FF FF FF FF FF FF FF FF ・P・・'・'・・・・・・・・・

Hereafter, 0x00FF is written as 0xFF.
Now, 0x0000--0x0017 is occupied. User can use from 0x0020.

As a real memory address, 0x2100--0x21FF is supported.
In a program, data that are in ORG 0x2100 and onward, are done DE as initial value at the time of ROM writing (Supported by MPASM).


6.3.4 The Processing of Rewriting "default" Value in EEPROM

The value "for returning EEPROM data to the initial stage" is stored in 0x1F00-- 0x1F17 (18h bytes). (Refer to Section 6.3.3)

To get its domain size, subtraction between the following labels, i.e. default_values_end - default_values_begin is done. For module: initial_values, only that part of the domain (subtracted result) is rewritten in EEPROM domain.

The writing sequence to actual EEPROM is done by module:write_eeprom and it is carried out by operating register files of EEADR and EEDATA etc.

<Notes>

From the above description, (at this stage) of the program

It is necessary to make the constant values of the following domain same.
EEPROM domain 0x2100--0x2117 (18h bytes) and,
default_values_begin :EEPROM data initial value 0x1F00--0x1F17 (18h bytes)
Now, the following four points are important.

IP address 0x2100 (192.168.0.200)
Net mask 0x2104 (255.255.255.0)
default gateway 0x2108 (0.0.0.0)
Firmware Version 0x210C (1.2.0.1)

If the values are not same, when the "default" value is read from the web control screen a different value from the ROM write value will be loaded.

(Inversely, is it also fun to make it reconfigurable by two or more contexts?)

Now, about the HTTP_PORT, LCD_PORT, PARALLEL_PORT and SERIAL_PORT, since the constants are defined in the upper part, only changing that part will be OK.


6.3.5 Message Creation of Web Control Screen

About the message creation of PICNIC web control screen, transmission processing of contents of every bank as well as about every branch indicator for embedding the values is written below.

Reference URL:
ASCII code table:
http://dbkun.cs.shinshu-u.ac.jp/cai/c2/text/e_ascii.html

MPASM Users Guide with MPLINK and MPLIB
page 59--60
microchip/33014g.pdf#page=59

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(1) I/O Ports assignment

RA0--RA3 Analog input (RA0 and RA1 are terminal block CN4)
RA5 Room temperature sensor IC input (After converting to degree Celsius display it)
RB0- RB1 Digital input (Both RB0 and RB1 terminal blocks CN4 point-of-contact input)
RB2--RB5 Only for LCD indicator (User use diabled)
RB6--RB7 Digital output (Both RB6 and RB7 terminal blocks and CN3 point-of-contact output)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(2) Response message domain

It is divided into four parts from #1 to #4.

PAGE 3
For web browsers -- message #1 0x1400--0x151C
For web browsers -- message #2 0x1700--0x190A
For web browsers -- message #3 0x1A00--0x1B9D
For web browsers -- message #4 0x1D00--0x1D9F

Relative specification of display domain for every 0x0300.

The contents of each bank are as follows.

#1: Content-type: text/html -- up to </TD> </TR> of I/O RA5 In xx Celsius
#2: RB0 In -- display [Reload] button of I/O Ports, up to </FORM>
#3: Network setup - display [Save] [Default] button, up to </FORM>
#4: Status display -- up to </HTML> at the end

DB 0,0 (0000h) is block terminating discernment data string.


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(3) Transmission processing of the contents of each bank

job_ESTAB → The state changes between each mode from 00 to 99 sequentially.

  goto ESTAB_00
  goto ESTAB_01
  goto ESTAB_02
  goto ESTAB_03
  goto ESTAB_99

ESTAB_00:
  TCP processing -> If established by a http port,
  If the character '?' is contained in URL,
  It moves to command analysis of ? parameter of URL. (→ to parse_cgi_tag)

  Else
estab1:
  Using LW=14h as bank address, the message of bank #1 is sent by using send_mes module.

  MOVLW 014H ; Bank address = 14h fan
  MOVWF wk
  goto send_mes; Send message

ESTAB_01:
  Using LW=17h fan as bank address, the message of bank #2 is sent by using send_mes module

ESTAB_02:
  Bank address LW=1Ah fan, Send message bank #3.

ESTAB_03:
  Bank address LW=1Dh fan, Send message bank #4.

ESTAB_99:
  Termination processing of transmission: call send_fin+call inc_seq_no


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(4) Send message: send_mes module

Start from around the 2017th line

send_mes_head: TCP header creation
send_mes0: Data is read from a bank domain
  Test
  If the read data is 0,0 bank termination direction, it ends (→ to send_mes9)

  Or when data is a processing branch indicator, processing is branched as follows.

  Meta character && 0x7F : Branch indicators are as follows :
    "$"(24h) : ctrl_code2
    "@"(40h) : ctrl_code3
    "%"(25h) : ctrl_code4
    " ̄"(3Fh) : ctrl_code5

  In case of usual characters except the above, low-order 7 bits are transmitted to RTL8019 buffer.
  Loop between send_mes0.

send_mes9: Data domain transmission escape point
send_mes_foot: TCP footer creation: checksum calculation
Finally send by call transmit!


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(5) Correspondence between each branch indicators and processing

ctrl_code5: SOCKET STATUS Socket status display
 ̄", from 0ah to 0eh, display of socket#1 to #5 (At present the function is stopped)
→ call put_socket_stat

ctrl_code4: TRIS Display of direction of input and output
  "%", From 00h to 04h, the direction of input and output from RA0 to RA5 is displayed.
  "%", From 10h to 17h, the direction of input and output from RB0 to RB7 is displayed.

ctrl_code3: PARALLEL The present input-output value Display of High/Low
  '@", From 00h to 04h, the analog input value from RA0 to RA5 is displayed.
  '@", From 10h to 17h, the digital input-output value from RB0 to RB7 is displayed.

ctrl_code2: META CHARACTER To the control character output routine
  → call ctrl_code1

ctrl_code1: Replace the embedded $? in the message of network setting value.
  From "$","0" to "B", the setting contents are displayed as follows.

goto put_mac_address ; 0:MAC address
goto put_ip_address ; 1:IP address
goto put_netmask ; 2:Net mask
goto put_gateway_address ; 3:Gateway
goto put_http_port ; 4:http port
goto put_lcd_port ; 5:lcd port
goto put_io_port ; 6:parallel port
goto put_232_port ; 7:232c port
goto put_version ; 8:Version display

goto put_send_packet ; 9:Number of transmitting packets
goto put_this_ip ; A:Display of self-IP
goto put_ptop ; B:PtoP IP address

ctrl_code: Tag to ctrl_code1?


6.3.6Acquisition of Short Messages as "In", "Out", "High" "Low" etc.

About acquisition of a short message as "In", "Out", "High", "Low", etc. message bank is from 0x1F00.

org 1F00h
getadtable:
mes_low DT " Low ",0
mes_high DT " High ",0
mes_in DT "In ",0
mes_out DT "Out",0

Message display module
get_short_mes:

The processing is done by ctrl_out, ctrl_in, ctrl_high and ctrl_low respectively.
Example: mes_out &.255 ; 'OUT' (low-order 8 bit mask)

Actual writing is done by put_short_mes10.

<Hint>Therefore, by adding the following character string definition in the message bank

mes_open DT " Open ",0
mes_close DT " Close ",0

If these are called instead of _low, _high

Input:
RB0 : Door open: Open and Door closed: Close
RB1 : Gone out mode Being at home : Open Gone out : Close

Output :
RB6 : Unlocked State :Open Locked state : Close

The display can be change in the above ways. (Here _low <--> _Open and _high <--> _Close corresponds respectively)


6.3.7 Escape Sequence Embedding to DA and Word Alignment

Reference URL :

ASCII code table :
http://dbkun.cs.shinshu-u.ac.jp/cai/c2/text/e_ascii.html

MPASM Users Guide with MPLINK and MPLIB
page 59--60
microchip/33014g.pdf#page=59

Escape sequence code
page105--
microchip/33014g.pdf#page=105

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

※The 7-bit segment store(Packed-8bit value) of DB, DA

PIC16F877 has a data width of 1 word = 14 bits.
The range of 1 word is 0x0000 -- 0x3FFF.
(In binary number it is 00.0000.0000.0000b -- 11.1111.1111.1111b)

If we think this 14bit data as two 7-bit width "bytes" lying together (Packed-8bit value), the store result of DB,DA described later is easy-to-understand.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(1) DB (Declare Data of One Byte)

For PIC16F877, constants described in DB (Declare Data of One Byte) are sequentially stored in 6 bits + 8 bits from higher order of 14 bits bit width.
That is, the ranges of the value of odd number byte and even number byte indicated by DB are 0x00-0x3F and 0x00-0xFF respectively.

Example 1-1:If DB 0xFF, 0xFF, etc. are indicated forcibly,

The following warning will be displayed. In fact, 0x3FFF is generated.

Message[303]: Program word too large. Truncated to core size. (FFFF)


The order of the value of DB is even number. If it is an odd number, low-order 8 bits are filled up with 0.

Example 1-2:In case of DB 0x3F etc., 0x3F00 will be generated.


We may treat the generated row (14 bits) as 7bit + 7bit ASCII code. This is deeply related to DA described later.

Example 1-3:If DB is 0x06, 0x8A, 0x068A will be generated.
If it is divided into 7bit+7bit bit width and since 0x06=0000.0110b and 0x8A=1000.1010b,
We can write

0x068A = 00.0110.1000.1010b → [000.1101]:[000.1010]b → [0x0D] : [0x0A]

That is, the code of "a new line" for CR+LF text file is generated.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

DA (Store Strings in Program Memory)

For example, in case of the direction DA "HTTP", the ASCII codes of non-meta characters "H","T","P" are in range of low-order 7 bits.
The row (14 bits) generated by DA directions can be regarded as the result stored as a 7bit+7bit ASCII code.

After putting this [x6 ... x0], [y6 ... y0] one by one, it becomes xx.xxxx.xyyy.yyyyb and this is the value of 1 word stored in memory.

Example 2-1:DA "HTTP" In case of DA "HTTP"

Since,

 "H" = 0x48 → 0100.1000b
 "T" = 0x54 → 0101.0100b
 "P" = 0x50 → 0101.0000b

Both "HT" and "TP" are packed as 1 word. So the following will be generated.

 [100.1000]:[101.0100] → 10.0100.0101.0100b = 0x2454
 [101.0100]:[101.0000] → 10.1010.0101.0000b = 0x2A50


The order of the value of DB is even number. If it is an odd number, low-order 7 bits are filled up with 0.

Example 2-2:In case of odd number characters like DA "K",、

Since,

 "K" = 0x4B → 0100.1011b

It has been packed as "K" + 7bit(filled by 0)
So the following will be generated.

 [100.1011]:[000.0000] → 10.0101.1000.0000b = 0x2580


Example 2-3:The value row of DA is stored as 6+8 bits like DB. For example, two lower mounting are equivalent.

 DB 0x3F, 0xFF
 DA 0x3FFF

0x3FFF is generated for all.


Example 2-4:In the character string row of DA, embedding of an ASCII escape sequence as well as hexadecimal number of \x?? format is possible.

The following two mounting are equivalent.

 DA "test\r\n"
 DA "test\x0D\x0A"

0x39F4 0x068A will be generated in both cases.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(3) The embedding of escape sequence to DA and word alignment

About the description of web response massage,

(a) We want to embed CR+LF or LF, a "new-line" code at the last of transmitting message character string.
(b) At the end of bank, describing as DB 0,0 and eliminating the side effects of zero-filling 7 bits that is needed for word alignment, and want it to run correctly.
(c) We want to use the limited memory domain as a Packed-8bit character string without any loss.

So we want to satisfy above three conditions.


Let's overlook the memory use efficiency of condition (c). About the conditions (a) and (b), let's ignore word alignment memory use efficiency and it is easy method to do it by escape sequence embedding to DA.


Example 3-1:Escape sequence embedding to DA

About the HTTP response and header transmission

----------------------------------------------------------------------
HTTP/1.0 200 OK[CR+LF]
Connection: close[CR+LF]
Content-type: text/html[CR+LF]
[CR+LF]            ←An empty line is required between message main part.
<HTML><HEAD><TITLE>PIC Network Interface Card</TITLE></HEAD><BODY>[LF]
----------------------------------------------------------------------

We want to transmit the above "character string". And if purpose (c) is ignored, by using escape sequence embedding to DA we can simply embed
[CR]->¥r, [LF]->¥n

----------------------------------------------------------------------
DA "HTTP/1.0 200 OK¥r¥n"
DA "Connection: close¥r¥n"
DA "Content-type: text/html¥r¥n"
DA "¥r¥n"
DA "<HTML><HEAD><TITLE>PIC Network Interface Card</TITLE></HEAD><BODY>¥n"
----------------------------------------------------------------------

We want to mount as above.

However, in some web browsers (Netscape7.1 etc.), the garbage(0x00) behind \r\n is interpreted accurately. So if the message type is text/html, there may arise some problems. Here we have decided not to adopt those browsers. (Correction on 2003/10/12)


example 3-2:Considering word alignment, escape sequence embedding to DA

Again, about HTTP response and header transmission, in the character string row for DA, if we divide suitably as every DA has even number character string, for example it becomes as follows.

----------------------------------------------------------------------
HTTP/1.0 200 OK[CR+LF]C  18 characters
onnection: close[CR+LF]  18 characters
Content-type: text/htm  22 characters
l[CR+LF][CR+LF]< 6 characters
HTML><HEAD><TITLE>PIC Network Interface Card</TITLE></HEAD><BODY>[LF] 66 characters
----------------------------------------------------------------------

Mounting is as follows.

----------------------------------------------------------------------
DA "HTTP/1.0 200 OK¥r¥nC"
DA "onnection: close¥r¥n"
DA "Content-type: text/htm"
DA "l¥r¥n¥r¥n<"
DA "HTML><HEAD><TITLE>PIC Network Interface Card</TITLE></HEAD><BODY>¥n"
----------------------------------------------------------------------

In this case, the word row generated is as follows.
From address 0x1441 to 0x1482-1, 0x40 words are generated.
Comparing to the case where word alignment is not taken into consideration, 2 words are saved!


1441 2454 2A50 17B1 DA "HTTP/1.0 200 OK¥r¥nC"
1730 1032 1830
104F 258D 0543
144A 37EE 3765 31F4 DA "onnection: close¥r¥n"
34EF 373A 1063
366F 39E5 068A
1453 21EF 3774 32EE DA "Content-type: text/htm"
3A2D 3A79 3865
1D20 3A65 3C74
17E8 3A6D
145E 360D 050D 053C DA "l¥r¥n¥r¥n<"
1461 2454 26CC 1F3C DA "HTML><HEAD><TITLE>PIC Network Interface Card</TITLE>....."
2445 20C4 1F3C
2A49 2A4C 22BE
2849 21A0 2765
3A77 37F2 35A0
24EE 3A65 3966
30E3 32A0 21E1
3964 1E2F 2A49
2A4C 22BE 1E2F
2445 20C4 1F3C
214F 2259 1F0A
1482 ....


Example 3-3:When you do not have to consider readability

In the above example, when we line them up there is an even number of strings, so if we do not consider readability, we can put them all in one line with "" using DA

----------------------------------------------------------------------
DA "HTTP/1.0 200 OK¥r¥nConnection: close¥r¥nContent-type: text/html¥r¥n¥r¥n<HTML><HEAD><TITLE>PIC Network Interface Card</TITLE></HEAD><BODY>¥n"
----------------------------------------------------------------------

Even in this form, the code generated will be the same as Example 3-2.

<Problem>
Is there a limit on the maximum number of characters for one line?
In the listing file .lst, the display of too long code generation was cut short partway.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(4) After all, is the combination of DB and DA just a lot of trouble?

In the end, implementations using combinations of DB and DA such as in the original assembly source file (v12.asm), for example

----------------------------------------------------------------
DA "HTTP/1.0 200 O"
DB 25,8D ;'K',13
DB 05,43 ;10,C
DA "onnection: close"
DB 06,8A ;, .13, .10,
DA "Content-type: text/htm"
DB 36,0D,05,0D,05,3C ;'l', .13, .10, .13, .10, '<'
----------------------------------------------------------------

we see that the result is poor readability and there is no merit whatsoever. ;-<


6.3.8 Start value insertion commands from the top part of word alignments

Value insertion commands (such as $8) must start from the top part of word alignment.

If $* begins from the bottom part of alignment, "$" and "8" will be interpreted as characters and "displayed" as "$8".

Example: In the (wrong) case below, the position of $ in $8 will be in the bottom part of word alignment so "$8" will be displayed. It is too much trouble to count characters in such a case, so it is simpler to divide into two DA statements as shown in the (right) case below.

(right)
  DA "<H1>PIC Network Interface Card Version "
  DA "$8</H1>"

(wrong)
  DA "<H1>PIC Network Interface Card Version $8</H1>"


6.3.9 On the room temperature sensor value display (RA5)

A temperature sensor IC (NS LM35DZ) is connected to RA5 and the A/D converter inside the PIC is used to convert its values to 10-bit binary numbers.

LM35 datasheet:
http://www.national.com/JPN/ds/LM/LM35.pdf

As noted in this datasheet, this IC can directly obtain linearly corrected outputs of temperature in degrees centrigrade (temperature coefficient + 10.0mV/degree C) (very convenient).

(1) Insertion of RA5 binary value "degrees C" conversion value to web control screen message

OK, the position for inserting the RA5 value is at the end of Bank#1 which begins from org 1400h.

;
;++++++++++++++ Room Temperature Sensor Input RA5(degrees C converted) ++++++++++++++++++
;
DA "<TR><TD>RA5 "
DB 12,84 ;%",0000_0100b,(input direction)
DA " </TD>"
DA "<TD ALIGN=¥"right¥">"
DB 20,04 ;@",00000100b,(display of degrees C conversion value)
DA " Celsius</TD></TR>"

In other words, the value is inserted as control character "@"+0x04.

During data output from the send_mes0 module, it jumps to "@"(40h):ctrl_code3 module and in the case of an analog input pin, A/D conversion processing by the ad_in:module begins.

For 0-+5V inputs, the PIC16F877 has a 10-bit A/D converter and the output of this temperature sensor IC is stored in variable [val1:val] as the conversion result.

In the case of RA5, we consider the temperature coefficient above, the connection to Vs=GND by R14(10KΩ), the A/D conversion range (0-5V), as well as the resolution (0 to 1023 (≒1000) in decimal). For input values of 0 to approximately 1000, we compute values (5x) to be able to display 0-50 degrees centrigrade linearly.

For details, refer to the v12.asm assembly source file ad_in:module starting around line 2325.

(2) What is the meaning of "DB 12,84"?

As explained earlier in 6.3.7 On insertions of escape sequences for DA and "word alignment", this is an instruction for inserting the <input direction> "In" or "Out" in HTML messages.

When a "%" is found in the top part of word alignment, the processing for message output is branched and the material indicated by the parameter in the following bottom part is carried out. In this implementation, the message "%"+0x04 is generated.

<Explanation>

The DB directive of the MPASM assembly language here means Declare Data of One Byte so an implementation of

 DB 0x12, 0x84

in the PIC16F877 which has a one word 14-bit core, the following machine code is generated.

 0x1284

If we divide this into 7bit+7bit widths, 0x12=0001.0010b, 0x84=1000.0100b, so

 0x1284 = 00.010.0101:000.0100b → [010.0101]:[000.0100]b → [0x25]:[0x04]

In other words, the result is the generation of the message "%"+0x04.

For details, refer to §6.3.7.

(3) On the processing of the "%" meta-character

※ The message sending module send_mes begins near line 2017.

++++++++++++++++++++++++++++++++++++++++++++++++++++
send_mes_head: construction of TCP header
send_mes0: Read data from bank area.
  If the data read is 0,0 the end of bank instruction, end (→ go to send_mes9)

  Otherwise, if the data is a meta-character, treat it as a control character or branch the processing as shown below.

  meta-character && 0x7F : branch as shown below:
  "$"(24h) : ctrl_code2
  "@"(40h) : ctrl_code3
  "%"(25h) : ctrl_code4
  " ̄"(3Fh) : ctrl_code5
++++++++++++++++++++++++++++++++++++++++++++++++++++

Here, we have "%", so we jump to the ctrl_code4:module

++++++++++++++++++++++++++++++++++++++++++++++++++++
ctrl_code4: TRIS input/output direction display
  from "%"+00h, use 04h and display the input/output direction of RA0 to RA5.
  from "%"+10h, use 17h and display the input/output direction of RB0 to RB7.
++++++++++++++++++++++++++++++++++++++++++++++++++++

and divide the processing. Here, "%"+0x04 is specified so we jump to the module for the "display" of the input/output direction of RA5, namely the string "In" or "Out" (after this, we will do table lookup processing of the message bank. See §6.3.6.

Since RA5 is an "input" from the temperature sensor as described earlier, we check the PIC register file input/output direction bit and the "In" display is done as a result.

<Hint>

Example: The following is an equivalent implementation. DB 12,84 ⇔ DA "%¥x04" For details, see §6.3.7.


6.3.10 Display temperature in Fahrenheit (degrees F) instead of the current Celsius display (degrees centrigrade)

There are two methods.

(1) In place of the current Celsius (degrees centrigrade) sensor, install a Fahrenheit (degrees F) sensor

In place of the Celsius direct reading NS LM35(DZ), use the Fahrenheit direct reading version LM34(DZ) and that will be it.

LM34 datasheet:
http://www.national.com/JPN/ds/LM/LM34.pdf

The temperature coefficients are also +10.0mV/℃ for LM35 and +10.0mV/F for LM34, so the portion for calculating temperature from the A/D conversion result will be the same.

To avoid confusion, when you switch the ICs, it would be a good idea to change the web display, for example, from "Celsius" to "Fahrenheit".

(2) Add a conversion formula for Celsius (degrees C) to Fahrenheit (degrees F)

If you wish to display temperatures in Fahrenheit using the Celsius (degrees C) sensor as is, you will need to add the following Celsius (degrees C) to Fahrenheit (degrees F) conversion formula to the ad_in: module described earlier before the part for storing values for display (or replace the current "5x" calculation).

++++++++++++++++++++++++++++++++++++++++
※Conversion formula for Celsius to Fahrenheit
  (temperature in Fahrenheit) = 1.8 × (temperature in Celsius) + 32
++++++++++++++++++++++++++++++++++++++++

The Celsius temperatures are non-negative so the Fahrenheit results will also be non-negative and treatment for negative values is not necessary.

<Hint>
The PIC16F877 is equipped with integer computation functions only so it cannot compute x 1.8 directly.
As a hint for implementation, by multiplying both sides of the above equation a suitable number of times, we can replace it with a suitable number of left bit shift operations. A division module for 16- bit binary numbers is already implemented in the firmware (divide16 module).

※ This will be a good exercise, so I will leave it for student practice, OK? :-)


6.3.11 On the internal timer and interrupts

<URL references>

PIC16F877 datasheet (Japanese)
microchip/30292a-j.pdf

PICmicro PIC16F87x MID-RANGE Complete Reference Manual:
microchip/33023a.pdf

Microchip seminar documents:
http://www.microchip.co.jp/1999seminar058-094.pdf?page=25
http://www.microchip.co.jp/1999seminar150-198.pdf?page=8

(1) On the internal timer

The PIC16F877 is equipped with three internal timers TMR0 to TMR2.

PIC16F877 datasheet DS30292A-J page47--
microchip/30292a-j.pdf#page=47

8bit timer/counter with prescaler
TMR0 --> T0IF interrupt flag set on overflow

16bit timer/counter with prescaler
TMR1 --> T1IF interrupt flag set on [TMR1H]:[TMR1L] overflow

8bit timer/counter with prescaler/postscaler
TMR2 --> T2IF interrupt flag set on overflow

※Current PICNIC Fosc=20MHz(50nsec) so Fosc/4 = 5MHz(200nsec)

++++++++++++++++++++++++++++++++++++++++++++++++++++++

Internal timer 0 TMR0(8bit)

Block diagram
PIC16F877 datasheet DS30292A-J page47 Figure5-1
microchip/30292a-j.pdf#page=47

Related registers
PIC16F877 datasheet DS30292A-J page48 Table5-1
microchip/30292a-j.pdf#page=48

TMR0 register:register BANK#1, 101h

PSout := !TOCS && PSA && (Fosc/4)

PSA bit clear --> prescaler assigned to timer 0
prescale value:PSA bit ==L --> 1:2 ~ 1:256

TMR0register:TMR0 interrupt occurs on the 0xFF --> 0x00 transition (overflow)

Interrupt flag is T0IF(INTCON:2)(need to first set this bit to 0)
Interrupt mask is T0IE(INTCON:5)

++++++++++++++++++++++++++++++++++++++++++++++++++++++

Internal timer 1 TMR1(16bit)

Block diagram
PIC16F877 datasheet DS30292A-J page50 Figure 6-3
microchip/30292a-j.pdf#page=50

T1CON control register
PIC16F877 datasheet DS30292A-J page49 Figure 6-1
microchip/30292a-j.pdf#page=49

Related registers
PIC16F877 datasheet DS30292A-J page51 Table 6-2
microchip/30292a-j.pdf#page=51


TMR1 register [TMR1H]:[TMR1L]: register BANK#0, TMR1L:0Eh, TMR1H0Fh

PSout := !TMR1CS && (Fosc/4) or RC oscillator

Prescale values:1:1 ~ 1:8

TMR1 register: TMR1 interrupt occurs on the 0xFFFF --> 0x0000 transition (overflow)

Interrupt flag is TMR1IF(PIR1:0)(need to first set this bit to 0)
Interrupt mask is TMR1IE(PIE1:0)

++++++++++++++++++++++++++++++++++++++++++++++++++++++

Internal timer 2 TMR2(8bit)

Block diagram
PIC16F877 datasheet DS30292A-J page54 Figure 7-2
microchip/30292a-j.pdf#page=54

T2CON control register
PIC16F877 datasheet DS30292A-J page53 Figure 7-1
microchip/30292a-j.pdf#page=53

Related registers
PIC16F877 datasheet DS30292A-J page54 Table 7-1
microchip/30292a-j.pdf#page=54

TMR2 register:register BANK#0, 11h

PSout := TMR2ON && (Fosc/4)

Prescale values:1:1 1:4 1:16
Postscale values(4 bit):1:1~1:16

PR2 register:in a comparator with TMR2 register. FFh on reset.

TMR2 register:0x00 --> if matching PR2, scaled by postscaler -->
TMR2 interrupt occurs. (TMR2 register returns to 0x00)

Interrupt flag is TMR2IF(PIR1:1)(need to first set this bit to 0)
Interrupt mask is TMR2IE(PIE1:1)

++++++++++++++++++++++++++++++++++++++++++++++++++++++

(2) On interrupts

PICmicro PIC16F87x MID-RANGE Complete Reference Manual page123--
microchip/33023a.pdf#page=123

PIC16F877 datasheet DS30292A-J page143--
microchip/30292a-j.pdf#page=143

Logic for interrupt types
PIC16F877 datasheet DS30292A-J page144 Figure 12-11
microchip/30292a-j.pdf#page=144

14 interrupt types.


Global interrupt mask:GIE
Interrupt mask:INTCON
Peripheral interrupt mask bit:PEIE

Peripheral interrupt flags:PIR1 PIR2
Peripheral interrupt enable bits:PIE1 PIE2

When an interrupt is performed, the GIE bit becomes 0 and any further interrupts are disabled. The return address is pushed to the stack and 0004h (the interrupt processing routine) is loaded to the PC.

In the interrupt processing routine, the cause of the interrupt can be checked by looking at the interrupt flag bit.

After the interrupt is processed, before enabling the interrupt again, the interrupt flag bit has to be cleared by software. (Otherwise, once we have returned from the interrupt processing routine, the interrupt will occur again and an infinite loop of requests will be made.)

You must save the context (STATUS, W, PCLATH registers) during an interrupt.
PIC16F877 datasheet DS30292A-J page145--
microchip/30292a-j.pdf#page=145

※For more information on the details of implementation, refer to the article of the above datasheet.

 


6.3.12 On the real-time clock

(1) The PIC16F877 is not equipped with a so-called "real time clock (RTC)". The only way to get date and time is to connect a real time clock IC to an external port (serial port, for example).

Example: Ultra small serial I/O real time clock module manufactured by Ricoh
RICOH Rx5C348A/B
http://www.ricoh.co.jp/LSI/spec/rtc/5c348/5c348ab-j.pdf

(2) Wait modules in units of milliseconds msec and microseconds μsec are already implemented in the firmware.

(3) An example different from the PICNIC firmware we use here was found in another project which gets date and time from an NTP server on the Internet.
http://park11.wakwak.com/ ̄domo/time.html

(4) In theory, it may be possible to implement a "current time" feature on this PIC by somehow making it possible to set the current time, embedding calendar calculations in the remaining program memory, and generating internal timer interrupts for counting up one second at a time.

※In (3) above, they are actually counting up using 100msec internal timer interrupts.

However, in the attached v12.asm firmware, the program memory is used up for implementing the current functions and the above implementation would be very difficult in the current form without deleting certain functions.

(5) In the implementation of (4), if the power is cut, the current time will be forgotten so some other method for setting the date and time externally will be necessary. This will turn out to be another vicious cycle so the method in (1) for attaching an external RTC with battery backup would probably be the best solution.


6.3.13 On the CGI ? parameter command parse and EEPROM write

When we do a gateway address change from a web browser, the ? parameters in the URL are passed and the gateway address in the EEPROM is rewritten.

Example:In the following URL:http://192.168.1.200:8080/submit.cgi?00b=192.168.1.200&04b=255.255.255.0&08b=0.0.0.0&10w=8080

this would be the 08b=0.0.0.0 part. (we write it in byte units 0,0,0,0)

(1) Outline of parameter command parsing and EEPROM writing

++++++++++++++++++++++++++++++++++++++++
<Processing>
In estab0:, we have
; Found '?' character? (=GET command processing)
MOVLW '?'
SUBWF data0,0
BTFSC 3,2
GOTO parse_cgi_tag
++++++++++++++++++++++++++++++++++++++++

and if "?" is included in the URL, we treat the following parts as parameters and jump to the analysis module parse_cgi_tag. This is the tag for jumps between memory banks and the actual processing is the parse_cgi module.

The outline of processing for parse_cgi which begins around line 4374 is as follows.

++++++++++++++++++++++++++++++++++++++++
parse_cgi
 Read next character.
 If end of string, end→parse9_tag
 Check if I/O related
 Check if word units
 Check if byte units
 If "&" appears, this will be the next parameter so return to the beginning

parse_cgi0
 If "&" appears, this is the next parameter so return to the beginning
 Read "."-delimited numbers in order
 If they continue, loop to parse_cgi0 and read values.

parse_cgi2
parse_cgi3
 Write the value calculated from the "."-delimited values to the EEPROM
 Return to the beginning to check for the next parameter

parse9_tag
 tag for jumping across banks.
 Use goto parse9 to go to TCP transmission processing (same address as estab1)
++++++++++++++++++++++++++++++++++++++++

So you can see that as soon as a gateway address change is instructed, the value in the EEPROM is immediately rewritten.

(2) IP address and http port number use variable values in memory

In the current version of firmware, the IP address and http port number are read from the EEPROM at startup after a reset and copies of these values are held in memory as this_ip, http_port.

During packet header generation for example, the values copied to memory are used rather than the values in the EEPROM.

Therefore, when the IP address and http port number are changed from the web screen, the values are only written to the EEPROM and the configuration will not actually change until the values are read into this_ip, http_port after a reset.

The other settings such as netmask and gateway appear to be read directly from the EEPROM so any changes made will be reflected immediately.

<Hint>

For a local PC connected under the same router, the netmask and gateway values are not meaningful for ordinary HTTP responses (because they are in the same segment), so even if these values are changed, you can still "continue" to see the web control screen.


6.3.14 On the processing for getting IP addresses from DHCP (Notes of caution)

In the instructions manual, it says
 "By setting the IP address=0.0.0.0, an IP address can be obtained through DHCP on reset."
but, some caution is needed in the actual implementation.

At present, the following problems are known.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
In the response from the DHCP server, only the IP address is used and the netmask value dhcp_router_ip is not set.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

(1) Operation of address retrieval from DHCP

<DHCP protocol packet>

;               DHCP protocol
;
dhcp_header SET udp_data
dhcp_ope SET udp_data+0
dhcp_type SET udp_data+1
dhcp_phylen SET udp_data+2
dhcp_hop SET udp_data+3
dhcp_trans SET udp_data+4
dhcp_sec SET udp_data+8
dhcp_dummy SET udp_data + .10
dhcp_client_ip SET udp_data + .12
dhcp_user_ip SET udp_data + .16
dhcp_user_ip1 SET udp_data + .17
dhcp_user_ip2 SET udp_data + .18
dhcp_user_ip3 SET udp_data + .19
dhcp_server_ip SET udp_data + .20
dhcp_server_ip1 SET udp_data + .21
dhcp_server_ip2 SET udp_data + .22
dhcp_server_ip3 SET udp_data + .23
dhcp_router_ip SET udp_data + .24

<Outline of processing of IP address retrieval from DHCP>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
main:
 ; Own IP address 0.0.0.0?
do_dhcp
 set dhcp_done flag
 call dhcp

dhcp:
bootp_tx:
 send UDP packet for dhcp address request
bootp_res:
 Check for bootp response for own MAC address
 If a response is returned, save the assigned IP address dhcp_user_ip in this_ip

→Check in the timer interrupt routine and unset the dhcp_done flag

※In the main0 loop, check the dhcp_done flag.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

So, in the response from the DHCP server, only dhcp_user_ip-ip3 are used and the value for netmask dhcp_router_ip is not set.

Therefore, the default values
netmask=255.255.255.0
gateway=0.0.0.0
will be used and some caution will be necessary.

(2) Case in which accesses outside of the router become necessary

The netmask and gateway values will need to be

・written to the EEPROM as initial values beforehand or
・set separately from a PC connected inside the router using URL ? parameters

(3) Can we make it possible to automatically get gateway address, etc.?

In theory, it would be possible to change the firmware yourself to set the netmask value dhcp_router_ip and operate much like a Windows PC, obtaining the gateway address automatically, etc.

You can save the values in variables in memory in the same way as this_ip, http_port and dynamically change the netmask, gateway values depending on whether you are using a fixed IP or DHCP.

You could add this processing to the same place as the setting for this_ip, etc. when the DHCP response is received.

The difficulty with implementing this in the current firmware is the fact that every reference to the netmask, gateway values is done by a read to the EEPROM. You will have to change all of these references to reads of variables in memory.

※It is quite difficult work, but if it works stably, many people might be happy to have that distribution as ver1.2.1.0. :-)

(4) On the DHCP protocol standards (BOOTP)

The details of the DHCP protocol standards can all be found from RFCs since it is an Internet working protocol.
http://www.faqs.org/rfcs/

The DHCP standards draft is RFC2131.
RFC2131 standards:
http://www.faqs.org/rfcs/rfc2131.html


Historically speaking, first there was BOOTP, and then DHCP was developed as an extension of it.

RFC 951(BOOTP)
RFC 1084(BOOTP Extensions)
RFC 1542(Clarifications and extensions for BOOTP)

RFC 2131 Dynamic Host Configuration Protocol, Draft Standard Protocol
RFC 2132 DHCP Options and BOOTP Vendor Extensions

<Reference URLs>

http://www.net.intap.or.jp/oiia/cont1/p0302.html%7B0recid=10342.html
http://www.net.intap.or.jp/oiia/cont1/p0302.html%7B0recid=10024.html


6.3.15 Mechanism for the display of "Number of packets sent"

For the display of number of packets sent, we use value insertion in Sent Packets $9. The actual processing is shown below.

(1) Branched processing of send_mes module

In send_mes0: module,
; If the upper 7 bits are a meta-character, branch processing
MOVLW '$'
SUBWF data0,0
BTFSC 3,2
GOTO ctrl_code2
If there is a match, jump to ctrl_code2, and then to ctrl_code1 to make
a relative jump(? -"0"(0x30)) based on the $? value.
ctrl_code1
ADDWF 2,1
goto put_mac_address ; 0:MAC address
goto put_ip_address ; 1:IP address
goto put_netmask ; 2:netmask
goto put_gateway_address ; 3:gateway
goto put_http_port ; 4:http port
goto put_lcd_port ; 5:lcd port
goto put_io_port ; 6:parallel port
goto put_232_port ; 7:232c port
goto put_version ; 8:version display

goto put_send_packet ; 9:number of packets sent
goto put_this_ip ; A:diplay of own IP
goto put_ptop ; B:PtoP IP address

※After $9 is '$'+0x3a(":"). (refer to the ASCII code table)

In the case of $9, the put_send_packet: module is called. In this module processing, the IP packet sequence number:ident is referenced

val1 <-- upper part of sequence number:ident
val <-- lower part of sequence number:ident
val2,val3 <-- 0

After each of these variables is set, we call the 32bit->decimal conversion:put_decimal32 and display the number of packets sent.

(2) Conversion of 32-bit binary to decimal routine : put_decimal32 module

The 32-bit binary to decimal conversion routine put_decimal32() module reads 4 words (byte enabled) specified from the area holding the binary values (val3:val2:val1:val) as a parameter and displays 32-bit binary values as decimal (val_m).

The related variable memory areas are as follows.

※Environment setting variables
ident EQU 0AEH ; IP packet sequence number
ident1 EQU 0AFH ;
※Global variables
val EQU 32H ; Byte 1
val1 EQU 33H ; Byte 2
val2 EQU 34H ; Byte 3
val3 EQU 35H ; Byte 4
val_m EQU 36H ; for DECIMAL
val_cn EQU 37H ; Remainder for division?
※Work area for decimal conversion (is this OK? We haven't used org 120h)
decimal_top EQU 120H ; For binary → decimal conversion

 


6.3.16 On the processing for v12.asm internal timer and interrupts

<Outline>

・We use the internal timer TMR1 for processing timeouts of DHCP request completions.
・We perform socket timeout checks with dec_tm. Internal timer TMR1 is also used here.


(1) Initial setup for timers and interrupts in the startup routine start: module

(a) Configuration for option registers
(near line 4662)


                bsf     STATUS,RP0
MOVLW B'10000110'
DB 00,62 ; Option register
......
bcf STATUS,RP0

Switch to register bank #1/3
Wreg←B'10000110'(enable bit7,2,1)
Machine code 0x0062 => option register(BANK#1, 81h)←Wreg

(Reference)
Option register Wreg load machine code(00.0000.0110.0010)
PIC16F87x Complete Reference Manual page554
microchip/33023a.pdf#page=554

※Why 86h is loaded to OPTION_REG is a mystery.
(The datasheet states something about compatibility with PIC16C)


(b) USART setup & interrupt enable
(near line 4781)


                bsf     STATUS,RP0
MOVLW B'10100000' ; restore rc
MOVWF TRISC
MOVLW B'00100110'
MOVWF TXSTA ; initialize ASYNC module Tx side
MOVLW BAUD_RATE
MOVWF SPBRG ; set baud rate
BSF PIE1,5 ; rcie; enable Rx interrupts
bcf STATUS,RP0
MOVLW B'10000000'
MOVWF RCSTA ; Initialize ASYNC module Rx side
bcf STATUS,RP0
bcf INTCON,6 ;peie ; enable peripheral

Set interrupts for Rx processing of the serial interface USART.
The setting for the interrupt control register is as follows

PEIE(INTCON[bit6])
PIE[bit5] (RCIE: USART Receive Interrupt Enable bit)

(Reference)
Interrupt control register INTCON, PIE
PIC16F87x Complete Reference Manual page127-- §8.2.1
microchip/33023a.pdf#page=127


(c) DHCP request flag clear and timer TMR1 initialization
(near line 4803)


                bsf     STATUS,RP0
CLRF dhcp_done
bcf STATUS,RP0
CLRF PORTB ; Initial state RB=00h
CLRF TMR1L
CLRF TMR1H
MOVLW B'000101'
MOVWF T1CON

Clear DHCP request flag (dhcp_done) (BANK#1)
PORB all bits Low(BANK#0)

Initialize timer TMR1 16bit([TMR1H]:[TMR1L]) to zero
TICON ← B'xx000101'
; T1CKPS1:T1CKPS0 := 0:0, !T1SYNC:=1, TMR1ON :=1

TMR1CS := 0, so use internal clock.

!TISYNC : Timer1 External Clock Input Synchronization Select bit
-- 1 = "Do not synchronize external clock input"

TMR1ON: Timer1 On bit
-- 1 = "Enables Timer1"

T1CKPS1:T1CKPS0: Timer1 Input Clock Prescale Select bits
-- 00 = 1:1 Prescale value(count up with Fosc/4)


Using the above, if we calculate the overall time TMR1の0x0000-->0xFFFF,
the current PICNIC is Fosc=20MHz(50nsec) so
Fosc/4 = 5MHz(200nsec)。We count 65535 with this and when it is all over, the time it takes for an interrupt to occur is

200nsec x 65535 = 13,107,000nsec (約13.1msec)

(Reference)
TMR1 control register T1CON
PIC16F87x Complete Reference Manual page183
microchip/33023a.pdf#page=183


(d) Enabling timer TMR1 interrupts, peripheral interrupts, and global interrupts
(near line 4811)


                BSF     STATUS,RP0
BSF PIE1,TMR1IE
BCF STATUS,RP0
BSF INTCON,PEIE
BSF INTCON,GIE
BSF INTCON,GIE ;gie; global interrupts enabled
goto main

PIE1[TMR1IE] set: timer TMR1 interrupts enabled
INTCON[PEIE] set: peripheral interrupts enabled
INTCON[GIE] set: global interrupts enabled

※It is not clear why they do GIE twice.

 

(2) On the main, main0 routine

Following start, we jump to the main routine and after checking the conditional branch for DHCP, we enter the main loop: main0. In the main0 loop, the following processing is done in order

・Rx check from USART I/F(receive232c)
・Check for completion of DHCP request (do_dhcp)※use timer TMR1 for timeout control
・Check for Ethernet-NIC Rx buffer overflow (if there is an overflow, empty reads overflow)
・Check Rx packets from Ethernet (get_packet)

After a goto to each part, the routine is designed to return to this main0 label with another goto.

 

(3) On the interrupt processing routine

Check PIR1,TMR1IF and if it is a TMR1 interrupt, jump to int_tmr1.

Processing for DHCP done: int_tmr1

Send DHCP retrieval requests at intervals of TMR1 all over intervals approximately 13.1msec * 80h
= 1676.8msec(approximately 1.68 seconds)
Memory for timer control: dhcp_done(BANK#1, 0xB2)

Socket timeout check: int_tmr2
Memory for timer control: timer, timer_cn(BANK#1, 0xB3, 0xB4) are used
Jump to timeout control module: dec_tm

Return to → dec_tm9

 


6.3.17 On an implementation error concerning the ADCON0 control register in the ad_in module

・In the ad_in module where the ADCON0 register is modified to control the A/D converter, it appears that the actual firmware (v12.asm) is actually modifying the ADCON1 register.
・However, since RP0 of the STATUS register is not High, it becomes an operation for BANK#0 of the ADCON0 register and the operation looks "correct" as a result
・In this portion, code for manipulating ADCON0 needs to written so keep in mind that this is an implementation error.

Implementation of ad_in module
(from about line 2320)


;		AD conversion
;
ad_in
RLF getmes_wk1,1
RLF getmes_wk1,1
RLF getmes_wk1,1
MOVLW B'00111000'
ANDWF getmes_wk1,1
MOVLW B'10000001'
IORWF getmes_wk1,1
MOVF getmes_wk1,0 ; set value in ADCON1
MOVWF ADCON1
MOVLW 1
MOVWF wait_cn
MOVLW HIGH (wait_ms)
MOVWF PCLATH
;
call wait_ms ; Sampling time 20us wait
MOVLW HIGH (ad_in)
MOVWF PCLATH
;
bsf ADCON1,2 ; Start AD conversion
btfsc ADCON1,2 ; AD conversion wait
goto $-1

All of the ADCON1 in the above need to be rewritten as ADCON0.

Shinshu University Graduate School on the Internet

wasaki@cs.shinshu-u.ac.jp
Copyright(c) 2005 Katsumi Wasaki. All rights reserved.