Nivelul Legatura de Date Si Interfata cu Nivelul Aplicatie Utilizare a Modemului

Modem radio FSK pentru comunicații de tip MPT1327, cu implementarea protocolului MAP27

Nivelul legatură de date și interfața cu nivelul aplicație – utilizare a modemului

Proiect de diplomă

Cuprins

Capitolul 1. Microcontroler-ul 80C552 – Arhitectura generală

1.1. Familia Intel 8051

1.2. Caracteristici specifice Phillips 80C552 vs. cu Intel 8051

1.3. Detalierea blocurilor relevante

1.3.1. Registrele SFR și bancurile de registre de uz general

1.4 Platforma de dezvoltare cu microcontroler 80C552

Capitolul 2. Protocolul MAP27.Descriere și detaliere a nivelului legătură de date

2.1. Protocolul MAP27 – generalități

2.2. Stiva de protocoale

2.3. Interfața fizică

2.3.1. Caracteristici electrice

2.3.2. Conectorul

2.3.3. Transmisiunea asincronă și viteza de transmisiune

2.4. Detalierea nivelului legătură de date

2.4.1. Elemente de protocol

2.4.2. Formatul general al unui cadru

2.4.3. Antetul cadrului de cerere legătură (Link Request)

2.4.4. Antetul cadrului de confirmare legătură (Link Acknowledge)

2.4.5. Antetul cadrului de transfer date pe legătură (Link Transfer)

2.4.6. Asigurarea transparenței datelor 29

2.4.7. Verificarea erorilor

2.4.8. Variabilele și numerele de secvență

2.4.9. Timerele nivelului legătură de date și parametrii care determină valorile acestora

2.5. Situații de stabilire a conexiunii de nivel legătură de date

Capitolul 3. Comunicații mobile de tip trunking.Comunicații MPT1327

3.1. Tipuri de apeluri

3.2. Canalul de control

3.3. Tratarea apelurilor

3.4. Adresarea

3.5. Transmitere a unui mesaj scurt de date.

Capitolul 4. Compilatorul Franklin C51, fișierele necesare pentru rularea codului sursă, hiperterminalul și programul monitor

4.1. Compilatorul Franklin C51

4.2. Fișiere necesare pentru rularea codului sursă din hiperterminal, utilizând programul monitor

4.3. Hiperterminalul și programul monitor

Capitolul 5. Implementarea software a modulelor necesare funcționării nivelului legătură de date pentru protocolul MAP27

5.1. Schema bloc a unui sistem de comunicații MPT1327 – conexiune MAP27

5.2. Întreruperi folosite în cadrul implementării

5.3. Realizarea bazelor de timp pentru contorizarea evenimentelor

5.4. Realizarea funcționalității timerelor de la nivelul legătură de date

5.4.1. Timer-ul T0

5.4.2. Timerul T1

6.4.3. Timerul T3

6.4.4. Timerul T4

6.5. Utilizarea UART pentru comunicația dintre microcontroler și terminal

5.7. Utilizarea serialei asincrone de tip bit-banging pentru comunicația între stația radio și microcontroler.

5.7.1. Cazul emisiei

5.7.2. Cazul recepției

5.8. Funcția de verificare a erorilor

5.9. Funcția de asigurare a transparenței datelor

5.10. Testarea pachetelor de nivel legătură de date la recepție

5.10.1. Testarea antetului LR

5.10.2. Testarea antetului LA

5.10.3. Testarea antetului LT

5.11. Construirea pachetelor de nivel legătură de date pentru emisie

5.11.1. Construirea pachetului LR

5.11.2. Construirea pachetului LA

5.11.3. Construirea pachetului LT

Capitolul 6. Stările principale ale legăturii de date

6.1. Starile Reset Wait și Link Wait

6.2. Starea Ready

6.3. Observații experimentale

Capitolul 7. Implementarea software a regimurilor de lucru

Lista figurilor

Fig. 1.1 Microcontrolerul Phillips 80C552 …………………………………………………………………………14

Fig. 1.2 Harta memoriei microcontrolerului 80C552 …………………………………………………………..15

Fig. 1.3 Registrul PCON ( Power Control )…………………………………………………………………………16

Fig. 1.4 Registrul TCON…………………………………………………………………………………………………..17

Fig. 1.5 Registrul CTCON………………………………………………………………………………………………..17

Fig. 1.6 Registrul TM2CON……………………………………………………………………………………………..18

Fig. 1.7 Registrul CTCON………………………………………………………………………………………………..18

Fig. 1.8 Registrul TM2IR………………………………………………………………………………………………….18

Fig. 1.9 Registrul SCON…………………………………………………………………………………………………..19

Fig. 1.10 Registrul IEN0……………………………………………………………………………………………………20

Fig. 1.11 Registrul IEN1……………………………………………………………………………………………………21

Fig. 1.12 Schema electrică a plăcii de dezvoltare (blocurile utilizate)……………………………………..24

Fig. 2.1 Comunicația capăt la capăt pe căi radio…………………………………………………………………..25

Fig. 2.2 Comunicația prin Portal (Gateway)…………………………………………………………………………26

Fig. 2.3 Semnale de pe interfața V.24 și numărul pinilor……………………………………………………….26

Fig. 2.4 Transmisiunea asincronă………………………………………………………………………………………..27

Fig. 2.5 Structura generală pachet legătură de date……………………………………………………………….28

Fig. 2.6 Antet pachet cerere legătură……………………………………………………………………………………28

Fig. 2.7 Antet pachet confirmare legătură…………………………………………………………………………….29

Fig. 2.8 Antet pachet transfer de date…………………………………………………………………………………..32

Fig. 2.9 Exemplu stabilire conexiune la legătură de date cu negocierea parametrilor………………..33

Fig. 2.10 Exemplu stabilire conexiune la legătură de date cu aceeași parametri……………………….36

Fig. 3.1 Mesaje MPT1327 pentru transmiterea unui mesaj scurt……………………………………………..38

Fig. 4.1 Fișierul C.BAT……………………………………………………………………………………………………..39

Fig. 4.2 Programul monitor………………………………………………………………………………………………..39

Fig. 4.3 Configurația hiperterminalului teraterm pentru comunicația cu UART………………………..41

Fig. 5.1 Diagrama modulelor hardware ce alcătuiesc schema de principiu a proiectului…………….42

Fig. 5.2 Tabela vectorilor de întrerupere și adresele lor………………………………………………………….42

Fig. 5.3 Registrul IEN1………………………………………………………………………………………………………43

Fig. 5.4 Registrul IEN0………………………………………………………………………………………………………43

Fig. 5.5 Registrul TCON…………………………………………………………………………………………………….43

Fig. 5.6 Registrul TMOD……………………………………………………………………………………………………45

Fig. 5.7 Diagrama de funcționare a bazei de timp………………………………………………………………….47

Fig. 5.8 Registrul SCON…………………………………………………………………………………………………….49

Fig. 5.9 Diagrama de recepție a pachetelor de la stația radio…………………………………………………..55

Fig. 6.1 Diagrama de stări și tranziții a legăturii de date. ………………………………………………………..56

Fig. 6.2 Diagrama de funcționare a stării RESET_WAIT………………………………………………………..58

Fig. 6.3 Diagrama de funcționare a stării LINK_WAIT………………………………………………………….61

Fig. 6.4 Diagrama de funcționare a stării STATE_READY (partea 1) ……………………………………….62

Fig. 6.5 Diagrama de funcționare a stării STATE_READY (partea 2) ……………………………………….63

Fig. 6.6 Schimb de mesaje de nivel legătură de date și emisia unui SST………………………………….64

Fig. 6.7 Schimb de mesaje de nivel legătură de date și apariția unei erori pe recepție………………..65

Fig. 7.1 Interfața cu utilizatorul……………………………………………………………………………………………72

Abrevieri

ACC – Acumulator

ALH – Aloha

APP – Aplicație

ASCII – American Standard Code for Information Interchange

C51 – Compilator 51

CCIT – Consultative Committee for International Telegraphy and Telephony

CR – Carriage Return

CTCON – Capture control register

DCE – Data Circuit terminatic Equipment

DLE- Data Link Escape

DPH – Data Pointer High

DPL – Data Pointer Low

DPTR – data pointer

DTE – Data Terminal Equipment

EA – External Access enable

ECM- Enable Comparation Register

EPROM – Erasable Programable Read Only Memory

ETX – End of text

FCS – Frame Check Sequence

FFSK- Fast Frequency Shift Keying

GA – Gateway Access

GTC – Go To Channel

I/O – Input / Output

I2C- Inter Integrated Circuit

IEN – Interrupt ENable

ISDN – Integrated Services for Digital Network

LA – Link Acknowledge

LR – Link Request

LT – Link Transfer

LW – Link Wait

LSB – Least Significant Bit

MAP27 – Mobile Access Protocol

MPT1327 – Ministry of Posts and Telegraph 1327

MSB – Most Significant Bit

OBJ – Object

PCON- power configuration register

PSEN – Program Store Enable

PSW- program status word

PWM – Pulse Width Modulation

RAM – Random Access Memory

RA – Radio Access

RD – Read signal

REN – Reception Enable

RI- Receive Interrupt flag

RU- Radio Unit

RW – Reset Wait

S0BUF – Serial Buffer

SCON – Serial Configuration Register

SFR- Special Function Register

SP – Stack Pointer

STX – Start of Text

SYN – Synchronization

TCON – Timer Configure Register

TI- Transmit Interrupt flag

TF1- Timer 1 flag

TMOD – Timer Modifier Register

TM2IR – Timer 2 Interrupt Register

TSC- Trunking System Controller

UA – User Access

WR – Write signal

Introducere

Motivația alegerii acestei teme are ca bază dorința de a pune în practică un sistem de comunicații prin aplicarea cunostințelor dobandite în cadrul facultații.O altă motivație este referitoare la specializarea urmată în cadrul ETTI de Rețele și Software pentru Telecomunicații, care se îmbină cu tema proiectului, aceasta necesitând atât cunoștințe de rețelistică, cât și cunoștiințe de concepere și implementare a unui cod sursă într-un limbaj de nivel înalt.

Prin extinderea serviciilor de voce și introducerea de servicii adăugate de transfer de date la viteze mici (1200 bps), sistemul poate fi utilizat în diferite aplicații.Nivelul de noutate nu este unul foarte ridicat, datorită vitezelor de transfer destul de reduse comparativ cu cele din rețelele actuale, însă funcțiile realizate de un astfel de sistem în raport cu costurile de implementare pot duce la utilizarea acestuia în anumite situații.(ex. automatizarea sau modificarea unor parametrii ale unor dispozitive de la distanță).

Obiectivele generale ale proiectului sunt implementarea nivelului legătură de date din cadrul protocolului MAP27 și a interfeței dintre utilizator și terminal pentru evidențierea capabilităților platformei modem cu ajutorul microcontrolerului Phillips 80C552.

Pentru a obține rezultatele care urmează a fi prezentate am acumulat informațiile necesare citind arhitectura microcontrolerului, nivelul legătură de date al protocolului MAP27 și elemente din cadrul comrd Code for Information Interchange

C51 – Compilator 51

CCIT – Consultative Committee for International Telegraphy and Telephony

CR – Carriage Return

CTCON – Capture control register

DCE – Data Circuit terminatic Equipment

DLE- Data Link Escape

DPH – Data Pointer High

DPL – Data Pointer Low

DPTR – data pointer

DTE – Data Terminal Equipment

EA – External Access enable

ECM- Enable Comparation Register

EPROM – Erasable Programable Read Only Memory

ETX – End of text

FCS – Frame Check Sequence

FFSK- Fast Frequency Shift Keying

GA – Gateway Access

GTC – Go To Channel

I/O – Input / Output

I2C- Inter Integrated Circuit

IEN – Interrupt ENable

ISDN – Integrated Services for Digital Network

LA – Link Acknowledge

LR – Link Request

LT – Link Transfer

LW – Link Wait

LSB – Least Significant Bit

MAP27 – Mobile Access Protocol

MPT1327 – Ministry of Posts and Telegraph 1327

MSB – Most Significant Bit

OBJ – Object

PCON- power configuration register

PSEN – Program Store Enable

PSW- program status word

PWM – Pulse Width Modulation

RAM – Random Access Memory

RA – Radio Access

RD – Read signal

REN – Reception Enable

RI- Receive Interrupt flag

RU- Radio Unit

RW – Reset Wait

S0BUF – Serial Buffer

SCON – Serial Configuration Register

SFR- Special Function Register

SP – Stack Pointer

STX – Start of Text

SYN – Synchronization

TCON – Timer Configure Register

TI- Transmit Interrupt flag

TF1- Timer 1 flag

TMOD – Timer Modifier Register

TM2IR – Timer 2 Interrupt Register

TSC- Trunking System Controller

UA – User Access

WR – Write signal

Introducere

Motivația alegerii acestei teme are ca bază dorința de a pune în practică un sistem de comunicații prin aplicarea cunostințelor dobandite în cadrul facultații.O altă motivație este referitoare la specializarea urmată în cadrul ETTI de Rețele și Software pentru Telecomunicații, care se îmbină cu tema proiectului, aceasta necesitând atât cunoștințe de rețelistică, cât și cunoștiințe de concepere și implementare a unui cod sursă într-un limbaj de nivel înalt.

Prin extinderea serviciilor de voce și introducerea de servicii adăugate de transfer de date la viteze mici (1200 bps), sistemul poate fi utilizat în diferite aplicații.Nivelul de noutate nu este unul foarte ridicat, datorită vitezelor de transfer destul de reduse comparativ cu cele din rețelele actuale, însă funcțiile realizate de un astfel de sistem în raport cu costurile de implementare pot duce la utilizarea acestuia în anumite situații.(ex. automatizarea sau modificarea unor parametrii ale unor dispozitive de la distanță).

Obiectivele generale ale proiectului sunt implementarea nivelului legătură de date din cadrul protocolului MAP27 și a interfeței dintre utilizator și terminal pentru evidențierea capabilităților platformei modem cu ajutorul microcontrolerului Phillips 80C552.

Pentru a obține rezultatele care urmează a fi prezentate am acumulat informațiile necesare citind arhitectura microcontrolerului, nivelul legătură de date al protocolului MAP27 și elemente din cadrul compilatorului Franklin. În pasul următor am trecut la implementarea propriu-zisă a legăturii de date utilizând unele din capabilitățile microcontrolerului, monitorul Franklin și câteva funcții proprii pentru depanarea mai ușoară a funcționării codului sursă.

Rezultatele obținute pe baza utilizării resurselor puse la dispoziție și a implementării unor funcții, conform cu protocolul în cauză, urmăresc obținerea conectivității de nivel 2 din arhitectura OSI, între platformă și stația radio Motorola GM1200.

Capitolul 1. Microcontroler-ul 80C552 – Arhitectura generală

Un microcontroler este o unitate de calcul integrată într-un chip. Prefixul "micro" oferă informații despre dimensiunile componentelor utilizate în construirea acestuia (dimensiuni de ordinul micronilor), în timp ce sufixul "controler" indică faptul că acest dispozitiv este conceput să supravegheze o serie de procese sau evenimente. Conceptul de microcontroler aduce cu sine și ideea de a integra în aceeași capsula o serie de circuite auxiliare (memorii RAM, circuite dedicate). Microcontrolerele au o arie vastă de aplicații, în orice domeniu unde există necesitatea unei entități cu capacitatea de a stoca, prelucra și afișa o serie de informații pentru a duce la funcționarea în parametrii normali a acelui sistem. Exemple de astfel de aplicații pot fi: sistemul de gestiune al controlului tracțiunii la o masină, a tastaturii sau mouse-ului de la calculatorul personal.

Un microcontroler este asemănător microprocesorului folosit în calculatorul personal. Exemple de astfel de microprocesoare sunt Intel 8086 sau Motorola 68000. Atât microprocesorul cât și microcontrolerul conțin o unitate centrală de procesare (UCP) ce execută funcții matematice de bază, funcții logice sau de mutare a datelor. Pentru a avea un calculator funcțional un microprocesor necesită memorie pentru gestionarea proceselor și stocarea datelor și interfețe de intrare/ieșire (I/O) pentru lucrul cu perifericele. Microcontrolerul însă, înglobeaza toate aceste funcții într-o capsulă fiind numit și „single chip computer” . Din cauza acestui tip de arhitectură apar limitări din punctul de vedere al dimensiunii memoriei și al numărului de interfețe disponibile, astfel microcontrolerele sunt folosite în sisteme care nu au cerințe foarte mari atât ca putere de procesare cât și ca stocare. Un exemplu de chipuri cu o răspândire largă este cel al familiei de microcontrolere Intel 8051.[9]

1.1. Familia Intel 8051

Intel a introdus primul microcontroler 8051 în anul 1980. De atunci mai multe companii (Phillips ,Siemens, Fujitsu) au preluat arhitectura acestuia și au dezvoltat variante noi, fiecare aducând diferite imbunătățiri. Modelul inițial folosește o memorie internă de program RAM de 4KB și poate adresa pană la 64KB și o memorie de date de 128 octeți.

Memoria de date este împărțită în trei zone, fiind acesibilă atât prin adresare directă cât și prin adresare indirectă:

– 4 bancuri de registre numerotate de la 0 la 3 ocupă locațiile de memorie de la 00h până la 1Fh. Bancul de lucru predefinit este bancul 0, comutarea pentru lucrul cu celelalte bancuri realizându-se software;

– zona adresabilă pe bit conține 16 octeți și ocupă locațiile de memorie între 20h și 27h; această zonă poate fi accesată și la nivel de octet;

– zona între 30h și 7Fh este oferită pentru definirea diferitelor variabile de către utilizator.

O caracteristică specifică microcontrolerelor 8051 este bancul de registre SFR (Special Function Register). Acesta poate fi adresat doar în mod direct având adrese începând cu 80h până la FFh și o mărime de 128 octeți. Registrele SFR au rolul de a monitoriza și controla diferitele activități întreprinse de microcontroler. Principalele funcții sunt descrise în cele ce urmează:

– registrul ACC acumulator este folosit în majoritatea instrucțiunilor;

– registrul B este folosit în intrucțiuni de înmulțire și împărțire;

– registrul PSW conține informații despre registrele aflate în folosire de către program;

– registrul SP (indicator către vârful stivei) este incrementat în timpul operațiilor de PUSH, POP și CALL;

– indicatorul (pointer) către date (DPTR) este format din doi octeți, DPH și DPL; acesta este folosit pentru a stoca o adresă cu dimensiune de 16 biți, putând fi accesat ca un întreg sau la nivel de octet;

– porturile 0-3 sunt locațiile din registrele SFR unde pot fi citiți sau scriși pini individuali ai porturilor microcontrolerului;

– bufferul de date serial (S0BUF) are rol atât de buffer serial pentru recepție cât și de buffer serial pentru transmisie; atunci în acest buffer când este scris un octet este declanșată emisia fiind setat flag-ul, iar atunci când se citește din el (flag-ul RI fiind setat), octetul citit este cel recepționat;

– registrele timerelor (TH0, TL0, TH1, TL1, TH2, TL2) sunt folosiți pentru a citi valoarea acestora la un anumit moment de timp;

– registrele de control ale microcontrolerului au diferite funcții și sunt constituite din registrul de configurare a timerelor (TMOD), registrul de configurare a interfeței seriale (SCON) ,registrul de control al alimentarii (PCON). Detalierea componenței și functionalității acestor registre va fi acoperită în descrierea implementării proiectului. [3] [5]

1.2. Caracteristici specifice Phillips 80C552 vs. cu Intel 8051

Microcontrolerul Phillips 80C552 (figura 1.1) este folosit în acest proiect, arhitectura și funcționalitățile lui cuprinzând toate caracteristicile familiei de microcontrolere 8051, la care se adaugă o serie de îmbunatățiri.

Fig. 1.1 Microcontrolerul Phillips 80C552 [4]

Memoria de program încorporată este de 8KB (4KB 8051) putând fi accesată prin locațiile de memorie cuprinse între 0h și 1FFFh atunci când pinul este în "1" logic. Adresele mai mari decât 1FFFh sunt folosite pentru a accesa numai memoria de program externă; pentru a accesa partea inferioară a memoriei de program este folosit pinul în "0" logic.

Memoria de date este împarțită în 3 zone: primii 128 de octeți sunt de uz general și pot fi adresați atât direct cât și indirect, ultimii 128 de octeți, adresați în mod direct reprezintă locațiile SFR, în timp ce adresarea indirectă a ultimelor 128 de locații din memorie, permite accesarea părții superioare a memoriei RAM. Harta memoriei microcontrolerului este prezentată în figura 1.2. [4]

Fig. 1.2 Harta memoriei microcontrolerului 80C552 [3]

Comparativ cu microcontroler-ul 8051, Phillips 80C552 are 4 timere (T0-T3) în timp ce pe Intel 8051 clasic sunt doar 2 timere (T0,T1). T0 și T1 sunt timer/counter pe 16 biți în funcție de valoarea TMOD, având patru moduri de funcționare posibile în modul timer în funcție de configurarea registrului TCON. Timerul/counterul T2 are trei moduri de funcționare posibile selectate pe baza configurării registrului SFR T2CON, iar timerul T3 este conceput pentru a fi folosit pe post de watchdog. În cadrul registrelor SFR apar și registre aferente îmbunătațirilor aduse de 80C552 (ex. CT0I-CT3I,CMI0-CMI2,IEN1,IEN2 etc.)

Alte îmbunatațiri privind arhitectura sunt două ieșiri PWM cu rezoluție pe 8 biți, două interfețe seriale, UART( Universal Asynchronous Receiver/Transmitter) și I2C (Intel 8051 doar UART), memorie RAM internă de 256 kB (128 pentru 8051), șase porturi I/O (P0-P5) și 15 vectori de întrerupere cu 2 priorități față de 5 vectori pentru 8051. Validarea sau devalidarea întreruperilor de la o anumită sursă poate fi configurată pe baza registrelor IEN0 și IEN1 pentru granularitate sau prin atribuirea valorii de 1/0 bitului EA(pentru validarea/devalidarea tuturor întreruperilor).

1.3. Detalierea blocurilor relevante

Pentru a înțelege implementarea proiectului este necesară înțelegerea modului în care am gestionat resursele microcontrolerului. La inițializarea sistemului este apelată o funcție care setează parametrii de funcționare ai microcontrolerului.

1.3.1. Registrele SFR și bancurile de registre de uz general

Registrul PCON (Control al alimentării, Adresă 87h):

Fig. 1.3 Registrul PCON ( Power Control ) [3]

SFR-ul de control al alimentării (figura 1.3) este folosit pentru a controla modurile de alimentare disponibile pentru familia de microcontrolere 8051, din care face parte și Phillips 80C552. Între modurile de alimentare disponibile pentru 80C552 acesta prezintă un mod de consum scăzut (configurabil prin bitul 1 PD-Power Down mode) și un mod inactiv (configurabil prin setarea bitului 0 – IDL din registrul PCON ).

Biții 2 și 3 din cadrul registrului SFR sunt flag-uri de uz general disponibile pentru dezvoltator, fără a avea funcționări prestabilite în timp ce biții 5 și 6 sunt rezervați.

Bitul 7 este singurul setat în această implementare, acesta având rolul de a dubla rata de baud pentru interfața serială UART, când aceasta lucrează în modurile 1, 2 sau 3. [10] [12]

Registrul TCON ( Control al timerelor, Adresă 88h, Adresabil pe bit):

Fig. 1.4 Registrul TCON [11]

Registrul SFR de control al timerelor (figura 1.4) este utilizat pentru a modifica modul în care timerele T0 și T1 operează.Acesta controlează funcționarea sau oprirea timerelor prin setarea sau ștergerea biților: 4 pentru timer 0 respectiv 6 pentru timer 1.

Biții 5 și 7 au rolul de a indica un overflow al timerelor T0 respectiv T1.În plus nibble-ul inferior conține biți nerelaționați cu timerele, folosiți pentru configurarea modului în care întreruperile externe sunt activate (IE0 și IE1) și două flag-uri care sunt setate atunci când apare o întrerupere externă(IT1 și IT0). [10]

Registrul TMOD (Modul de operare al timerelor, Adresă 89h):

Fig. 1.5 Registrul CTCON [11]

Reprezintă SFR-ul de configurare al modului în care timerele 0 și 1 functionează (figura 1.5).Acestea au fiecare 4 moduri de funcționare configurabile prin biții 4,5 (M0,M1) în cazul lui T1, respective biții 0,1(M0,M1) în cazul T0.Folosind M1 și M0 fiecare timer poate fi pe 16 biți, pe 8 biți cu reîncărcare la overflow (auto-reload), sau două timere separate.În plus T1 și T0 pot fi configurate să se incrementeze doar atunci când un pin extern este activat sau să se incrementeze la apariția unui eveniment pe un pin extern. [10]

Registrele TL0/TH0 ( T0 Inferior/Superior, Adresă 8Ah/8Ch):

Aceste două registre SFR, concatenate, reprezintă timerul 0.Comportamentul lor depinde de modul în care nibble-ul inferior al registrului SFR TMOD este configurat. Indiferent de configurația din TMOD , atunci când timerul T0 este activ cele doă registre se incrementează ( nu se decrementează).Partea configurabilă este reprezentată de evenimentele care fac TL0/TH0 să iși incrementeze valorile. [10]

Registrele TL1/TH1 ( T1 Inferior/Superior, Adresă 8Bh/8Dh):

Au același comportament ca în cazul TL0 și TH0 singura difierență fiind sursa care generează evenimente pentru modificarea valorilor lor, timerul 1.

Registrul TM2CON (Configurare T2,Adresă EAh):

Fig. 1.6 Registrul TM2CON [3]

Timer-ul 2 (figura 1.6),este un registru pe 16 biți format din alte două registre de 8 biți TMH2 și TML2 cu adresele EDh respectiv ECh, conectat la patru registre de captrură și trei registre de comparație.Registrele de comparație pot fi folosite pentru a compararea continuă a lui T2 cu o valoare prestabilită pentru aceștia în vederea setării unei întreruperi sau pentru compararea valorii lui T2 cu valorile dintr-un registru de captură. Registrele de captură pot fi folosite pentru a stoca valoarea lui T2 la un moment de timp, în vederea utilizării ei.

Bitul T2IS1, activează întreruperea datorată overflow-ului pe 16 biți al timerului; bitul T2IS0, activează întreruperea datorată overflow-ului registrului inferior al timerului; bitul T2ER, poate fi utilizat pentru a obține resetarea timerului 2, când apare un front crescător pe pinul asociat RT2 (P1.5) ; bitul T2BO, reprezintă flag-ul de overflow al registrului TML2; biții T2P1 și T2P0 sunt folosiți pentru selectarea unei pre-scalări a sursei de ceas, variantele fiind 00-ceasul microcontrolerului,01-ceas microcontroler/2,10-ceas/4,11-ceas/8; ultimii 2 biți T2MS1 și T2MS0 sunt utilizați pentru activarea și selectarea modului în care lucrează timerul. Acesta poate fi oprit prin combinația 00, folosit având frecvența de la oscilator/12, utilizat în mod de test prin combnația 10, iar prin combinația 11 acesta poate avea o sursă de oscilație proprie pe pinul T2. [10] [3]

Registrul CTCON ( Control al registrelor de captură a timerului 2, Adresă 0EBh):

Configurează cele trei registre de captură ale microcontrolerului. Funcția registrelor de captură este de a înregistra valoarea timerului 2 la apariția unui eveniment pe pinii aferenți acestora și de a provoca o întrerupere dacă este activată această funcție. Registrul este inițializat cu valoarea 82h ceea ce indică activarea pe front descrescător a registrului 3 (CTN3), folosit pentru transmisie și 1 (CTN1) folosit pentru recepție. În figura 2.7 se poate observa structura registrului CTCON.

Fig. 1.7 Registrul CTCON [11]

La declanșarea întreruperii cauzate de registrele de comparare sau înregistrare sunt activate flagurile aferente acestora fiind necesară o resetare software. Aceste flaguri sunt în registrul TM2IR și pot fi observate în figura 2.8.[3]

Fig. 1.8 Registrul TM2IR [3]

Registrul SCON (Control al interfeței seriale,Adresă 98h,Adresabil pe bit) :

Fig. 1.9 Registrul SCON [11]

Registrul SFR ,SCON ,este utilizat pentru configurarea modului în care este utilizată interfața serială UART. Acesta conține 3 biți pentru selecția modului de funcționare al serialei (SM0,SM1,SM2) , din care bitul SM2 este setat doar pentru comunicații multiprocesor. Biții 2 și 3 sunt nefolosiți , neavând o funcționalitate bine definită, în timp ce biții 0,1 și 4 au urmatoarele roluri: TI – flag întrerupere pe emisie setat hardware, RI – flag întrerupere pe recepție setat hardware , iar REN – bit care controlează activarea/dezactivarea recepției.Flag-urile trebuiesc resetate software în tratarea întreruperii pentru a putea surprinde și evenimente care apar ulterior.[12]

Registrul S0BUF (Adresă 99h):

Acesta face parte din registrele de control ale serialei el fiind inițiatorul întreruperilor de emisie/recepție serială UART. Întreruperea hardware care apare în cazul acesteia descrisă și mai sus prin intermediul flag-urilor TI și RI este datorată recepției unui octet în S0BUF sau terminării emisiei unui octet din S0BUF. Emisia din buffer-ul serialei UART este realizată prin intermediul pinului TxD ( pinul 25 al microcontrolerului sau pinul 0 din cadrul portului 3), iar recepția este făcută prin intermediul pinului RxD (pinul 24 al microcontrolerului sau pinul 1 al portului 3).[10]

Registrul IEN0 (Activarea Întreruperilor,Adresă A8h):

Fig. 1.10 Registrul IEN0 [3]

Acest registru (figura 1.10) este utilizat pentru configurarea întreruperilor pe care utilizatorul le dorește a fi active sau inactive. Bitul 7 (EA) este cel mai important pentru registrele de întrerupere având rolul de a activa sau dezactiva întreruperile (control global al întreruperilor). Când EA are valoarea 0, nici o intrare din tabela vectorilor de întrerupere nu este activă , în timp ce pentru EA=1, orice întrerupere poate fi activă, depinzând de configurarea celorlalți biți din registre IEN0 și IEN1.[10]

Pentru a trece mai pe scurt prin funcționalitățile acestor registre pentru întreruperi, o să prezint pe scurt scopul setării fiecărui bit din aceștia : bitul 6 (EAD) – activarea întreruperii de la convertorul analog/digital, bitul 5 (ES1) – activarea întreruperii pentru interfața serială I2C, bitul 4 (ES0) – activarea întreruperii pentru interfața serială UART, bitul 3/1 (ET1/,ET0) – activează întreruperea de la timerul T1/T0, bitul 2/0 (EX1) – activează întreruperile externe primate printr-un semnal venit pe pinii INT1/INT0. [3]

Registrul IEN1 (Activarea Întreruperilor,Adresă E8h) :

Fig. 1.11 Registrul IEN1 [3]

Registrul IEN1 (figura 2.11) este o continuare a registrului IEN0. În cazul Intel 8051 există un singur registru de configurare a întreruperilor numit IE, deoarece existau doar 5 surse de întreruperi. Pentru 80C552 există 15 surse de întrerupere, iar cele 8 rămase sunt configurabile prin intermediul lui IEN1. În cadrul IEN1 acțiunile efectuate de microcontroler la setarea biților sunt: bit 7 (ET2) – activare întrerupere la overflow a timerului 2, bit 6 (ECM2) – activare întrerupere dată de registrul 2 de comparație al timerului 2, bit 5 (ECM1) – activare întrerupere de la registrul 1 de comparație al T2, iar ECM0 activea întreruperii de la registrul de comparație 0 , în timp ce biții 4/3/2/1 (ECT3/ ECT2 /ECT1/ECT0) sunt setați pentru activarea întreruperii apărută în cadrul registrelor de captură datorată unei potriviri.[3]

Registrul ACC (Acumulator, Adresă E0h, Adresabil pe bit) : Acumulatorul este unul dintre cele mai ultizate registre SFR, aproape toate instrucțiunile fiind executate prin intermediul acestuia.

Registrul B (Acumulator secundar, Adresă F0h, Adresabil pe bit) : este folosit pentru două tipuri de instrucțiuni : instrucțiuni de împarțire și de înmulțire. Acesta mai poate fi folosit și ca acumulator auxiliar pentru a stoca valori temporare. [10]

Dintre bancurile de registre de uz general am folosit doar trei, în cadrul a trei întreruperi necesare pentru buna funcționare a proiectului. Aceste registre sunt bancul 1 , bancul 2 și bancul 3.

Bancul 1 de registre este folosit în cadrul utilizării serialei UART, bancul 2 este folosit pentru o interfață serială de tip bit-banging, iar bancul 3 este utilizat pentru întreruperea necesară bazei de timp pentru contorizarea evenimentelor.

Cele 6 porturi ale microcontrolerului 80C552 sunt registre adresabile pe bit, iar fiecare bit din cele 6 registre SFR corespunde unui pin fizic al acestuia. Setarea unui bit x (0≤x ≤7) din portul y (0≤y ≤7) va face ca pinul y.x din cadrul registului I/O să aibă o valoare de "1" logic în timp ce o resetarea unui bit va face ca pinul y.x din cadrul registului să aibă o valoare de "0" logic. Adresele porturilor sunt: P0 – 80h , P1 – 90h , P2 -A0h , P3 – B0h , P4 – C0h , iar P5 – C4h. [3]

Registrul PSW (Cuvântul de stare al programului , Adresă D0h , Adresabil pe bit) : este folosit pentru a stocarea unor biți importanți care sunt setați și resetați de către instrucțiunile microcontrolerului 80C552, și de aceea trebuiesc salvați de fiecare dată cand apare o comutare de contoext ( ex. în cazul unei întreruperi sau în cazul unei instrucțiuni de call). Ca biți importanți din cadrul acestui registru SFR putem menționa : fanionul de transport, fanionul de transport auxiliar,fanionul de depășire, fanionul de paritate și poate conține și biții de selectare a bancului de registre, care arată ce banc este folosit în instrucțiunea curentă. [10]

1.4 Platforma de dezvoltare cu microcontroler 80C552

În figura 1.12 sunt prezentate blocurile din cadrul schemei electrice, utilizate în proiect pentru implementarea legăturii de date descrisă de protocolul MAP27. Tot în această figură sunt prezentate și câteva semnalele aplicate pe pinii conectorilor X4, X5 și X6, rolul pe care îl au acestea urmând a fi explicat în cele ce urmează.

Fig. 1.12 Schema electrică a plăcii de dezvoltare

Caracteristicile platformei de dezvoltare IMC500,din punct de vedere hardware, sunt următoarele:

– microcontroler-ul 80C552 fără memorie internă de program;

– frecvența dată de cristalul de cuartz este de pentru ceasul sistemului este de 20MHz.

– memoria de date externă are o capacitate de 32 de octeți și un spațiu de adresare cuprins între adresele 8000h și FFFFh. Pentru selecția memoriei RAM , activă pe nivel coborât, se utilizează semnalul . Pentru a scrie în memoria RAM este folosit semnalul de control , iar pentru a citi din memoria externă de date este utilizat semnalul de control * ;

– memoria de program externă este implementată cu un circuit EPROM cu capacitatea de 32 de octeți, cuprinzând adrese începând cu 0h până la 7FFFh. Selectarea memoriei RAM pentru accesul la zona de program este făcută cu semnalul , iar semnalul de citire din RAM este făcută cu semnalul ;

– interfață serială asincronă compatibilă cu standardul RS-232;

– 3 numărătoare de tip timer/counter pe 16 biți și 1 watchdog programabil;

– 15 vectori de întrerupere din care 6 sunt externe; [8]

Capitolul 2. Protocolul MAP27.Descriere și detaliere a nivelului legătură de date

2.1. Protocolul MAP27 – generalități

Protocolul MAP27 definește o interfață între o stație radio mobilă și un terminal de date, care descrie proceduri de nivel rețea, pentru stabilirea apelurilor și a transferului de date specificat în MPT1327.

În standardul MPT1327 sunt definite reguli pentru comunicația între stații radio și controlere de sistem bazate pe trunking (TSC) care operează în sisteme radio mobile trestre. Anticipând creșterea nevoii utilizatorilor pentru comunicații de date “UK DTI Band 3 Drafting Group” a specificat o serie de servicii și proceduri pentru utilizarea sistemelor radio bazate pe trunking.

Standardul include proceduri pentru transmiterea de:

– mesaje de stare pe un canal de control,acestea fiind reprezentate printr-un număr între 0 și 31.

– mesaje scurte de date pe un canal de control, de până la 184 de biți sau 25 de caractere ASCII.

– mesaje extinse de date pe canalul de control, de până la 704 biți sau 100 de caractere ASCII.

– mesaje standard de date pe un canal de date dedicat.(date prin comutare de pachete cu o rată de baud de 1200b/s dar și o opțiune cu rate de bit mai mari).

În plus față de serviciile de date predefinite, un utilizator poate iniția o conexiune de date care nu este predefinită.

Procedurile și conexiunile specificate în acest standard sunt suficiente pentru câteva tipuri de comunicații de date,pe care utilizatorii le necesită în mod specific.Printre acestea se numără:

– mesajele cu confirmare;

– mesajele scrise/poștă virtuală;

– transferul de fișiere;

– apelurile de voce/modem;

– controlul automat al apelurilor de voce;

Pentru aceste tipuri de comunicații o interfață de date și/sau control este necesară pe fiecare stație radio. Prin această interfață utilizatorul poate conecta un terminal de date sau de control, precum un PC sau laptop. Utilizând o aplicație software dedicată pe un PC, utilizatorul poate intra și transfera date într-o manieră care nu necesită foarte multe cunoștinte legate de funcționarea acesteia.[1][9]

2.2. Stiva de protocoale

MAP27 este bazat pe arhitectura modelului de referință cu șapte straturi OSI (Open Systems Interconnection) definit de către ISO (Organizația Internațională de Standardizare). În acest standard numărul nivelurilor definite este de trei, iar acestea sunt :

– nivelul 1 sau interfața fizică;

– nivelul 2 sau nivelul legătură de date;

– nivelul 3 sau nivelul rețea;

– nivelurile de aplicație de la 4 la 7 nu sunt definite;

Interfața fizică descrie conectorul și formatul de transmisie, între un echipament terminal de date (DTE) și o stație radio într-o configurație de tip punct la punct, fiecare terminal de date având propria lui conexiune la stație. Datele standard folosesc o sub-adresă numită PORT, care poate fi alocată unei conexiuni logice sau fizice.

Protocolul de nivel legătură de date descrie schimbul de informație pe conexiunea locală utilizând o procedură orientată pe pachete de date, și va fi descris în ansamblu mai târziu în acest document.

Protocolul de nivel rețea descrie schimbul de informație capăt la capăt folosind rețeaua ca infrastructură pentru transportul pachetelor.Terminalul de date sau aplicația pot fi conectate direct, logic sau printr-un portal la un alt DTE. Tot aici sunt definite de altfel, servicii locale și funcții de control a stațiilor radio.

Un model general de rețea și stiva de protocoale asociată sunt prezentate în figurile de mai jos. Abrevieri:

APP: Aplicație sau nivel mai sus de Rețea;

UA3: Acces al Utilizatorului la nivelul Rețea;

UA2: Acces al Utilizatorului la nivelul Legătură de Date;

UA1: Acces al Utilizatorului la nivelul Fizic;

RA3: Acces Radio la nivel 3;

RA2: Acces Radio la nivel 2;

RA1: Acces Radio la nivel 1 definit de alocarea frecvențelor;

GA3: Acces al Portalului la nivel 3 (X.25 sau ISDN);

GA2: Acess al Portalului la nivel 2 (X.25 sau ISDN);

GA1: Acces al Portalului la nivel fizic.[1][9]

Stiva de protocoale folosită pentru comunicație pe căi radio, capăt la capăt între două DTE-uri este reprezentată în figura 2.1 :

Fig. 2.1 Comunicația capăt la capăt pe căi radio [2]

Comunicația a două DTE-uri printr-un portal conectat la infrastructura de rețea este prezentă în figura 2.2.

Fig. 2.2. Comunicația prin Portal (Gateway) [2]

2.3. Interfața fizică

Interfața fizică descrie conexiunile fizice dintre un echipament terminal (DTE) și o stație radio. Această definiție acoperă o conexiune de tip punct la punct folosind un subset de recomandări din standardele V.24, V.25 și RS232. În plus față de nivelele de tensiune necesare se definește și conectorul, numărul pinilor și formatul transmisiunii la nivel fizic.[9]

2.3.1. Caracteristici electrice

Acestea urmează standardul CCIT V.28 pentru semnale pe circuite nebalansate.Tensiunea la ieșire din sursă, pentru orice sarcină rezistivă între 3kΩ și 7kΩ, ar trebui să fie între +5V și +15V pentru valoarea binară “0” și între -5V și -15V pentru valoarea binară “1”.Tensiunea în buclă deschisă a sursei trebuie sa nu depășească 25V în amplitudine.

Receptorul ar trebui să detecteze valoarea “0” când tensiunea în punctul de interfațare este mai mare de +3V și valoarea binară “1” când tensiunea este mai joasă de -3V.[9]

2.3.2. Conectorul

Stația radio reprezintă un echipament de comunicații de date (DCE) care are inclus un conector specific acestui tip de echipamente. Dacă este flosit un conector de tip D, atunci unitatea radio ar trebui sa aibă fie un conector cu 25 de pini fie unul cu 9 pini, cu cel puțin subsetul minim de semnale definite în standardul V.24.

În următorul tabel este prezentată legătura dintre semnalele necesare și numărul pinului asociat atât pentru conectorul cu 9 pini cât și pentru cel cu 25 de pini. Ceilalți pini specificați în standardul V.24 pot fi folosiți pentru scopuri potrivite unui proiect specific. Semnalele sau nivelele de tensiune vehiculate ar trebui să fie în limitele recomandate de CCIT V.28, pentru a se asigura faptul că nu vor apărea probleme sau defecțiuni în cazul DTE-urilor conectate la stația radio.[9]

În realitate interfața nu este una conformă cu standardul CCIT V.28, acesta fiind una cu nivele TTL cu logică pozitivă, iar pentru adaptarea la cerințele standardului V.28 este folosit un etaj de adaptare a nivelelor de tensiune.

Fig. 2.3 Semnale de pe interfața V.24 și numărul pinilor [9]

2.3.3. Transmisiunea asincronă și viteza de transmisiune

Pentru a putea dispune de o transparența totală a datelor este folosit un format al caracterelor pe 8 biți. Caracterele sunt transmise în mod asincron cu 1 bit de start și 1 bit de stop fără a avea un bit de verificare a parității.Codul de 8 biți este identificat prin b8,b7,b6,b5,b4,b3,b2 și b1, unde b8 este bit-ul cel mai semnificativ (MSB), iar bitul b1 este cel mai puțin semnificativ bit (LSB).Combinațiile de biți formează întregi în plaja de 0 – 255 unde b8 are o pondere binară de 128, iar b1 are o pondere binară de 1.Sensul de transmisiune a biților este de la b1 (b1 fiind primul bit transmis) către b8 exemplificat în figura 3.4.[9]

Fig. 2.4 Transmisiunea asincronă [9]

Viteza de transmisiune este de 9600 biți/sec.Alte viteze de transmisiune ar putea fi ultilizate pentru implementari specifice.O valoare preferată este 1200 biți/sec.În implementarea realizată pentru acest proiect viteza de transmisiune aleasă pentru interfața de tip bit-banging dintre microcontroler și stația radio este de 9600 b/s.

2.4. Detalierea nivelului legătură de date

În această secțiune este descris pe larg protocolul legătură de date definit în standardul MAP27 pentru comunicații intre un echipament terminal de date (DTE) și o stație radio (RU).Legătura de date descrisă de protocol este una bidirecțională în sensul schimbului de date simultan în ambele direcții, indiferent dacă legătura radio este simplex sau duplex.

Nivelul legătură de date se bazează pe nivelul fizic pentru transportul transparent al datelor în formatul de 8 biți pentru fiecare caracter, iar într-o ordine inversa nivelul fizic primește de la nivelul 2 parametrii de timp negociați la inițierea conexiunii DTE-RU.[1][9]

2.4.1. Elemente de protocol

Terminologia folosită este bazată pe recomandarile CCITT T.50 (Alfabetul International No. 5 – IA5). Nivelul legătură de date folosește un subset de caractere de control în plaja 00h – 1Fh definite în T.50, și doar acele caractere de control definite în secțiunile următoare au un efect asupra funcțiilor nivelului 2 al MAP27.Partea de date (primită de la nivelul rețea) a unui mesaj de nivel legătură este total transparentă și poate conține orice caracter de 8 biți.[1][9]

2.4.2. Formatul general al unui cadru

Formatul general al pachetului start-stop, orientat pe octet este prezentat în figura 3.5.Pachetul ar trebui să înceapă cu o secvență de start combinând 3 caractere din alfabetul IA5, și anume SYN – DLE –STX.Secvența de start este urmată de un câmp antet cu o lungime constantă a câmpului de informație de 4 octeți înainte de a se aplica procedeul de DLE stuffing (va fi prezentat mai târziu).Câmpul antet poate fi la randul său urmat de un câmp variabil de date, iar acesta ar trebui să se încheie cu o secvență de stop, DLE-ETX.Fanionul DLE-ETX este urmat de un doi octeți care formează câmpul FCS.[9]

Fig. 2.5 Structura generală pachet legătură de date [1]

Câmpul de date, atunci când este prezent în pachetele de nivel 2 , conține date transparente.Pentru a transmite datele utilizatorului în mod transparent se folosește o metoda numită “DLE stuffing”.

2.4.3. Antetul cadrului de cerere legătură (Link Request)

Formatul cererii de legătura (LR) este folosit pentru a stabili sau a restabili o conexiune între două entități cu o conexiune fizică activă, acestea nu au câmp de date,iar structura antetului este ilustrată în figura 3.5.

Fig. 2.6 Antet pachet cerere legătură [1]

În formatul antetului parametrul lungime maximă N1 definește lungimea maximă a câmpului de date care poate fi transmisă printr-un LT (Transfer pe legătura de date).Formula de calcul a câmpului de date din pachetele de tip LT este: 16*(N1+1).

Dimensiunea ferestrei k, definește numărul maxim de pachete LT, cu un câmp de date maxim, care ar putea fi transmise fără a se primi confirmare pentru nici unul din ele.Valoarea prestabilită a parametrului k este 1, dar poate merge până la 255.

Numărul versiunii protocolului (VERSION) ar trebui sa aibă valori între 0 și 127, numărul acestei versiuni este 1. [1][9]

2.4.4. Antetul cadrului de confirmare legătură (Link Acknowledge)

Formatul pachetului de confirmare a legăturii (LA) este utilizat atât pentru faza de stabilire a legăturii de date între DTE și stația radio cât și pentru a confirma recepția pachetelor de tip LT.Un singur pachet LA poate confirma mai multe pachete LT, iar acestea nu au câmp de date.

Fig. 2.7 Antet pachet confirmare legătură [1]

N(R ) numărul de secventă la recepție, este numărul urmatorului pachet LT așteptat.

N(k) numărul de credit la recepție reprezintă numărul de pachete LT care pot fi transmise înainte ca emițătorul să aștepte o confirmare.În cazul proiectului curent N(k) este ales static, el având valoarea 1, astfel implementându-se o strategie de ARQ(Automatic Repeat Request) cu oprire și așteptare.Un LA emis cu o valoare a creditului de 0 va opri transmisia unui nou LT la celălalt capăt rezultând o strategie de control al fluxului de date.[1][9]

2.4.5. Antetul cadrului de transfer date pe legătură (Link Transfer)

Pachetul de transfer de date pe legătură (LT) este folosit pentru a transfera date de la nivelele de mai sus în câmpuri de date etichetate cu numere de secventă.Câmpul de date conține date de utilizator transparente cu o lungime maximă definită de parametrul N1, negociat în timpul fazei de stabilire a conexiunii.

Fig. 2.8 Antet pachet transfer de date [1]

N(S) numărul de secvență la emisie, reprezintă numărul câmpului de date, iar acesta este incrementat modulo 256 cu fiecare LT transmis.

Cererea de confirmare AR, ar trebui să aibă valoarea 0 în cazul în care confirmarea nu este imediat necesară și valoarea 1 dacă pachetul LT transmis are nevoie de o confirmare imediată. [1][9]

2.4.6. Asigurarea transparenței datelor

Metoda de “DLE stuffing” constă în faptul că, entitatea care transmite ar trebui să examineze conținutul pachetului (antetul și câmpurile de date) și să introducă un caracter de control DLE după fiecare apariție a caracterului DLE în mesaj.DLE-urile utilizate în fanioanele de început și sfârșit nu trebuiesc dublate.

Un alt aspect important în cazul asigurării transparenței datelor este faptul că singurul DLE care intră în calculul FCS este cel din fanionul de sfârșit, DLE-ul de start și cele dublate sunt eliminate înainte de calculul acestuia.

Implementarea acestei metode de asigurare a transparenței datelor utilizatorilor este listată în codul sursă al proiectului care poate fi consultat în Anexă, fiind transpusă în funcția checkDLE() care este folosită la verificarea pachetelor recepționate înainte de calculul FCS.[1][9]

2.4.7. Verificarea erorilor

Un cod polinomial de tip CRC este folosit pentru protecția la erori asupra antetului și datelor.Acesta este definit de polinomul generator: G(X) = .

Secvența de verificare a antetului și datelor (CRC – Cyclic Redundancy Check) cuprinde 16 biți și ar trebui să fie utilizată pentru detecția erorilor care pot apărea pe canal.

Biții de verificare ar trebui să fie complementul fată de 1 a sumei modulo 2 dintre:

a) Restul împarțirii modulo 2 a polinomului la polinomul G(X), unde k reprezintă numărul de biți protejati și

b) Restul împărțirii modulo 2 a polinomului generator G(X) la produsul dintre și polinomul de date, excluzând câmpul de FCS.

Această metodă de detecție a erorilor apare listată în codul sursă din Anexă sub forma a doua funcții diferite și anume: checkSumCalc() și recSumCalc() fiind necesară o funcție pentru calculul sumei de control la emisie și cealalta pentru calculul acesteia la recepție. [1][9]

2.4.8. Variabilele și numerele de secvență

Protocolul MAP27 definește câteva concepte necesare pentru a realiza cu succes o comunicație de nivel legătură de date. Acestea sunt numerotarea pachetelor transmise între entități, două perechi de variabile la emisie și recepție și starea creditului la emisie și recepție. Cu ajutorul acestor mecanisme se poate asigura recepția în ordine și fără duplicate a pachetelor dar și controlul fluxului de date în cazul în care una din entitațile participante la comunicație are o capacitate de procesare mai scăzută decât cealaltă.

Toate pachetele de confirmare și de transfer pe legătura de date ( LA și LT ) sunt numărate secvențial în fiecare dintre acestea fiind prezente variabile de stare corespunzătoare care pot avea orice valoare în plaja 0 ÷ m-1, unde m reprezintă modulul numerelor de secvență. Modulul este 256 și toate operațiile realizate pe variabilele de stare și numerele de secvență definite sunt afectate de operații modulo 256.

Pachetele LT sunt etichetate cu numărul curent de secvență la emisie N(S).Dacă un pachet LT este destinat pentru a fi emis valoarea lui N(S) este preluată din variabila de stare la emisie V(S). Aceasta din urmă, reprezintă numărul de secvență al următorului pachet LT destinat pentru emisie. Valoarea lui V(S) trebuie incrementata cu 1 cu fiecare pachet LT transmis cu succes, dar nu poate depăși N( R) al ultimului pachet LA receptionat cu mai mult decat numărul maxim de pachete LT transmise fara a recepționa LA pentru nici unul din acestea, marimea ferestrei k.

Oricărui pachet LA îi este atașat un număr de secvență la recepție N( R), care reprezintă valoarea așteptată pentru câmpul N(S) al următorului pachet LT care urmează a fi transmis de către entitatea corespondentă. Recepția unui pachet LA cu un număr de secventa N( R) poate confirma că toate pachetele LT recepționate pană la și inclusiv N( R)-1 au fost corecte. Dacă un pachet de confirmare este pregătit pentru transmisie valoarea lui N(R ) trebuie sa fie preluată din V(R ). Variablila de stare la recepție V( R) stochează numărul de secvență al următorului pachet LT care este așteptat la receție de la entitatea corespondentă.

R(k) reprezintă variabila de stare a creditului la recepție și exprimă numărul de pachete LT pe care receptorul este capabil să le recepționeze.Suma dintre numărul de pachete neconfirmate și R(k) nu poate să depășească mărimea ferestrei k.

Pachetele de confirmare (LA) conțin și o a doua variabila N(k) reprezentând creditul de la recepție.Daca un pachet LA este gata de transmisie, valoarea lui N(k) este egală cu cea a lui R(k).Acest N(k) exprimă capacitatea receptorului de a primi pachete LT numerotate pâna la și incluzând N(k)+N( R)-1.

O altă variabilă definită de protocolul MAP27 este starea creditului la emisie S(k) prin care se cunoaște numărul de pachete LT pe care emițătorul le poate transmite fără a avea o actualizare a creditului la recepție a receptorului. Valoarea variabilei S(k) este decrementată de fiecare dată cand este emis un pachet LT, iar aceasta nu poate depăși ultima valoare recepționată pentru N(k).[1]

2.4.9. Timerele nivelului legătură de date și parametrii care determină valorile acestora

Printre parametrii de sistem ai protocolului MAP27 la nivel 2 sunt definite și câteva timere de control al stabilirii legăturii în condițiile date.În cadrul acestuia sunt descrise cinci timere de control dintre care în implementarea abordată sunt realizate doar patru dintre acestea, unul dintre ele descris și în protocol ca nefiind necesar (timer-ul T2 – timer pentru confirmare de legătură) în cazul în care strategia de control al erorilor este una cu oprire și așteptare (S&W – Stop and Wait).

Timer-ul T0 – timer-ul de retransmisie în faza de stabilire a conexiunii reprezintă timpul pe care o entitate il așteaptă înainte de a iniția o retransmisie în faza de stabilire a legăturii. Valoarea inițiala a lui T0 este de 100ms, iar aceasta crește la fiecare reîncercare de ridicare a conexiunii fiind limitată la 15 secunde.

Timer-ul T1 – timer-ul de retransmisie în faza de transfer reprezintă timpul pe care o entitate îl așteaptă înainte de a face o retransmisie. Perioada de timp așteptată în cazul lui T1 este dependentă de viteza de transmisiune a conexiunii fizice dar și de marimea maximă a pachetelor de nivel 2.

Timer-ul T3 – timer-ul de activitate reprezintă timpul pe care o entitate il asteaptă înainte de a transmite un pachet de confirmare (LA) pentru a raporta creditul disponibil pentru recepție.Acesta poate avea o valoare de maximum 15s.

Timer-ul T4 – timer-ul de detecție a eșuarii legăturii reprezintă timpul pe care o entitate îl așteaptă pentru a recepționa o confirmare sau un pachet de transfer de date înainte de a concluziona că a avut loc o eșuare a conexiunii și de a iniția o resetare a legăturii de date. Valoarea acestuia trebuie să fie cu o perioadă mai mare decât N3*T3.

În cele ce urmează sunt prezentați parametrii necesari pentru a putea defini valorile timerelor descrise mai sus:

N1 – lungime maximă – definește lungimea maximă a câmpului de date din cadrul pachetului de transfer de date pe legătură (LT). Acest parametru poate avea valori în plaja 0 – 255. Lungimea maximă a câmpului de date în octeți este calculată cu formula:

= 16*(N1+1)

Cu N1=0 numărul maxim de octeți de date este 16, iar cu N1=255 lungimea maximă a campului de de date este 4096.Valoarea aleasă pentru acest parametru trebuie să fie destul de mare pentru a încadra cel mai lung pachet de nivel Rețea.

N2 – numărul maxim de retransmisii – definește numărul maxim de încercări ale unei entități pentru a transmite cu succes un pachet de transfer de date (LT) către entitatea corespondentă.După cum descrie protocolul MAP27 valoarea acestui parametru ar trebui sa fie 10.

N3 – numarul maxim de pauze de activitate – definește numărul de pauze pe care le poate avea timerul T3 înainte de a se detecta un lipsă a activității pe legătura de date.N3 și T3 sunt folosite pentru defininirea valorii timerului T4. Valoarea lui N3 trebuie sa fie cel puțin 2. [1]

2.5. Situații de stabilire a conexiunii de nivel legătură de date

În prima situație prezentată în figura 2.9 are loc negocierea parametrilor între cele două entități. Negocierea parametrilor este făcută prin cele 3 mesaje de cerere de legătură, stația apelantă modificându-si parametrii în funcție de cei ai stației apelate care parametrul N1=10.

Fig 2.9 Situația de stabilire a conexiunii cu negociere a parametrilor

Cea de-a doua situație posibilă privind stabilirea legăturii de date este prezentată în figura 2.10. Se poate observa că în acest caz nu mai este necesară modificarea parametrilor nici de către stația apelantă, nici de către stația apelată, ambele având parametrul N1=10.

Fig 2.10 Situația de stabilire a conexiunii fără negocierea parametrilor

În cadrul proiectului s-au acoperit ambele situații de stabilire, iar acestea vor fi prezentate în detaliu în capitolul 6 unde este descrise stările principale de la nivelul legătură de date și tranzițiile posibile între acestea.

Capitolul 3. Comunicații mobile de tip trunking.Comunicații MPT1327

MPT1327 este un standard de semnalizare pentru sisteme radio mobile terestre private cu configurație trunk. Acesta definește un set de reguli pentru comunicația intre un controller de sistem de tip trunking ( denumit în continuare și TSC(trunking system controller) și echipamentul terminal radio (denumit în continuare și RU(radio unit)).

3.1. Tipuri de apeluri

Protocolul pune la dispoziție o gamă largă de facilități care pot fi implementate și puse la dispoziția utilizatorilor, dar nu este neapărat necesară implementarea tuturor pentru o aplicație particulară.

Facilitațile descrise în standard care pot fi implementate și puse la dispoziția utilizatorilor sunt următoarele: apelurile de voce, apelurile de date, apelurile de urgență, serviciul de conferință, mesajele de stare, mesajele de date scurte; [9]

3.2. Canalul de control

Sistemul de control definit de protocol folosește semnalizări la o rată de baud de 1200 b/s modulând o subpurtătoare cu FFSK (Fast Frequency Shift Keying) și este conceput pentru a fi folosit de stații radio care operează cu două frecvențe în modul bidirecțional alternant.Semnalizările pentru efectuarea unui apel sunt transmise pe un canal radio de “control”.Un TSC poate opera folosind una din cele două strategii ale canalului de control, acestea fiind cu canal dedicat sau nededicat.

Un sistem dedicat are un canal de control disponibil tot timpul pentru semnalizări, în timp ce un sistem nededicat poate folosi canalul de control pentru trafic (de voce sau de comunicații de date) dacă toate celelalte canale sunt ocupate de alte apeluri.Utilizarea unui canal de control dedicat este potrivit pentru un TSC cu multe canale, în timp ce un sistem nededicat este mai potrivit pentru cazul în care sunt alocate puține canale de trafic, protocolul permițând utilizarea oricărei strategii din cele două prezentate.

Una dintre problemele sistemelor de semnalizare radio mobile este interferența mesajelor pe mediul comun provenind de la stații radio diferite care transmit în același timp.Această problemă este rezolvata în cazul MPT1327 cu ajutorul unui protocol de acces aleator la mediu numit Random Access Protocol, bazat pe metoda de acces Aloha, care oferă flexibilitate, stabilitate și eficiență ridicată.

Protecția împotriva coliziunii semnalelor este implementata prin etichetarea semnalizărilor cu un cod de identitate a sistemului, care în unele mesaje poate fi reprezentat chiar de numărul canalului folosit.Dacă interferențele sunt mari, atunci controlul poate fi mutat pe un alt canal. [2]

3.3. Tratarea apelurilor

Protocolul este proiectat pentru a fi ultilizat de sisteme cu coadă de apeluri în care apelul nu este efectuat imediat în cazul în care nu există canale disponibile în momentul inițierii acestuia de către apelant.

Înainte ca un canal de trafic sa fie rezervat pentru o stație radio, TSC-ul verifică dacă unitatea apelată este în raza de acoperire, pentru a evita risipa de canale.Semnalizarile pentru mentenanța apelurilor este definita astfel încat la sfârșitul conversațiilor canalele sunt eliberate imediat.Ca precauție împotriva utilizării frauduloase a sistemului de către o unitate radio neautorizată, TSC-ul poate instrui stația radio să transmita identificatorul său unic.Comparând valoarea primita cu cea așteptată va ajuta la detectarea unui utilizator fraudulos. [2]

3.4. Adresarea

O adresă a unei stații radio este un număr de 20 de biți care cuprinde două câmpuri: un prefix de 7 biți și un ident pe 13 biți, toate terminalele din cadrul unei arii de acoperire a TSC-ului având acelasi prefix.Diviziunea realizată prin prefix și ident din cadrul adresei stațiilor, permite ca majoritatea mesajelor transmise de acestea în interiorul aceleuiași TSC să conțina două adrese, cea a apelantului și cea a stației apelate, incluzând o singură dată prefixul.Pentru a exemplifica, cererile de apel și mesajele de tip “Go To Channel” conțin două ident-uri și un singur prefix. [2] [9]

3.5. Transmitere a unui mesaj scurt de date.

În figura 3.1 este ilustrată o secvență de mesaje pe canalul de control, schimbate între stații radio cu același prefix, pentru a efectua un apel.Secvența conține cererea de apel, verificarea disponibilitații și semnalizarea necesară alocării unui canal.

Fig. 3.1 Mesaje MPT1327 pentru transmiterea unui mesaj scurt [2]

1.ALH: invitație Aloha generală (cadru de 3 sloturi).

2.RQS: cerere de apel cu acces aleator.

3.AHY: mesaj de verificare a disponibilitații.

– confirmă mesajul RQS;

– necesită un răspuns de la stația apelată (în acest fel verificând contactul radio cu stația apelată);

– inhibă acesul aleator în slotul următor.

4.ACK: confirmare de la stația apelata, trimisă în slotul rezervat.

5.GTC: mesaj “Go To Channel”, care indică celor două stații să comute pe un canal de trafic pentru apelul inițiat.(în acest mesaj GTC apare de două ori pentru siguranță). [2]

Capitolul 4. Compilatorul Franklin C51, fișierele necesare pentru rularea codului sursă, hiperterminalul și programul monitor

4.1. Compilatorul Franklin C51

Franklin C51 a fost creat pentru a fi folosit pe sisteme ce rulează MS-DOS în cadrul compilării codurilor de limbaj înalt, implementat în conformitate cu standardele ANSI (American National Standards Institute) pentru limbajul C. Limitările acestuia sunt date de faptul că nu poate compila orice program de limbaj C, el având ca scop optimizarea și generarea de coduri cât mai compacte pentru microcontrolerele din familia 8051 [3].

Pentru a putea folosi acest compilator, în urma copieri tuturor fișierelor și librăriilor acestuia, a fost necesară declararea unor variabile de sistem și de utilizator în cadrul sistemului de operare (Environment Variables). Aceste variabile includ calea C51 și celelalte sisteme de dezvoltare din cadrul acestuia ( PATH \C51\BIN ), calea pentru accesul la librăriile standard ale compilatorului ( C51LIB \C51\LIB ) și calea către alte librării create de dezvoltatorul de aplicații ( :INCLUDE: \C51\INCLUDE )[4].

Execuția unui program se face prin comanda "c <nume program>", iar în urma execuției, dacă programul nu a avut erori, compilatorul generează patru fișiere cu extensie diferită : <nume program>.LST , <nume program>.OBJ, <nume program>.I și <nume program>.SRC.

Fișierul <nume program>.LST a fost folosit în cadrul proiectului pentru a determina liniile de program care au avut erori la compilare.

4.2. Fișiere necesare pentru rularea codului sursă din hiperterminal, utilizând programul monitor

Primul fișier necesar este STARTUP.A51, care este declarat ca fiind public pentru a putea fi apelat din exterior și este utilizat pentru a crea un segment de cod la adresa 8000h pentru lucrul cu monitorul și pentru a elibera memoria internă, externă și de program.

Al doilea fișier este salturi.asm, în care am declarat funcțiile care folosesc întreruperi ca EXTERN CODE, pentru a putea fi apelate din exterior, și am relocat adresele vectorilor de întrerupere deasupra monitorului.Toți vectorii de întrerupere folosiți, nu mai au ca adresă 00xxh, acestea fiind schimbate în 80xxh.

Alt fișier folosit este C.BAT, care după cum arată și extensia este un fișier batch în care am scris o listă de comenzi necesare pentru asamblare, compilare, realizarea legăturilor ( prin intermediul linker-ului) și conversie. Pentru a fi mai explicită ordinea comenzilor, conținutul fișierului C.BAT este prezentat în figura 4.1.

Fig. 4.1 Fișierul C.BAT

În cadrul primelor două comenzi este folosit asamblorul a51 pentru fișierele deja prezentate mai sus. A treia linie din cadrul fișierului batch reprezintă compilarea propriu zisă a codului sursă de către compilatorul Franklin ( sintaxa %1.c reprezintă o modalitate de a putea introduce de la tastatură numele codului dat către C51).

În continuare, în urma generării fișierelor de ieșire de către C51, este invocat generatorul de legături (linker-ul). Linker-ul atribuie adresele clare pentru toate variabilele și generează fișierul <nume program>.exe. Pentru a putea realiza aceste sarcini, acesta necesită în mod explicit zona memoriei de program în care să pună codul și dimensiunea memoriei RAM, pentru a ști ce adrese poate să aloce variabilelor. Directiva IXREF este utilizată în cadrul linker-ului pentru a crea o referință în cruce în fișierul <nume program>.M51 (harta de legături a linker-ului) care include atât simbolurile publice cât și pe cele externe.

Fișierul <nume program>.M51 a fost folosit în cadrul proiectului pentru a determina adresele unor variabile sau a zonelor de memorie alocate bufferelor de emisie/recepție.

Directiva NOOVERLAY dezactivează suprapunerea memoriei utilizate de către variabilele locale și argumentele funcțiilor.

Convertorul ohs51 este utlizat pentru a transforma fișierul <nume program>.exe într-un fișier Intel HEX, <nume program>.HEX, compatibil cu microcontrolerul 80C552. În final fișierele .exe și .obj sunt șterse, ele nefiind necesare.

4.3. Hiperterminalul și programul monitor

Pe placa de dezvoltare se află într-o memorie flash un program monitor (figura 4.2) care este utilizat pentru o depanare mai ușoară a codului sursă, el având comenzi de afișare a memoriei externe, de ștergere a memoriei, dar și de execuție a zonei de program.Pentru că programul monitor lucrează în memoria externă de program, aceasta începând cu adresa 0000h și încheindu-se la adresa 7FFFh, monitorul adună la toate adresele primite de la microcontroler 8000h, astfel fiind tratate și întreruperile.

Din funcțiile de depanare pe care le deține monitorul, cea mai utilă a fost funcția de afișare din memoria externă de date. Pentru a reuși să observ conținutul bufferelor de emisie/recepție am obținut adresele de început a acestora din fișierul M51, iar apoi am utilizat funcția DX.

Alte funcții folosite din cadrul monitorului sunt funcția de afișare din memoria de program (DC) , funcția de umplere a unei zone de memorie externă cu o valoare (FILLX) și funcția de execuție a programului în urma transferului fișierului Intel HEX, (G 8000).

Fig. 4.2 Programul monitor

În afară de funcțiile de depanare pe care acesta le oferă, el lucrează într-o aplicație hiperterminal, în cazul nostru hiperterminalul este Tera Term, care este unul gratuit. Rolul hiperterminalului este de a transfera prin intermediul unei interfețe seriale fișierul Intel HEX, în memoria de date a microcontrolerului, în zona de cod definită pentru linker.

Interfața serială prin care acesta transmite este configurată după cum se poate observa și în figura 4.3 sunt de transmisie asincronă cu baud rate de 9600b/s, un singur bit de stop și 1 milisecundă de pauză după fiecare linie de cod mașină.

Fig. 4.3 Configurația hiperterminalului teraterm pentru comunicația cu UART

Capitolul 5. Implementarea software a modulelor necesare funcționării nivelului legătură de date pentru protocolul MAP27

5.1. Schema bloc a unui sistem de comunicații MPT1327 – conexiune MAP27

Ansamblul sistemelor prezentate în figura 5.1 permite prin interconectarea acestora o comunicație pe cale radio, capăt la capăt, utilizând protocolul MAP27 și standardul MPT1327. Modemul FSK a fost pus cu fundal alb deoarece acesta nu a fost încă implementat.

Fig. 5.1 Diagrama modulelor hardware ce alcătuiesc schema de principiu a proiectului

5.2. Întreruperi folosite în cadrul implementării

Dintre cele 15 surse de întreruperi prezentate în această tabela din figura 5.2, în cadrul proiectului s-au folosit doar 4,două dintre acestea fiind folosite pentru deservirea serialei UART și actualizarea variabilelor de timp, iar două dintre acestea sunt utilizate pentru interfața serială bit-banging.

Fig. 5.2 Tabela vectorilor de întrerupere și adresele lor [3]

Vectorul de întrerupere al serialei asincrone implementată hardware în cadrul microcontrolerului are adresa 0023h, iar pentru baza de timp, folosind timerul T0, acesta are valoarea 0013h, acestea fiind prioritizate începând cu valoarea cea mai mică. Prioritățile întreruperilor pot fi schimbate pentru cazul în care o întrerupere mai importantă dintr-o anumită implementare are prioritate mai mică decat altele, astfel putând fi întreruptă de o alta, însă pentru legătura de date nu a fost necesar. Registrul SFR utilizat pentru modificarea priorității întreruperilor este IP ( Prioritatea Întreruperilor) care are adresa B8h și este adresabil la nivel de bit.

Pentru a putea lucra cu monitorul Franklin a fost necesare câteva instrucțiuni în limbaj de asamblare, deoarece era nevoie sa se sară peste întreruperile de la adresele descrise mai sus. Tot în limbaj de asamblare este facută și legătura între funcțiile din limbaj înalt și adresele vectorilor de întrerupere folosite pentru acestea prin sintaxa : void nume funcție () interrupt x. qq mai întreb

Validarea întreruperilor ce țin de registrele de comparare sau captură se face cu ajutorul registrului SFR IEN1. Bitul ET2 valideaza întreruperile de depășire pentru timerul 2. Biții ECM validează întreruperile registrelor de comparație în timp ce biții ECT întreruperile registrelor de captură. Strictura registrului este prezentată în figura 5.3.

Fig. 5.3 Registrul IEN1 [3]

Registrul IEN0 folosit pentru a activa anumite întreruperi asociate timerelor și a unor evenimente externe, fiind adresabil doar pe bit. Pentru a putea avea comunicație între terminal și microcontroler în cadrul programului monitor trebuie activată întreruperea aferentă serialei existente a microcontrolerului (setarea bitului ES0 are acest efect). De asemenea trebuie setat și bitul pentru activarea întreruperii pe timerul 0 (ET0) folosită pentru implementarea unor timere software folosite în cadrul aplicației. Biții EX0 și EX1 au efectul de a activa întreruperile externe care pot fi declanșate în urma unor tranziții pe front crescator sau descrescător pe pinii asociați acestora. La finalizarea tuturor setărilor asupra registrelor SFR ale microcontrolerului este setat și bitul EA acesta validând global întreruperile. Această setare este lasată la final pentru a evita situația în care apariția unor întreruperi înaintea configurării corecte a registrelor SFR poate duce la funcționarea defectuoasă a sistemului.

Fig. 5.4 Registrul IEN0 [3]

5.3. Realizarea bazelor de timp pentru contorizarea evenimentelor

După cum am prezentat și în partea teoretică a acestei lucrări protocolul MAP27 descrie pentru nivelul legătură de date cinci timere necesare pentru monitorizarea evenimentelor și asigurarea bunei funcționari a acesteia.

În implementarea abordată funcția care controlează toate aceste contoare de timp se numește contor.Pentru realizarea unei baze de timp cu ajutorul căreia să se actualizeze toate cele patru timere din cadrul protocolului, unul nefiind necesar datorită strategiei de control al erorilor folosită (cu oprire și așteptare) în cazul căreia se transmite/recepționează un mesaj de confirmare după fiecare pachet recepționat/transmis, am folosit una din resursele microcontrolerului și anume timerul T0.

Fig. 5.5 Registrul TCON [3]

Fig. 5.6 Registrul TMOD [3]

Pentru activarea timerului T0,timer pe 16 biți, din cadrul microcontrolerului a fost setat în registrul TCON, bitul 4 (TR0), acesta operând în modul free running. Având nevoie de un contor de timp exact am folosit modul timer de operare a lui T0 setând bitul 1 din cadrul registrului TMOD (M0), dar și registrele acestuia. Folosirea registrelor a fost necesară datorită necesității unei operații de reinițializare automată (auto-reload) a valorii de la care pornește timerul de fiecare dată când are loc un overflow.

Frecvența cristalului de cuartz folosit pentru generarea tactului microcontrolerului este una de 20MHz. Pentru a avea o rezoluție cât mai bună a bazei de timp (figura 5.7) am decis că este necesară o întrerupere dată de timer la fiecare miime de secundă.Întreruperea folosită după cum se poate vedea și în codul din anexă este definită de sintaxa interrupt 1 din tratarea funcției, aceasta fiind o întrerupere proprie timerului 0, setată hardware la fiecare overflow (bitul 5 din registrul TCON – TF0 ) și resetată prin apelarea rutinei de servire a întreruperii.

Pe baza acestor considerente ( frecvența cristalului de cuartz și întreruperea dată de timer la overflow) am calculat valoarea de inițializare a lui T0 pentru care acesta generează o întrerupere la fiecare miime de secundă. Valoarea rezultată în hexazecimal este 0xF97D.

Microcontrolerul folosește o prescalare a frecvenței cuartz-ului, aceasta fiind divizat cu 12:

= = 1666666,66666667

Această valoare va fi notată cu .

Pentru o întrerupere de ordinul unei miimi de secundă este necesară o frecvență de overflow de 1kHz.Valoarea necesară pentru divizarea frecvenței de tact este notată cu x.

Transformând în hexazecimal numarul 1666 => 0x682 (numărul incrementări până la overflow);

0xFFFF- y = 0x682 => y=0xFFFF-0x682 => y=0xF97D.

Am folosit această valoare pentru a implementa o reîncarcare automată a timerului, care este setat să numere „în sus” până la valoarea de overflow 0xFFFF. În partea de inițializare a registrelor SFR, registrele acestuia (TL0 și TH0) au valoarea 0x7D respectiv 0xF9. Cu o aproximație foarte bună, la aproximativ o miime de secundă de la execuția programului o să apară o întrerupere cauzată de T0. Pentru ca aceasta să devină una periodică primele două instrucțiuni din cadrul funcției apelte pentru servirea întreruperii sunt folosite pentru reinițializarea registrelor lui T0 cu aceeași valoare 0xF97D.

Având această bază de timp (figura 5.7) dată de întreruperea la fiecare miime de secundă, generarea unor contoare de timp la nivel de sutimi, zecimi și secunde a fost o sarcină mai simplă. Am definit variabile miimi, sutimi, zecimi, secunde de tip unsigned char și le-am inițializat cu valoarea 10 pentru primele trei respectiv 60 în cazul secundelor.

Pentru a putea controla mai ușor trecerea timpului, am definit și un flag, flzec, pe care îl setez de fiecare dată când a mai trecut o zecime de secundă și îl resetez, prelucrând în interiorul condiției care verifică setarea acestuia informația furnizată de el. Toate variabilele de timp sunt decrementate la trecerea unei unități din fiecare, acest lucru facându-se în “cascadă”.

În figura 5.7 se pot urmări pe diagragramă pașii urmați în servirea întreruperii dată de către timerul 0 la fiecare overflow. Ultimul bloc al diagramei prezină și setarea flagului fl_zec, acesta fiind baza peste care s-a construit o funcție externă de actualizare a contoarelor de timp mai mari decât ordinul zecimilor de secundă.

Fig. 5.7 Diagrama de funcționare a bazei de timp

Datorită constrângerilor de timp datorate vitezei ridicate a serialei dintre microcontroler și stația radio în comparație cu capacitatea de procesare relativ redusă a acestuia, am fost nevoit să reduc timpul necesar realizării înteruperii pentru baza de timp.

Soluția propusă este bazată pe tratarea contoarelor vitale pentru funcționarea cât mai precisă a transmisiei și recepției pe interfețele seriale în interiorul întreruperii, și actualizarea celorlalte contoare de timp cu o rezoluție de o sută de ori mai mică decât a celui din întrerupere, într-o funcție externă denumită timp.

Această funcție este apelată periodic în cadrul programului, și actualizează toate timerele mai mari de o zecime de secundă pe baza unui flag setat în întrerupere pentru semnalarea trecerii acesteia.

5.4. Realizarea funcționalității timerelor de la nivelul legătură de date

5.4.1. Timer-ul T0

Este timerul de retransmisie în faza de stabilire a conexiunii de nivel LD și este implementat prin două funcții necesare pentru controlul total asupra acestuia. Rezoluția lui T0 este una dinamică, care se întinde în plaja de valori începând de la 100ms pâna la 15sec ceea ce a facut dificilă tratarea acestuia. Pentru realizarea funcțiilor care definesc T0 am definit o variabilă pentru valoarea curentă a sa numită ctTm0, un flag fl_T0 pentru a indica dacă timerul este activ sau este oprit și un index,idx_retT0, pentru menținerea numărului de reîncercări de stabilire a conexiunii.

Inițializările sunt facute în funcția initvar unde ctTm0 este predefinit cu valoarea 1, flagul are valoarea 0, iar idx_retT0 cu 1.

La apelarea funcției de activare a timerului T0, START_T0, flag-ul de activitate al T0 este setat și ctTm0 ia valoarea 10, el fiind decrementat chiar în funcția contor la trecerea fiecărei sutimi de secundă. În cazul în care legătura nu este stabilită în perioada de 100ms ( nu este apelată funcția STOP_T0), atunci acesta expiră. La expirare este apelată din nou funcția START_T0, având idx_retT0 deja incrementat la prima apelare, astfel următorul interval de stabilire are o durată de 200ms. În cazul în care se ajunge la valoarea maximă de 15 secunde și legătura ramâne nestabilită valoarea indexului este resetată, iar T0 începe din nou de la valoarea inițială de 100ms.

Funcția STOP_T0, oprește funcționarea lui T0 resetând flag-ul fl_T0 și reinițializează variabilele ctTm0 și idx_retT0.

5.4.2. Timerul T1

Acest timer este implementat în interiorul funcțiilor start_T1 și stop_T1 prin variabila sutT1. Valoarea acestui timer este setată în funcție de viteza de transmisie de la nivelul fizic. În protocolul MAP27 este reprezentat un tabel în care pentru viteza de transmisiune de 9600b/s indică faptul că valoarea timerului ar trebui să fie de 0,5s.

După cum se poate observa în cadrul funcției start_T1 variabilei sutT1 îi este atribuită valoarea 50. Această valoare este decrementată în funcția timp, după cum a fost prezentat în subcapitolul 6.3 Realizarea bazelor de timp pentru contorizarea evenimentelor. Flag-ul care apare în cadrul start_T1 are rolul de a indica dacă timerul este activ sau dacă este oprit, pentru a face diferența între o ajungerea variabilei sutT0 la valoarea 0 din cauza trecerii celor 0,5 secunde și inactivitatea acestuia.

Funcția stop_T1 este implementată pentru a reseta valoarea variabilei sutT1 și pentru a reseta flag-ul de activitate al timerului fl_T1.

6.4.3. Timerul T3

Implementarea timerului de activitate T3, este asemănătoare cu cea prezentată în cazul T1, și acesta având definite două funcții start_T3 și stop_T3. Diferența o face cuanta de modificare a acestui timer, care este de ordinul secundelor, valoarea maximă a acestuia putând fi 15 secunde. În cadrul implementării valoarea de start a lui T3 este de 6 secunde.

T3 este folosit pentru a menține legătura de date ridicată, în urma negocierii parametrilor. Valoarea acestui timer a fost setată pe baza descrierii protocolului MAP27 dar și pe baza observațiilor experimentale din comunicația cu stația radio.

6.4.4. Timerul T4

Timerul care detectează eșuarea legăturii de date T4, este implementat tot pritr-o funcție de start și una de stop, având declarate un flag de activitate fl_T4 și o variabilă secT4. Variabila secT4, conform protocolului trebuie să aibă o valoare de minim două ori mai mare decât secT3, în implementarea curentă valoare de start a lui T4 este de 20 de secunde. Variabila secT4 este decrementată tot în cadrul funcției de actualizare a variabilelor de timp, timp.

6.5. Utilizarea UART pentru comunicația dintre microcontroler și terminal

Registrul PCON este setat cu valoarea 80H ceea ce indică setarea MSB în 1 logic. Bitul MSB este singura poziție ce prezintă importanță în situația abordată, acesta permițând folosirea unei rate de baud dublă pentru conexiunea serială implementată în microcontroler.

Registrul SCON este cel folosit pentru configurarea uneia dintre cele două seriale disponibile pe microcontrolerul Phillips 80C552, aceasta fiind interfața serială UART.

Fig. 5.8 Registrul SCON [3]

Acesta este folosit în comunicația dintre terminal și placa de dezvoltare. Este initializat cu valoarea 50h ceea ce indică setarea biților din pozițiile 4 și 6. Setarea bitului SM1 împreuna cu nesetarea bitului SM0 indică funcționarea seriale în modul 1. În modul 1 portul are funcționalitățile unui port serial de tip UART(universal asynchronous receiver/transmitter) pe 8 biți a cărui rată de baud poate fi setată explicit. Bitul REN are rolul de a valida sau nu recepția putând fi setat software. TI și RI sunt flaguri(fanioane) setate automat în momentul terminării de transmis respectiv recepționat un octet acestea necesitând o resetare software pentru a permite transmiterea sau recepția unui nou octet.În figura 8 poate fi observată structura registrului SCON.

Pentru a asigura rata de baud a comunicației dintre calculator și microcontroler am folosit timerul 1 în modul reîncărcare și nevalidând întreruperile la depășire. Pentru a calcula valoarea de reîncărcare a timerului am folosit formula : , unde k are valoarea 2 datorită folosirii opțiunii de dublare a ratei de baud. Un calcul simplu relevă valoarea de reîncărcare pentru registrul TH1 de F5h pentru o rata de baud de 9600 utilizând un oscilator de cuartz cu frecvența de 20 MHz.

Funcția din codul sursă care tratează transmisia și recepția pe interfața cu terminalul este

void cons_ser(void). În această funcție care tratează comunicația pe UART am folosit întreruperea proprie acestuia , care în tabela vectorilor de întrerupere este pe poziția 4 , vectorul de întrerupere pentru deservirea acesteia având adresa 0023H.

Funcționarea acestei interfețe se face la nivel de octet, emisia facându-se automat atunci când în tamponul S0BUF este scris un octet. După transmiterea unui octet flag-ul TI este setat hardware semnalând o întrerupere, la fel și la recepție, unde după un octet receptionat este setat hardware flag-ul RI, care indică o întrerupere pe recepția UART.

În cadrul funcției cons_ser este realizată atât tratarea recepției cât și cea a emisiei.Pentru a implementa transmisia serială am definit un buffer de caractere numit bfemcons și un index numit idx_em_cons.

Transmisia serială începe odată cu scrierea unui caracter în S0BUF care emite automat primul octet și ridica flag-ul TI. Flag-ul este resetat software ,iar transmisia se face octet cu octet incepând cu indexul de la 1, și incrementându-l până cand se ajunge la o valoare vidă în bfemcons reprezentată de caracterul TERM (terminator sau CR).Atunci când se ajunge la CR resetez un flag numit fl_emcons pentru a știi că informația din buffer a fost transmisă. Flagul fl_emcons provine dintr-o altă funcție care îmi declanșează emisia caracterelor din buffer și urmează a fi prezentată.

Declanșarea emisiei pe seriala cu DTE-ul este făcută prin funcția decl_em_cons care are rolul de a inițializa valoarea indexului idx_em_cons cu 1, de a seta flag-ul fl_emcons și de a pune în registrul S0BUF primul caracter din bfemcons.

Recepția serială este declanșată de recepționarea în S0BUF a unui caracter, ceea ce face ca flag-ul RI să fie setat, iar în deservirea întreruperii în cadrul cons_ser RI este resetat după care se copiază în bufferul de receptie bfreccons caracterul primit.

5.7. Utilizarea serialei asincrone de tip bit-banging pentru comunicația între stația radio și microcontroler.

5.7.1. Cazul emisiei

În cazul emisiei de la DTE către stația Motorola GM1200, funcția decl_em_radio este cea care preia informația din bufferul bfemradio și o pune bit cu bit pe pinul conectat pentru transmisie cu stația. Funcția de emisie decl_em_radio primește ca parametru doar lungimea bufferului din care este preluată informația pentru a fi transmisă.

Bfrecradio împreună cu bfemradio reprezintă interfețele între cele două implementări de nivel fizic și nivel legătură de date.

Pentru a realiza o emisie către stația radio este necesar să pun în bufferul bfemradio informația, acest lucru realizându-se în cadrul funcției care adaugă secvențe de Data Link Escape pentru asigurarea transparenței, și să apelez funcția decl_em_radio dându-i parametrul de lungime lgem1.

5.7.2. Cazul recepției

În cazul comunicației având ca sursă stația radio, funcția getoct concepută pentru comunicația asincronă între aceasta și microcontroler, preia de pe interfața bit-banging bit cu bit informația și o înscrie în bufferul de recepție bfrecradio (figura 5.9) . Tot în getoct este menținută și informația legată de lungimea mesajului emis de către stație, necesară mai târziu pentru efectuarea unor teste asupra formatului.

Fig. 5.9 Diagrama de recepție a pachetelor de la stația radio

După prelucrarea informației de la stația radio de către funcția getoct, aceasta este testată la nivel de cadru pentru a se asigura integritatea conform protocolului MAP27. Pentru a mă asigura că structura cadrului este una conformă, am construit o mașină de stări simplă care testează octet cu octet atât secvența de start cât și secvența de stop prin intermediul funcției Rec_pkt_R.

În interiorul Rec_pkt_R am definit o variabilă internă I pentru o bucla for și am inițializez valorile pentru indexul de parcurgere al bufferului bfrecradio, idx_R , pentru starea de la care se pleacă în cadrul parcurgerii și pentu flag-ul chix care îmi indică dacă unul dintre octeții primiți nu a fost cel așteptat. Cu ajutorul flag-ului chix este implementat conceptul de aruncare al pachetului care nu îndeplinește condițiile de integritate.

Funcționarea testării este bazată pe un switch-case pe care îl parcurg până cand lungimea pachetului din bfrecradio ajunge la 0. Dacă la o iterație a ciclului for octetul primit este cel așteptat variabila stare este incrementată urmând sa verific următorul octet, iar după parcurgerea fiecărui caz este testată valoarea chix. În cazul în care valoarea lui chix este 1, atunci reinițializez stare cu 1 și ies din funcție ignorând pachetul.

Valoarea la care trebuie să ajungă variabila stare în cazul în care recepția este una corectă este 7, iar dacă se ajunge la această valoare setez un flag numit fl_pkt_R pentru a face în continuare tratarea pachetului și a prelua informația utilă din acesta.

Tot în Rec_pkt_R apar inserate și alte două funcții care au rolul de a verifica CRC-ul și de a elimina secvențele de DLE introduse de către entitatea emitentă pentru a asigura transparența datelor. Funcționalitatea acestora va fi prezentată în cele ce urmează.

5.8. Funcția de verificare a erorilor

Void ChecksumCalc ( unsigned char *buff, unsigned int len) este funcția de verificare ciclică a redundaței (CRC) la emisie, care are ca parametru de ieșire o valoare de 16 biți, utilizată de receptor pentru compararea cu rezultatul propriu al verificării pe pachetul recepționat. După cum se poate observa, aceasta necesită doi parametrii , și anume un indicator către bufferul pe care să realizeze verificarea, și lungimea acestuia.

În interiorul funcției apar trei inițializări, facute pentru a respecta procedura de calcul descrisă de către protocolul MAP27, deplasamentele având roul de a impune limitarea bufferului de intrare la antet și date, iar valoarea inițială a variabilei CRC fiind 0xffff. Variabila locală q este un indicator către o tabelă de valori ale CRC definită static în memoria de program (qq), prin intermediul căreia rezultă o valoare a CRC pentru pachetul curent.

Void RecSumCalc (unsigned char * buff, unsigned int len) reprezintă funcția de verificare la recepție care este realizată similar cu ChecksumCalc.

Implementarea a două funcții diferite de calcul a valorii CRC-ului a fost necesară datorită tratării diferite a emisiei și recepției.

În cazul emisiei calculez valoarea CRC modificând valorile de început și sfârșit a bufferului din care preiau informația de verificat, iar apoi adaug valoarea calculată octet cu octet la sfârșitul acestuia, cuvântul CRC fiind divizat în doi octeți numiți crcHi și crcLo.

În cazul recepției calculez valoarea preiau valorile crcHi și crcLo din pachetul recepționat în starea 6 și 7 din Rec_pkt_R, după care scot secvențele DLE și calculez propria valoare CRC.Diferența o face funcția de eliminare a DLE-urilor, care în implementarea abordată îmi elimină secventa de start SYN DLE STX și secvența de sfârșit DLE ETX, astfel putând sa aplic funcția de calcul, RecSumCalc, fără a mai fi nevoie să modific valorile de început și sfârșit pe care se aplică aceasta.

Tot pentru partea de recepție este definită funcția checkCRC care folosește RecSumCalc pentru a compara valoarea CRC recepționată cu cea calculată local, la nivel de octet.

5.9. Funcția de asigurare a transparenței datelor

Pentru asigurarea transparenței datelor de la nivelul 2 al protocolului MAP27 am implementat conform cu descrierea dată de acesta funcțiile putDLE și checkDLE.

Apelarea funcției putDLE este făcută doar în cadrul transmisiei, având ca intrare doi parametrii, primul constituindu-l o referință către primul octet din bufferul din care este preluată informația care urmează să fie pusă în bufferul de emisie al serialei asincrone ( bfemradio ), iar cel de-al doilea este lungimea în octeți pe care informația o ocupă.

În cadrul funcției sunt definite două variabile interne, I și j , cu ajutorul cărora sunt parcurse cele două buffere, ele jucând rol de index în interiorul buff , respectiv bfemcons. Primii trei octeți care reprezintă secvența de start a unui cadru de nivel legătură de date sunt copiați static, aceștia neavând nevoie de o verificare la nivel de transparență, la fel tratându-se și ultimii patru octeți care reprezintă secvența de sfârșit de cadru și CRC-ul.

În cazul antetului și a datelor, acestea sunt parcurse, verificându-se octet cu octet dacă apare o potrivire între valoarea lor și cea a secvenței de Data Link Escape ( 0x10). Dacă potrivirea există atunci în bufferul de emisie este scrisă de două ori valoarea 0x10 incrementându-se indexul j după fiecare scriere.

Astfel se asigură faptul că după fiecare DLE care apare în partea de informație este adăugat pe poziția imediat următoare un altul, ultimul menționat fiind scos la recepție.

La terminarea parcurgerii celor două buffere, lungimea informației din bufferul de emisie către stația radio este copiată într-o altă variabilă, aceasta fiind necesară în cadrul funcțiel decl_em_radio.

Pentru asigurarea transparenței datelor recepționate, am implementat funcția checkDLE. Această funcție are două roluri în cadrul funcționării legăturii de date care sunt prezentate în cele ce urmează.

Prima funcționalitate este posibilă deoarece checkDLE este apelată în starea 7 din cadrul funcției de testare a integrității pachetului, având asigurarea că secvențele de început și sfârșit sunt prezente și corecte. Acest lucru îmi permite să folosesc funcția pentru a elimina secvența SYN DLE STX și DLE ETX, având în vedere necesitatea acestei intervenții pentru calculul propriului CRC (pe antet și date) și compararea acestuia cu CRC-ul recepționat.

Cea de-a doua funcționalitate este cea de asigurare a transparenței datelor la recepție. Aceasta este realizată prin parcurgerea antetului și datelor la nivel de octet și testarea a două condiții de egalitate. Prima condiție testează egalitatea dintre octetul de pe poziția indexului curent și octetul DLE, iar ce-a de-a doua testează egalitatea dintre octetul de pe poziția octetului imediat următor și DLE. În cazul în care condiția compusă este îndeplinită doar primul octet este copiat în bufferul de recepție de pe interfața radio, BFpktR. La terminarea parcurgerii mesajului este menținută lungimea informației, aceasta fiind necesară pentru calculul CRC-ului.

5.10. Testarea pachetelor de nivel legătură de date la recepție

În urma testării pachetelor recepționate la nivel de integritate cu ajutorul funcțiilor prezentate mai sus ( Rec_pkt_R (5.6.2), RecSumCalc (5.7), checkCRC (5.7) și checkDLE (5.8) ) , este nevoie și de o testare a antetului fiecărui tip de pachet de nivel legătură de date.

După cum am spus și în cadrul părții teoretice (2.4.3, 2.4.4, 2.4.5), pentru legătura de date există trei tipuri de pachete care se pot transmite între stația radio și microcontroler. Funcția care face un test preliminar pentru a determina tipul pachetului recepționat de la stație este test_pkt_R. Primul lucru verificat în interiorul acesteia cu ajutorul funcției checkCRC, este faptul că valoarea CRC-ului recepționat corespunde cu valoarea CRC-ului calculat local.

În cazul în care valoarea returnată de testarea prin funcția checkCRC este 0, atunci pachetul este considerat eronat, și este neglijat.

În cazul în care valoarea returnată de către testarea checkCRC este 1, atunci urmează sa fie testate valorile din primul octet al antetului, care exprimă tipul de pachet. Fiecare pachet posibil la nivel legătură de date este tratat în continuare într-o funcție separată. În cazul unui pachet LR funcția apelată este testLR, în cazul LA funcția este testLA, iar în cazul unui LT este apelată funcția testLT.

5.10.1. Testarea antetului LR

Funcția de testare a cadrului de cerere legătură de date se numește testLR și este cea mai simplă dintre cele trei, din cauză că în cadrul pachetului LR nu apar variabile de stare sau de secvență. Din antetul pachetului este testat octetul 3 și 4 care reprezintă mărimea ferestrei de recepție respectiv versiunea de protocol folosită. În cazul în care condițiile puse pe acești octeți sunt îndeplinite este setat un flag (fl_LR), care indică faptul că am recepționat o cerere de legătură corectă. Cu ajutorul flagului fl_LR, pot trata mai departe funcționarea protocolului.

5.10.2. Testarea antetului LA

Confirmările recepționate la nivel legătură de date sunt tratate prin funcția testLA. Singurul test făcut în cadrul acestei funcții este asupra variabilei de secvență la emisie.

În cazul în care variabila varTX_seqNo este egală cu valoarea din octetul 2 al antetului de LA recepționat, am confirmarea că pachetele LT transmise, care fac variabila de secveță la recepție (varRX_seqNo) să se incrementeze au fost recepționate corect. Prelucrările ulterioare din interiorul testLA sunt setarea a două flaguri fl_LA și fl_LAgood și actualizarea creditului de transmisie TX_credNO. Flagul fl_LA indică recepția unui pachet de confirmare, iar fl_LAgood indică recepția unui pachet de confirmare corect din punct de vedere al variabilei de secvență la recepție, așteptată de emițător din partea receptorului.

În celălalt caz, în care variabila de secvență la recepție din octetul 2 al antetului LA este mai mică cu o unitate decât variabila de secvență la emisie locală, sunt setate flagurile fl_LA și fl_LTresend. Flagul fl_LTresend indică faptul că, confirmarea recepționată este un duplicat al celei anterioare și că ultimul pachet LT transmis trebuie retransmis.

5.10.3. Testarea antetului LT

Pachetele de transfer de date pe legătură sunt tratate de către funcția testLT, în cadrul căreia există trei posibilități de ramificare în funcție raportul dintre variabila de secvență la recepție locală și valoarea din octetul 2 al antetului de LT recepționat.

În cazul în care variabila de secvență așteptată este cea recepționată, variabilei de stare la recepție (RX_seqNo) îi este atribuită valoarea variabilei de secvență varRX_seqNo, iar aceasta din urmă este incrementată. Pentru a cunoaște faptul că am recepționat un pachet LT corect și pentru a trata mai departe acest lucru, este setat un flag fl_LT.

Dacă variabila de secvență recepționată este mai mică cu o unitate decât cea așteptată setez flagurile fl_LT și fl_LAresend. Combinația de flaguri fl_LT și fl_LAresend îmi indică faptul că am ultima confirmare transmisă nu a fost recepționată corect.

Dacă nici una dintre condițiile de mai sus nu este îndeplinită, înseamnă ca a avut loc o eroare a legăturii de date, iar în această situație setez flagurile fl_LT și fl_DLerr.

5.11. Construirea pachetelor de nivel legătură de date pentru emisie

Pentru a emite pachetele necesare stabilirii legăturii de date și pentru a putea menține această conexiune au fost necesare trei funcții de construire a celor trei tipuri de pachete. Aceste funcții se regăsesc în codul sursă sub denumirea sndLR , sndLA și sndLT. În implementarea construirii pachetelor am folosit câteva funcții prezentate în capitolele anterioare precum CheckSumCalc, putDLE sau decl_em_radio și trei buffere diferite numite bfLR, bfLA și bfLT.

5.11.1. Construirea pachetului LR

Cererea de legătură de date este implementată prin funcția sndLR. Bufferul bfLR din care se preia informația pentru construirea pachetului LR a fost definit static în cadrul memoriei externe de date. Pentru formarea cadrului complet al cererii de legătură este apelată funcția CheckSumCalc având ca parametrii un indicator către bfLR și lungimea acestuia. După calculul CRC-ului acesta este atașat lui bfLR pe în cadrul ultimilor doi octeți. Pentru asigurarea transparenței datelor este apelată funcția putDLE, care are și rolul de a muta pachetul în bufferul de emisire către stația radio, bfemradio. În urma acestor procesări este salvată lungimea pachetului LT în variabila lgemradio, ea fiind necesară pentru funcția decl_em_radio, care este apelată la finalul funcției sndLR.

5.11.2. Construirea pachetului LA

Confirmările transmise pe interfața serială bit-banging conectată la stația radio sunt construite în cadrul funcșiei sndLA. Bufferul bfLA din care se preia informația pentru a fi transmisă este și el definit static, pozițiile 4 și 5 din cadrul acestuia, care conțin variabila de secvență la recepție și creditul de recepție fiind suprascrise pentru fiecare nouă confirmare. După aceste procesări asupra bufferului este adăugată și valoare CRC în ultimii doi octeți, ea fiind calculată prin apelarea funcției CheckSumCalc. Ultimele două linii de cod din cadrul sndLA, apelează funcția putDLE care asigură transparența datelor, mută pachetul de confirmare din bfLA în bfemradio și salvează lungimea acestuia, lungimea fiind necesară funcției decl_em_radio din linia următoare.

5.11.3. Construirea pachetului LT

În tratarea pachetelor de transfer de date emise, datorită interfațării cu nivelul rețea, apar și câteva elemente care se regăsesc în cadrul acestuia. În cazul bufferului bfLT doar primele 7 poziții sunt definite static, acestea reprezentând secvența de început de cadru și antetul. De fiecare dată când este apelată funcția de construire a unui pachet LT, poziția 4 a bufferului, care semnifică valoarea variabilei de secvență la emisie este suprascrisă cu valoarea curentă. În următorii doi pași variabila de secvență la emisie este incrementată, iar variabila care menține valoarea creditului de emisie este decrementată.

În linia următoare apare variabila lenNL, care reprezintă lungimea informației primită de la nivelul rețea pentru a fi încapsulată intr-un cadru de nivel legătură de date. Pentru a cunoaște poziția din bufferul bfLT unde trebuie să se insereze secvența de sfârșit de cadru, acesteia I se adună valoarea 7 datorită deplasamentului dat de secvența de început și de antet.

După formarea cadrului start-stop pașii următori sunt similari celor urmați în interiorul funcțiilor sndLR și sndLA fiind apelate în ordinea scrierii funcțiile CheckSumCalc, putDLE și decl_em_radio.

Capitolul 6. Stările principale ale legăturii de date

Procedurile de stabilire a unei conexiuni de nivel legătură de date pot începe după alimentarea circutului IMC 5000 sau după o resetare a microcontroler-ului. Imediat după alimentare sau resetare fiecare entitate trebuie să fie pregătită să recepționeze și să interpreteze un pachet de nivel legătură de date în scopul de a ajunge în faza de transfer de date.

Ordinea în care trebuiesc parcurse stările de către o entitate de protocol MAP27 pentru a ajunge în faza de transfer de date este următoarea : starea Reset Wait starea Link Wait starea Ready (figura 6.1)

Fig. 6.1 Diagrama de stări și tranziții a legăturii de date

Pentru a realiza o prefață pentru ceea ce urmează a fi prezentat, putem spune că rolurile principale pe care le au stările de mai sus sunt :

– starea Reset_Wait – negocierea parametrilor pentru conexiunea de nivel legătură de date; – starea Link_Wait – acceptarea parametrilor între entități prin confirmări de nivel legătură de date ;

– starea State_Ready – transferul de date împreună cu menținerea conexiunii.

6.1. Starile Reset Wait și Link Wait

Starea inițială în care se află legătura de date după execuția codului sursă este starea de așteptare a resetării legăturii (RESET_WAIT) (figura 6.2). Modalitățile în care se poate ajunge în această stare sunt alimentarea circuitului, resetarea hardware a microcontrolerului, prin tranziția din starea LINK_WAIT din cauza recepției unui pachet neașteptat, prin tranziția din starea STATE_READY datorită valorii 0 în care ajunge numărătorul C1 în cazul în care după 10 încercări de stabilire a legăturii toate eșuează, sau din cauza unui reset primit de la nivelul rețea.

Fig. 6.2 Diagrama de funcționare a stării RESET_WAIT

Atât în exteriorul (la inițializare) cât și în interiorul acestei stări este setat flagul fl_RW pentru a cunoaște starea în care se află programul, iar în cele ce urmează se fac patru testări asupra a patru variabile.

Primul test este legat de flagul NL_reset , care dacă este setat indică faptul că s-a recepționat de la nivelul aplicație o cerere de resetare a legăturii de date. În cazul în care condiția este îndeplinită, aceasta este tratată prin resetarea flagului și prin apelarea funcției RESET_PON. În interiorul RESET_PON sunt apelate consecutiv funcțile STOP_T1, STOP_T3, STOP_T4, SND_LR și START_T0 urmate de o linie de cod în care programul se întoarce la instrucțiunea de după apelarea RESET_PON și mai departe în funcția main.

Al doilea test este făcut pe baza a două flaguri fl_LR și fl_PON, cel din urmă fiind setat în la inițializare și reprezentând prezența alimentării. Dacă nu s-a recepționat pachet de LR, iar flagul fl_PON este setat, condiția este îndeplinită, tratarea este aceeași cu cea prezentată mai sus, singura diferență fiind făcută de resetarea flagului fl_PON după întoarcerea din funcția RESET_PON.

Dacă intrarea în starea RESET_WAIT este făcută având flagul fl_LR setat, este îndeplinită cea de-a 3-a condiție. În această situație tratarea se face prin resetarea fl_LR , apelarea funcțiilor sndLR și START_T0, iar în continuare se resetează flagul stării reset wait și se setează flagul fl_LW, care indică intrarea în starea LINK_WAIT.

În ultima condiție sunt testate posibilele erori datorate recepției unor pachete de nivel legătură de date neașteptate în această stare ( în cazul în care este setat flagul fl_LA de recepție al unui pachet LA sau este setat flagul fl_LT al unui pachet LT ) sau expirării timerului ctmT0. Dacă oricare din aceste posibilități este îndeplinită, flagurile fl_LA, fl_LT și timerul ctmT0 sunt resetate și se reîncearcă stabilirea conexiunii prin emiterea unui pachet LR.

După parcurgerea stării RESET_WAIT programul se întoarce în bucla principală, unde datorită flagurilor (care sunt implmentate asemănator unui concept de semafor ) corespunzătoare fiecărei stări (fl_RW, fl_LW și fl_READY) acesta poate accesa doar una dintre ele la fiecare parcurgere.

În cazul în care negocierea parametrilor a eșuat, flagul fl_RW rămâne setat și astfel programul parcurge din nou starea RESET_WAIT, iar între entități sunt vehiculate din nou mesaje de cerere de legătură. Pentru stabilirea conexiuni este utilizat timerul dinamic T0, acesta pornind de la 100 de milisecunde și incrementându-se la fiecare retransmisie cu alte 100 de milisecunde.

În urma transmiteri mesajelor de cerere legătură de date din starea RESET_WAIT și negocierea cu succes a parametrilor propuși de una din cele două entități se comută prin cele două flaguri care indică starea activă (fl_RW și fl_LW) din starea de așteptare a resetării legăturii în starea de așteptare a confirmării legăturii (LINK_WAIT).

Pentru a avea și un exemplu vizual, în care se poate înțelege mai ușor schimbul de mesaje, acesta este prezentat în subcapitolul 2.5.

În cadrul stări LINK_WAIT (figura 6.3) există trei condiții bazate pe flaguri ale pachetelor recepționate. Pachetele care sunt așteptate pentru a fi recepționate în starea LW sunt de cerere legătură pentru confirmarea acceptări parametrilor într-o negociere în 3 pași, sau de confirmare legătură dacă schimbul de pachete necesare negocierii au fost deja emise și recepționate.

Fig. 6.3 Diagrama de funcționare a stării LINK_WAIT

În cadrul acestei stări există trei condiții bazate pe flaguri ale pachetelor recepționate. Pachetele care sunt așteptate pentru a fi recepționate în starea LW sunt de cerere legătură pentru confirmarea acceptări parametrilor într-o negociere în 3 pași, sau de confirmare legătură dacă schimbul de pachete necesare negocierii au fost deja emise și recepționate. Pentru a avea și un exemplu vizual, în care se poate înțelege mai ușor schimbul de mesaje, acesta este prezentat în subcapitolul 3.5.

Dacă se recepționează un pachet LR, iar acesta are parametrii așteptați, atunci este setat flagul fl_LR care este testat în prima condiție din interiorul stării LW. În continuare, după îndeplinirea primei condiții flagul fl_LR este resetat, se emite un mesaj de confirmare, se dezactivează timerele de retransmisie (T0), se activează timerele de decție a eșecului realizării legăturii (T4) și de activitate (T3) și se comută starea activă pe STATE_READY. (fl_READY=1)

Dacă se recepționează un pachet LA având variabila de secvență așteptată, este setat flagul fl_LA fiind îndeplinită cea de-a doua condiție. Valoarea 1 a acestui flag în cadrul stării LW reprezintă confirmarea legăturii din partea entității cu care se comunică. În continuare se resetează flagul fl_LA, se oprește timerul de retransmisie, iar pentru a ajunge în faza de transfer de date, este emis un pachet LA către cealaltă entitate. După emisia acestuia se activează timerul de activitate pe legătura de date (T3), se resetează timerul de detecție a eșecului legăturii (T4) și se comută flagul de stare activă pe STATE_READY (fl_READY=1).

Există și o a 3-a condiție în care dacă timerul de retransmisie expiră (sutT0=0) sau se recepționează un pachet de transfer de date pe legătură (fl_LT=1), aceasta nefiind încă stabilită, se efectuează o tranziție din starea LINK_WAIT în starea RESET_WAIT.

6.2. Starea Ready

Pentru a putea avea o imagine mai bună asupra stării READY care este cea mai complexă dintre cele trei, am încercat o împărțire și o tratare a acesteia pe blocuri, în funcțiile de condițiile care sunt prezente în interiorul acesteia.

Primul bloc din cadrul stării STATE_READY este cel de emisie a datelor primite de la nivelul rețea. În cazul primirii unui pachet de la nivelul superior pentru a fi încapsulat la nivel legătură de date este setat flagul testat în prima condiție ( fl_NLP ). În interiorul acestei condiții există toate procedurile de transmitere a unui pachet de nivel rețea încapsulat în formatul cadrului LT. La început se testează dacă exista credit pentru a transmite mesajul din buffer. Dacă există atunci pachetul este acceptat și transmis, în continuare fiind activate mecanismele de detecție a erorilor, care sunt reprezentate de timerul 1 (timer de retransmisie în faza de transfer de date) și număratorul C1 ( numărul de reîncercări de transmisie fără succes).Dacă nu există credit, este setat flagul fl_Prej pentru a semnala nivelului rețea că pachetul nu a putut fi transmis.

Timerul T1 care declanșează retransmisia este oprit (fl_T1=0) doar în cazul în care este recepționat un pachet de confirmare pentru pachetul LT care se încearcă a fi transferat.Altfel, dacă sutT1 nu a ajuns la 0 și fl_T1 este setat (ceea ce semnalează că T1 este activ) și încă nu s-a primit o confirmare asupra pachetului LT transmis, numărătorul C1 este decrementat (el fiind inițializat cu 10). Până când C1 ajunge la 0 se încearcă retransmisia pachetului LT, iar când acesta ajunge la 0, timerele T3 și T4 sunt oprite și se resetează legătura făcându-se o tranziție din READY în RESET_WAIT.

Al 2-lea bloc este referitor la tratarea recepției unei confirmări de nivel legătură de date în starea STATE_READY. În cazul recepției unui LA , flagul este resetat, timerul de monitorizare a activității pe legătură (T4) este resetat și se actualizează creditul.

Dacă este setat și flagul fl_Lagood (care îmi indică faptul ca LA-ul primit este cel așteptat) atunci resetez fl_Lagood, opresc timerul de reîncercare transmisie LT și setez din nou numărătorul C1 la valoarea 10. Pentru tratarea unui LA duplicat, o sa fie setat flagul fl_LTresend ceea ce mă obligă sa transmit încă o dată pachetul LT și sa decrementez C1. Până când C1 ajunge la 0 se încearcă retransmisia pachetului LT, iar când acesta ajunge la 0, timerele T3 și T4 sunt oprite și se resetează legătura făcându-se o tranziție din READY în RESET_WAIT.

Blocul 3 tratează recepția unui mesaj de cerere legătură, atunci când legătura este deja stabilită. Acesta este fie un mesaj care s-a eronat în timpul propagării, fie o desincronizare sau resetare a entității de la celălalt capăt, care este tratat printr-o tranziție din starea STATE_READY în starea de LINK_WAIT,

Blocul 4 se ocupă de resetarea nivelului legătură de date din nivelul aplicație, care induce o tranziție direct în starea de RESET_WAIT fiind realizate toate inițializările necesare acesteia (oprire timere, setare fl_RW, resetare fl_READY )

Următoarea condiție se ocupă de recepția pachetelor de transfer de date pe legătura de date. Dacă flagul fl_LT este setat în starea READY, se trece la recepția propriu zisă a datelor, în cazul în care nu există erori. Erorile care pot apărea în acest caz sunt : nesincronizarea variabilelor de secvență care conduce la o eroare de nivel legătură de date ce nu poate fi rezolvată decât prin resetarea legăturii sau eronarea ultimului LA transmis ( LT-ul recepționat este același cu ultimul pentru care s-a trimis confirmare) , care se poate rezolva prin retransmiterea ultimului LA.

Dacă nu apare nici una din erorile discutate mai sus, atunci din cadrul LT este decapsulat pachetul de nivel rețea , care este considerat payload din punct de vedere al legăturii de date. Pachetul de nivel rețea este introdus în bufferul de bfrecNL setându-se flagul fl_recNL, în continuare urmând ca acesta să fie preluat și prelucrat de către nivelul superior.

Imediat după pasarea datelor din pachetul LT către nivelul superior este transmisă și o confirmare de nivel legătură de date pentru acest pachet, aceasta resetând timerul T3 al celeilalte entități. Local, timerul T3 este resetat prin apelarea funcției START_T3.

Ultima parte din starea STATE_READY testează expirarea timerului T3 și a timerului T4. Testarea variabilei secT3 este partea stării READY care are rolul de a menține legătura de date stabilă în cazul în care pe aceasta nu se transmit pachete de date, trimițând periodic pachete de confirmare.

Testarea variabilei secT4 și a flagului fl_T4 este făcută la sfârsitul stării READY, la expirarea timerului T4 fiind resetată legătura de date printr-o tranziție din READY în RESET_WAIT.

Pentru o mai bună înțelegere a proceselor ce iau parte în cadrul stării STATE_READY se pot urmări diagramele de funcționare prezentate în figura 6.4 și 6.5.

Fig. 6.4 Diagrama de funcționare a stării STATE_READY (partea 1)

Fig. 6.5 Diagrama de funcționare a stării STATE_READY (partea 2)

6.3. Observații experimentale

În figurile 6.6 și 6.7 este prezentat schimbul de mesaje între microcontroler-ul 80C552 și stația radio Motorola GM1200 utilizând programul monitor, hiperterminalul TeraTerm și o funcție de depanare cvchar folosită pentru afișarea mesajului în format ASCII.

În aceste figuri se poate observa funcționarea a aproape toate mecanismele descrise de protocolul MAP27 pentru nivelul legătură de date.În cadrul imaginilor prezentate. "E:" simbolizează emisia unui mesaj de la microcontroler către stație, iar "R:" simbolizează recepția unui mesaj de la stația radio de către microcontroler.

Fig. 6.6 Schimb de mesaje de nivel legătură de date și emisia unui SST.

Stabilirea legăturii are loc în 5 pași (primele 5 linii care urmează după rularea codului sursă cu comanda g8000). Primii 3 pași sunt cei de stabilire a parametrilor pentru legătura de date, iar următorii 2 reprezintă confirmarea pentru stabilirea acesteia.În urma stabilirii acesteia este emis un mesaj de nivel rețea și un altul recepționat, în urma acestora putându-se observa incrementarea variabilei de secvență din cadrul confirmărilor. În ultimele linii din cele două figuri schimbul de mesaje este unul repetitiv, aceste fiind transmise și recepționate în mod continuu la intervale de timp pentru a menține legătura de date stabilită, în cazul în care nu se transmit mesaje de date sau recepționează mesaje de transfer de date.

În figura 6.7 este prezentat un schimb de mesaje de nivel legătură în care apare o eroare a unui mesaj de cerere legătură recepționat de la stație ( linia , sub execuția programului cu comanda g8000). Tot aici se poate observa și faptul că pachetul eronat este neglijat, legătura stabilindu-se în condiții normale în următorii 5 pași de după eroare.

Fig. 6.7 Schimb de mesaje de nivel legătură de date și apariția unei erori pe recepție

Capitolul 7. Implementarea software a regimurilor de lucru

Pentru a putea accesa cu ușurință o aplicație care include comunicație capăt la capăt și pentru a nu fi nevoie de cunoștinte de funcționare a protocoalelor implementate în cadrul echipamentelor utilizate, este nevoie de o interfață simplă și intuitivă între utilizator și sistem.

În interfața implementată (figura 7.1), regimurile de lucru pentru demonstrarea capabilităților platformei sunt afișate succesiv pe ecran folosind hiperterminalul TeraTerm, prezentat în capitolul 4.

Fig. 7.1 Interfața cu utilizatorul

După cum se poate observa și în cadrul figurii 8.1,în urma execuției codului sursă,pe prima linie este afișat un mesaj de întâmpinare, care prezintă denumirea sistemului folosit și scopul pentru care acesta este realizat. Pe linia imediat următoare, este afișat un mesaj prin care utilizatorul este rugat să astepte pentru a putea utiliza sistemul, acesta fiind în faza de stabilire a legăturii de date.

Liniile 3, 4 și 5 sunt dedicate utilizatorului acesta fiind îndrumat în ce mod poate folosi resursele puse la dispoziție de către sistem. Cele 3 opțiuni sunt conforme cu implementarea realizată la nivel rețea și descrisă în protocolul MAP27. Selectând prima opțiune se poate transfera un mesaj de dimensiunea unui octet, acesta fiind denumit mesajul de STATUS. Selectând a 2-a opțiune se poate transfera un mesaj scurt de date (SST)format din maxim 23 de caractere ASCII, introdus de la tastatură de către utilizator. În cadrul celei de-a 3-a opțiuni este inițiat un apel de voce (VOICE CALL) către stația corespondentă, care poate fi încheiat de către ambii participanți la apelul în desfășurare.

În urma selecției de către utilizator a regimului de lucru dorit și a introducerii datelor ce se doresc a fi transmise (dacă este cazul), acesta este înștiințat dacă tranzacția dorită a avut loc cu succes sau a eșuat.

Pentru implementarea acestei interfețe care arată capabilitățile sistemului am colaborat cu Dl. Nadir Calil, fiind necesare cunoștințe ale implementării nivelului rețea.

Concluzii

Acest proiect a avut ca scopuri implementarea nivelului legătură de date a protocolului MAP27 pentru comunicații conforme standardului MPT1327 și implementarea regimurilor de lucru pentru interfața cu utilizatorul.

Pe durata desfășurării proiectului am întâmpinat dificultăți în partea de depanare a codului sursă, dar și probleme hardware, fiind necesară schibarea cristalului de cuartz de la cel de 11,059MHz la unul de 20MHz pentru a mări viteza de procesare a microcontrolerului. Acceastă modificare a fost benefică, prin schibarea ceasului sistemului servirea întreruperilor devenind mai puțin consumatoare de timp.

Alte dificultăți de menționat ar fi realizarea unei comunicații fiabile cu stația radio, care să poată acoperi toate cazurile de conexiune între aceasta și microcontroler. Pentru a rezolva problemele legate de logica de execuție am inclus în funcțiile ce trebuiau parcurse, utilizând bufferul S0BUF, caractere afișabile care să ajute la depanarea mai ușoară a codului.

Trecând peste aceste dificultăți scopurile propuse au fost atinse atât din punct de vedere teoretic cât și practic, implementarea fiind testată pe baza unui sistem asemănător celui prezentat în figura 6.1 format din două PC-uri, două plăci de dezvoltare IMC500 cu microcontroler 80C552, două stații radio Motorola GM1200 și o stație de bază compatibilă MPT1327.

Bibliografie

1. http://www.ofcom.org.uk/static/archive/ra/publication/mpt/mpt_pdf/mpt1327.pdf – Protocolul MAP27.

2. http://www.mpt1327-usa.org/downloads/map27.pdf – Standardul MPT1327.

3. ***: Phillips Semiconductors, 8051 family derivates,1996.

4. ***: Phillips Semiconductors, DATA SHEET 80C552/83C552, 2002.

5. http://www.8052.com/book – informații legate de familia 8051

6. ***: Keil Elektronik GmbH., and Keil Software, Inc. , C51 Compiler, 1997.

7. ***: Keil Elektronik GmbH and Keil Software, Inc. , 8051/251 Evaluation kit, 1998.

8. ***: Costin Ștefănescu , Nicolae Cupcea , Electronică aplicată – Sisteme inteligente hardware – Software de măsurare și control , București 2003.

9. ***: Mazilu Alexandru, Calil Nadir, Coordonatori Științifici V.Croitoru , T.Voica, Modem radio FSK pentru comunicații de tip MPT1327, cu implementarea protocolului MAP27, Sesiunea de Comunicări Științifice,București,2014.

10. http://www.hobbyprojects.com/8051_tutorial/special_function_registers.html – explicații legate de registrele SFR

11. ***: Temic Semiconductors, C51 Family, 1997.

12. ***: Phillips Semiconductors, 80C51 programmer's guide and instruction set,1997.

Anexă – codul sursă

#pragma SYMBOLS

#pragma CODE

#pragma DEBUG

#pragma LARGE

#include <stdio.h>

#include <ctype.h>

#include <string.h>

#include <stdlib.h>

#include <math.h>

#include <porturi.h>

#include "reg552.h"

#define TERM 0x0d

#define ML 0x0b

#define WS 0x01

#define VER 0x01

#define SYN 0x16

#define DLE 0x10

#define STX 0x02

#define ETX 0x03

#define LR 0x01

#define NUL 0x00

#define N2 0x0A

#define N3 0x02

#define LA 0x02

#define LT 0x04

#define N1 0x0A

#define STATUS 0x80

#define ACKP 0xC0

#define ACKN 0xE0

#define SST 0x81

#define MDM 0xA4

#define PROGP 0xC4

#define PROGN 0xE4

#define RPROGP 0xC5

#define RPROGN 0xE5

#define MDMDATA 0xA3

#define GDISC 0x86

#define FDISC 0xA6

#define RC 0xb2

#define RM 0xb3

#define IDLE 0xAA

#define OUTCW 0xBB

#define ACTIVE 0xCC

#define INCCW 0xDD

#define STATW 0xEE

#define SEGTRANSW 0xFF

extern bit endemr, fRecOctRd;

extern data char R0_2, R1_2, R2_2, R3_2, R4_2, R5_2, R6_2, R7_2, bfOctRcSt;

extern code initasm();

extern code armezCM1();

extern code sdebug();

void cons_ser(void);

void decl_em_cons(void);

void cvchar(unsigned char, unsigned char *);

void init_var(void);

void init_resurse(void);

void decl_em_radio(unsigned char);

void em_radio(void);

void contor(void);

void CheckSumCalc (unsigned char * buff, unsigned int len);

void pkt(void);

void REC_pkt_R(void);

void test_pkt_C(void);

void test_pkt_R(void);

void SND_LR(void);

void SND_LA(void);

void SND_LR(void);

void START_T0(void);

void STOP_T0(void);

void START_T1(void);

void STOP_T1(void);

void START_T3(void);

void STOP_T3(void);

void START_T4(void);

void STOP_T4(void);

void initialise_variables(void);

void record_send_credit(void);

void rewind_packet_no(void);

void setC1(void);

void decC1(void);

void START_Tpack(void);

void checkDLE(void);

void getoct(void);

void putDLE(unsigned char *buff, int lungime);

int checkCRC(void);

void testLR(void);

void testLA(void);

void testLT(void);

void RESET_WAIT(void);

void RESET_PON(void);

void LINK_WAIT(void);

void STATE_READY(void);

void NetLayer(void);

void makeNLpkt( unsigned char msgtip,unsigned char len);

void test_pktNL(void);

void START_T5(void);

void meniu(void);

bit flag_rec_cons,fl_emcons,flag_start_rec;

bit fl_pkt_rec ,fl_pkt_R,fl_AR, fl_LR, fl_LA, fl_LT, fl_RW,fl_LW;

bit fl_READY,fl_PON,NL_reset, chix, fpkt_err, flzec,fl_NLP, fl_Prej ,fl_Acc;

bit fl_LTresend,fl_DLerr,fl_LAresend,fl_LAgood,fl_T0, fl_T1,fl_T3, fl_T4, fl_recNL;

bit fl_hook,fl_treq,fl_sst,fl_mdm,fl_rctrl,fl_mgmt,fl_recsst, fl_recmdm, fl_RPROGP;

bit fl_PROGP,fl_PROGN,fl_DISCON,fl_RPROGN,fl_FDISC, fl_GDISC, fl_ACKP,fl_ACKN,fl_DLRESET,fl_sts;

bit fl_b,fl_p,fl_case,fl_sstp,fl_sstb,fl_callb,fl_callp,fl_recsts, fl_icall,fl_gdsc,fl_rsst;

data char idx_em_cons, idx_rec_cons, lgreccons,idx_R,secT5,sts ,stsmsg;

data char idx_emchar_radio, lgrecradio,idx_rec_radio,i,j,index;

data unsigned char bfemr,bfrecr, bftempr,varRX_seqNo,RX_seqNo,RX_credNo,TX_seqNo,TX_credNo,varTX_seqNo,RX_acked,C1,crcHi,crcLo;

data unsigned char stare,stRX_cred,lgemradio,lenNL,stateNL,afis,lgrecNL;

data unsigned char zecimi,sutimi,miimi, secunde,idx_pc,idx_pr,sutT1,secT3,secT4,miiToct,idx_retT0;

data unsigned char PFIX1,PFIX2,IDENT1a,IDENT1b,IDENT2a,IDENT2b,ADESC,LENGTH,NLB,ADDRESS;

data unsigned int CRC,RCRC, lmesrec, ctTm0;

xdata unsigned char bfLR[12]={SYN,DLE,STX,LR,N1,WS,VER,DLE,ETX};

xdata unsigned char bfLA[12]={SYN,DLE,STX,LA,ML,WS,NUL,DLE,ETX};

xdata unsigned char bfemcons[120], bfreccons[80], bfemradio[100],BFpktR[50], bfrecradio[100];

xdata unsigned char bfrecNL[100],bfLT[40]={SYN,DLE,STX,LT,0x00,0x01,0x00}, bfemNL[50],payload[30],recload[30];

code unsigned int mtab [] =

{

0x0000, 0xC1C0, 0x81C1, 0x4001, 0x01C3, 0xC003, 0x8002, 0x41C2, 0x01C6, 0xC006, 0x8007, 0x41C7, 0x0005, 0xC1C5, 0x81C4, 0x4004,

0x01CC, 0xC00C, 0x800D, 0x41CD, 0x000F, 0xC1CF, 0x81CE, 0x400E, 0x000A, 0xC1CA, 0x81CB, 0x400B, 0x01C9, 0xC009, 0x8008, 0x41C8,

0x01D8, 0xC018, 0x8019, 0x41D9, 0x001B, 0xC1DB, 0x81DA, 0x401A, 0x001E, 0xC1DE, 0x81DF, 0x401F, 0x01DD, 0xC01D, 0x801C, 0x41DC,

0x0014, 0xC1D4, 0x81D5, 0x4015, 0x01D7, 0xC017, 0x8016, 0x41D6, 0x01D2, 0xC012, 0x8013, 0x41D3, 0x0011, 0xC1D1, 0x81D0, 0x4010,

0x01F0, 0xC030, 0x8031, 0x41F1, 0x0033, 0xC1F3, 0x81F2, 0x4032, 0x0036, 0xC1F6, 0x81F7, 0x4037, 0x01F5, 0xC035, 0x8034, 0x41F4,

0x003C, 0xC1FC, 0x81FD, 0x403D, 0x01FF, 0xC03F, 0x803E, 0x41FE, 0x01FA, 0xC03A, 0x803B, 0x41FB, 0x0039, 0xC1F9, 0x81F8, 0x4038,

0x0028, 0xC1E8, 0x81E9, 0x4029, 0x01EB, 0xC02B, 0x802A, 0x41EA, 0x01EE, 0xC02E, 0x802F, 0x41EF, 0x002D, 0xC1ED, 0x81EC, 0x402C,

0x01E4, 0xC024, 0x8025, 0x41E5, 0x0027, 0xC1E7, 0x81E6, 0x4026, 0x0022, 0xC1E2, 0x81E3, 0x4023, 0x01E1, 0xC021, 0x8020, 0x41E0,

0x01A0, 0xC060, 0x8061, 0x41A1, 0x0063, 0xC1A3, 0x81A2, 0x4062, 0x0066, 0xC1A6, 0x81A7, 0x4067, 0x01A5, 0xC065, 0x8064, 0x41A4,

0x006C, 0xC1AC, 0x81AD, 0x406D, 0x01AF, 0xC06F, 0x806E, 0x41AE, 0x01AA, 0xC06A, 0x806B, 0x41AB, 0x0069, 0xC1A9, 0x81A8, 0x4068,

0x0078, 0xC1B8, 0x81B9, 0x4079, 0x01BB, 0xC07B, 0x807A, 0x41BA, 0x01BE, 0xC07E, 0x807F, 0x41BF, 0x007D, 0xC1BD, 0x81BC, 0x407C,

0x01B4, 0xC074, 0x8075, 0x41B5, 0x0077, 0xC1B7, 0x81B6, 0x4076, 0x0072, 0xC1B2, 0x81B3, 0x4073, 0x01B1, 0xC071, 0x8070, 0x41B0,

0x0050, 0xC190, 0x8191, 0x4051, 0x0193, 0xC053, 0x8052, 0x4192, 0x0196, 0xC056, 0x8057, 0x4197, 0x0055, 0xC195, 0x8194, 0x4054,

0x019C, 0xC05C, 0x805D, 0x419D, 0x005F, 0xC19F, 0x819E, 0x405E, 0x005A, 0xC19A, 0x819B, 0x405B, 0x0199, 0xC059, 0x8058, 0x4198,

0x0188, 0xC048, 0x8049, 0x4189, 0x004B, 0xC18B, 0x818A, 0x404A, 0x004E, 0xC18E, 0x818F, 0x404F, 0x018D, 0xC04D, 0x804C, 0x418C,

0x0044, 0xC184, 0x8185, 0x4045, 0x0187, 0xC047, 0x8046, 0x4186, 0x0182, 0xC042, 0x8043, 0x4183, 0x0041, 0xC181, 0x8180, 0x4040,

};

void init_resurse(void)

{

PCON|=0x80;

S0CON=0x50;

TMOD=0x21;

TCON=0x50;

TH1=0xF5;

PT0=0;

PS0=0;

PCM0=1;

PCM1=1;

PCT0=1;

ET0=1;

ET2=0;

ECM1=0;

ES0=1;

EA=1;

initasm();

}

void init_var(void)

{

idx_rec_radio=8;

idx_rec_cons=0;

flag_rec_cons=0;

fl_emcons=0;

idx_emchar_radio=0;

fl_pkt_rec=0;

NL_reset=0;

RX_seqNo=1;

miimi=10;

flzec = 0;

secunde=60;

sutimi=10;

zecimi=10;

stare=1;

idx_pc=0;

sutT1=0;

ctTm0=1;

secT3=0;

secT4=0;

i=0;

j=0;

fl_AR=0;

fl_pkt_R=0;

index=0;

crcHi=0;

crcLo=0;

fl_LR=0;

fl_LA=0;

fl_LT=0;

idx_R=0;

idx_retT0=3;

miimi= 10;

idx_pc=0;

idx_pr=0;

lmesrec=0;

fl_NLP=0;

fl_Prej=0;

fl_Acc=0;

stRX_cred=0;

fl_LTresend=0;

fl_DLerr=0;

fl_LAresend=0;

fl_LAgood=0;

fl_LAresend=0;

fl_T0=0;

fl_T1=0;

fl_T3=0;

fl_T4=0;

varTX_seqNo=1;

fl_recNL=0;

lenNL=0;

stateNL=IDLE;

fl_hook=1;

fl_treq=0;

fl_rctrl=0;

fl_mgmt=0;

fl_sst=0;

fl_mdm=0;

fl_recsst=0;

fl_recmdm=0;

fl_RPROGP=0;

fl_PROGP=0;

fl_PROGN=0;

fl_DISCON=0;

fl_RPROGN=0;

fl_FDISC=0;

fl_GDISC=0;

fl_ACKP=0;

fl_ACKN=0;

fl_DLRESET=0;

fl_sts=0;

PFIX1=11;

PFIX2=11;

IDENT1a=24;

IDENT1b=196;

IDENT2a=24;

IDENT2b=197;

stsmsg=20;

fl_case=0;

afis=0;

fl_b=0;

fl_p=0;

lgrecNL=0;

fl_sstb=0;

fl_sstp=0;

fl_callb=0;

fl_callp=0;

fl_recsts=0;

fl_icall=0;

fl_gdsc=0;

fl_rsst=0;

}

void decl_em_cons(void)

{

idx_em_cons=1;

fl_emcons=1;

S0BUF=bfemcons[0];

}

void cons_ser(void) interrupt 4 using 1

{

if(TI)

{

TI=0;

if(bfemcons[idx_em_cons])

{

S0BUF=bfemcons[idx_em_cons++];

}

else fl_emcons=0;

}

if (RI)

{

RI=0;

if((bfreccons[idx_rec_cons++]=S0BUF)==TERM)

{

flag_rec_cons=1;

lgreccons=idx_rec_cons;

idx_rec_cons=0;

fl_case=1;

ECT0=1;

}

}

}

void contor(void) interrupt 1 using 3

{

TL0=0x7d;

TH0=0xf9;

miimi–;

if(miiToct)

{

miiToct–;

}

if(!miimi)

{

miimi=10;

sutimi–;

if(ctTm0)

{

ctTm0–;

}

}

if(!sutimi)

{

sutimi=10;

flzec=1;

}

}

void timp()

{

if(flzec)

{

flzec=0;

zecimi–;

if(!zecimi)

{

zecimi=10;

secunde–;

if(secT3)

{

secT3–;

}

if(secT4)

{

secT4–;

}

if(!secunde)

{

secunde=60;

}

}

}

}

void cvchar(unsigned char cint, unsigned char * bem)

{

unsigned char b;

b = (cint>>4)&0x0f;

if(b<0x0A) b+=0x30;

else b+=0x37;

*bem = b;

bem++;

b = cint&0x0f;

if(b<0x0A) b+=0x30;

else b+=0x37;

*bem = b;

bem++;

*bem = ' ';

}

void decl_em_radio(unsigned char lgem1)

{

ECT0=0;

idx_emchar_radio=0;

endemr=1;

while(idx_emchar_radio<lgem1)

{

if(endemr)

{

endemr=0;

R3_2=bfemradio[idx_emchar_radio++];

P4_0=0;

armezCM1();

}

}

ECT0=1;

}

void START_Tpack()

{

miiToct=20;

}

void START_T0()

{

ctTm0=idx_retT0*10;

if (idx_retT0>150)

{

idx_retT0=1;

}

idx_retT0++;

fl_T0=1;

}

void STOP_T0()

{

idx_retT0=3;

ctTm0=1;

fl_T0=0;

}

void START_T1()

{

sutT1=50;

fl_T1=1;

}

void STOP_T1()

{

sutT1=0;

fl_T1=0;

}

void START_T3()

{

secT3=6;

fl_T3=1;

}

void STOP_T3()

{

secT3=0;

fl_T3=0;

}

void START_T4()

{

secT4=20;

fl_T4=1;

}

void STOP_T4()

{

secT4=0;

fl_T4=0;

}

void START_T5()

{

secT5=10;

}

void SND_LR()

{

CheckSumCalc((unsigned char*)bfLR,9);

bfLR[10]=(unsigned char)CRC;

bfLR[9]=(unsigned char)(CRC>>8);

putDLE((unsigned char *)bfLR,11);

lgemradio = 11;

decl_em_radio(lgemradio);

return;

}

void SND_LA()

{

bfLA[4]=varRX_seqNo;

bfLA[5]=RX_credNo;

CheckSumCalc((unsigned char*)bfLA,9);

bfLA[10]=(unsigned char)CRC;

bfLA[9]=(unsigned char)(CRC>>8);

putDLE((unsigned char *)bfLA,11);

decl_em_radio(lgemradio);

}

void SND_LT()

{

bfLT[4]=varTX_seqNo;

TX_seqNo=varTX_seqNo;

varTX_seqNo++;

TX_credNo–;

lenNL+=7;

bfLT[lenNL++]=DLE;

bfLT[lenNL++]=ETX;

CheckSumCalc((unsigned char *)bfLT,lenNL);

bfLT[lenNL+1]=(unsigned char)CRC;

bfLT[lenNL]=(unsigned char)(CRC>>8);

putDLE((unsigned char *)bfLT,lenNL+2);

decl_em_radio(lgemradio);

}

void putDLE(unsigned char *buff, int lungime)

{

char i,j;

bfemradio[0]=buff[0];

bfemradio[1]=buff[1];

bfemradio[2]=buff[2];

j=3;

for(i=3;i<lungime-4;i++)

{

if(buff[i]==DLE)

{

bfemradio[j++]=DLE;

bfemradio[j++]=DLE;

}

else

{

bfemradio[j++]=buff[i];

}

}

for(;i<lungime;i++)

{

bfemradio[j++]=buff[i];

}

lgemradio=j;

}

void CheckSumCalc (unsigned char * buff, unsigned int len)

{

unsigned int q;

buff+=3;

len-=3;

CRC = 0xffff;

while (len–)

{

q = * (mtab + (* buff++ ^(CRC >> 8)));

CRC = ((q & 0xff00) ^ (CRC << 8)) | (q & 0x00ff);

}

CRC = CRC^0xffff;

return;

}

void RecSumCalc (unsigned char * buff, unsigned int len)

{

unsigned int q;

RCRC = 0xffff;

while (len–)

{

q = * (mtab + (* buff++ ^(RCRC >> 8)));

RCRC = ((q & 0xff00) ^ (RCRC << 8)) | (q & 0x00ff);

}

RCRC = RCRC^0xffff;

return;

}

void test_pkt_R()

{

timp();

if(checkCRC())

{

if(BFpktR[0]==LR) testLR();

else if(BFpktR[0]==LA) testLA();

else if(BFpktR[0]==LT) testLT();

}

return;

}

void testLR()

{

if(BFpktR[2]==WS&&BFpktR[3]==VER )

{

fl_LR=1;

}

return;

}

void testLA()

{

if(BFpktR[1]==varTX_seqNo)

{

fl_LA=1;

fl_LAgood=1;

TX_credNo=BFpktR[2];

}

else if(BFpktR[1]==(varTX_seqNo-1))

{

fl_LTresend=1;

fl_LA=1;

}

return;

}

void testLT()

{

if(BFpktR[1]==varRX_seqNo)

{

RX_seqNo=varRX_seqNo;

varRX_seqNo++;

fl_LT=1;

}

else if(BFpktR[1]==(varRX_seqNo-1))

{

fl_LAresend=1;

fl_LT=1;

}

else

{

fl_DLerr=1;

fl_LT=1;

}

return;

}

void initialise_variables()

{

varTX_seqNo=1;

varRX_seqNo=1;

RX_credNo=1;

TX_credNo=0;

RX_acked=1;

C1=N2;

}

void record_send_credit()

{

TX_credNo=RX_credNo;

return;

}

void rewind_packet_no()

{

varTX_seqNo=TX_seqNo;

return;

}

void setC1()

{

C1=N2;

return;

}

void decC1()

{

C1–;

return;

}

void REC_pkt_R(void)

{

timp();

char i;

idx_R=0;

stare=1;

chix=0;

for(i=0;i<lgrecradio;i++)

{

switch(stare)

{

case 1: {

if(bfrecradio[idx_R++]==SYN) stare=2;

else chix=1;

}

break;

case 2: {

if(bfrecradio[idx_R++]==DLE) stare=3;

else chix=1;

}

break;

case 3: {

if(bfrecradio[idx_R++]==STX) stare=4;

else chix=1;

}

break;

case 4: {

if(bfrecradio[idx_R++]==DLE) stare=5;

}

break;

case 5: {

if(bfrecradio[idx_R++]==ETX) stare=6;

else stare=4;

}

break;

case 6: {

crcHi=bfrecradio[idx_R++];

stare=7;

}

break;

case 7: {

crcLo=bfrecradio[idx_R];

checkDLE();

}

break;

}

if(chix)

{

stare=1;

return;

}

}

if(stare==7)

{

stare=1;

fl_pkt_R=1;

}

lgrecradio=0;

return;

}

void getoct(void)

{

lgrecradio=0;

bfrecradio[lgrecradio++]=bfOctRcSt;

fRecOctRd=0;

START_Tpack();

while(1)

{

timp();

if (miiToct)

{

if(fRecOctRd)

{

fRecOctRd=0;

bfrecradio[lgrecradio++]=bfOctRcSt;

START_Tpack();

}

}

else break;

}

}

void checkDLE()

{

j=0;

for (i=3;i<(lgrecradio-2);i++)

{

if((bfrecradio[i]==DLE)&&(bfrecradio[i+1]==DLE))

{

BFpktR[j]=bfrecradio[i];

j++;

i++;

}

else

{

BFpktR[j]=bfrecradio[i];

j++;

}

}

lmesrec= (unsigned int)j;

}

int checkCRC()

{

RecSumCalc((unsigned char*)BFpktR, lmesrec);

if((crcLo==(unsigned char)RCRC)&&(crcHi==(unsigned char)(RCRC>>8))) return 1;

else return 0;

}

void RESET_WAIT()

{

timp();

fl_RW=1;

if (NL_reset)

{

NL_reset=0;

RESET_PON();

return;

}

else if(!fl_LR&&fl_PON)

{

RESET_PON();

fl_PON=0;

return;

}

else if(fl_LR)

{

fl_LR=0;

SND_LR();

START_T0();

fl_RW=0;

fl_LW=1;

return;

}

else if(fl_LA||fl_LT||ctTm0==0)

{

fl_LA=0;

fl_LT=0;

SND_LR();

START_T0();

return;

}

}

void RESET_PON()

{

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

return;

}

void LINK_WAIT()

{

timp();

if(fl_LR)

{

S0BUF='d';

fl_LR=0;

initialise_variables();

STOP_T0();

SND_LA();

START_T4();

fl_LW=0;

fl_READY=1;

START_T3();

S0BUF='E';

fl_case=1;

afis=1;

return;

}

if(fl_LA)

{

fl_LA=0;

initialise_variables();

record_send_credit();

STOP_T0();

SND_LA();

START_T3();

START_T4();

fl_LW=0;

fl_case=1;

fl_READY=1;

afis=1;

return;

}

else if((ctTm0==0)||fl_LT)

{

fl_LT=0;

SND_LR();

START_T0();

fl_RW=1;

return;

}

}

void STATE_READY()

{

timp();

if(fl_NLP)

{

if(TX_credNo)

{

fl_Acc=1;

fl_NLP=0;

setC1();

SND_LT();

START_T1();

return;

}

else fl_Prej=1;

}

if((!sutT1)&&fl_T1)

{

decC1();

if(!C1)

{

STOP_T1();

STOP_T3();

STOP_T4();

fl_RW=1;

fl_READY=0;

SND_LR();

return;

}

else

{

rewind_packet_no();

SND_LT();

START_T1();

return;

}

}

if(fl_LA)

{

fl_LA=0;

START_T4();

record_send_credit();

if(fl_LAgood)

{

STOP_T1();

fl_LAgood=0;

setC1();

}

else if(fl_LTresend)

{

fl_LTresend=0;

decC1();

if(!C1)

{

STOP_T1();

STOP_T3();

STOP_T4();

fl_RW=1;

fl_READY=0;

SND_LR();

return;

}

else

{

rewind_packet_no();

SND_LT();

START_T1();

return;

}

}

}

if(fl_LR)

{

fl_LR=0;

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

fl_LW=1;

fl_READY=0;

return;

}

if (NL_reset)

{

NL_reset=0;

fl_READY=0;

fl_RW=1;

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

return;

}

if(fl_LT)

{

fl_LT=0;

START_T4();

if(fl_DLerr)

{

fl_DLerr=0;

fl_READY=0;

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

fl_RW=1;

return;

}

else if(fl_LAresend)

{

fl_LAresend=0;

SND_LA();

START_T3();

return;

}

if(RX_credNo)

{

memmove(bfrecNL,BFpktR+4,(lmesrec-4));

lgrecNL=lmesrec-4;

fl_recNL=1;

SND_LA();

START_T3();

return;

}

}

if(!secT3&&fl_T3)

{

SND_LA();

START_T3();

return;

}

if((!secT4)&&fl_T4)

{

STOP_T1();

STOP_T3();

STOP_T4();

fl_RW=1;

fl_READY=0;

SND_LR();

START_T0();

return;

}

return;

}

void test_pktNL()

{

switch(bfrecNL[0])

{

case STATUS:

{ if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_recsts=1;

}

}

break;

case ACKP:

{

if((PFIX1=bfrecNL[1]&0x7F)&&(IDENT1a=bfrecNL[2]&0x1F)&&(IDENT1b=bfrecNL[3]))

{

fl_ACKP=1;

}

}

break;

case ACKN:

{

if((PFIX1=bfrecNL[1]&0x7F)&&(IDENT1a=bfrecNL[2]&0x1F)&&(IDENT1b=bfrecNL[3]))

{

fl_ACKN=1;

}

}

break;

case SST: {

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_recsst=1;

memmove(recload,bfrecNL+6,lgrecNL-6);

}

}

break;

case PROGP:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_PROGP=1;

}

}

break;

case PROGN: {

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_PROGN=1;

}

}

break;

case MDM:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_recmdm=1;

}

}

break;

case RPROGP:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_RPROGP=1;

}

}

break;

case RPROGN:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_RPROGN=1;

}

}

break;

case GDISC:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_GDISC=1;

}

}

break;

case FDISC:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_FDISC=1;

}

}

break;

}

}

void makeNLpkt( unsigned char msgtip,unsigned char len)

{

char i=0,j=0;

if(msgtip==RC)

{

bfemNL[i++]=RC;

if(fl_hook) // testez daca on hook

{

if(fl_treq) // flag transmit on request

{

bfemNL[i++]=0x01;

}

else bfemNL[i++]=0x00;

}

else{

if(fl_treq) // flag transmit on request

{

bfemNL[i++]=0x03;

}

else bfemNL[i++]=0x02;

}

}

else {

i++;

bfemNL[i++]=PFIX1;

bfemNL[i++]=IDENT1a;

bfemNL[i++]=IDENT1b;

bfemNL[i++]=0x0;

if(msgtip==SST)

{

bfemNL[0]=SST;

bfemNL[i++]=0x07;

while(len–)

{

bfemNL[i++]=payload[j++];

}

}

if(msgtip==STATUS)

{

bfemNL[0]=STATUS;

bfemNL[i++]=stsmsg;

}

if(msgtip==MDM)

{

bfemNL[0]=MDM;

bfemNL[i++]=0x00;

}

if(msgtip==GDISC)

{

bfemNL[0]=GDISC;

bfemNL[4]=0x07;

i–;

}

if(msgtip==FDISC)

{

bfemNL[0]=FDISC;

bfemNL[4]=0x08;

i–;

}

lenNL=i;

memmove(bfLT+7,bfemNL,lenNL);

fl_NLP=1;

}

}

void NetLayer()

{

if(fl_recNL)

{

fl_recNL=0;

test_pktNL();

}

switch(stateNL)

{

case IDLE:

{

if(fl_recsst)

{

fl_recsst=0;

fl_rsst=1;

fl_case=1;

}

if(fl_recsts)

{

fl_case=1;

}

if(fl_recmdm)

{

fl_recmdm=0;

if(bfrecNL[5]==0x08)

{fl_rctrl=1;

fl_hook=0;

stateNL=INCCW;

}

else {

stateNL=ACTIVE;

fl_case=1;

fl_icall=1;

}

if(fl_sts)

{

fl_sts=0;

stateNL=STATW;

makeNLpkt(STATUS,0);

}

if(fl_sst)

{

fl_sst=0;

stateNL=SEGTRANSW;

makeNLpkt(SST,lgreccons-1);

}

else if(fl_mdm)

{

fl_mdm=0;

stateNL=OUTCW;

makeNLpkt(MDM,0);

}

else if(fl_rctrl)

{

fl_rctrl=0;

makeNLpkt(RC,0);

return;

}

else if(fl_mgmt)

{

fl_mgmt=0;

makeNLpkt(RM,0);

return;

}

if(fl_DLRESET)

{

NL_reset=1;

fl_DLRESET=0;

stateNL=IDLE;

}

}

break;

case OUTCW:

{

if(fl_PROGP)

{

fl_PROGP=0;

stateNL=ACTIVE;

fl_callb=1;

fl_case=1;

}

else if(fl_PROGN)

{

fl_PROGN=0;

stateNL=IDLE;

fl_callp=1;

fl_case=1;

}

}

break;

if(fl_DISCON)

{

fl_DISCON=0;

makeNLpkt(FDISC,0);

stateNL=IDLE;

}

if(fl_DLRESET)

{

NL_reset=1;

fl_DLRESET=0;

stateNL=IDLE;

}

}

break;

case INCCW:{

if(fl_RPROGP)

{

fl_RPROGP=0;

stateNL=ACTIVE;

fl_case=1;

fl_icall=1;

}

else if(fl_RPROGN)

{

fl_RPROGN=0;

stateNL=IDLE;

}

else if(fl_FDISC)

{

fl_FDISC=0;

stateNL=IDLE;

fl_rctrl=1;

fl_hook=1;

}

if(fl_rctrl)

{

fl_rctrl=0;

makeNLpkt(RC,0);

}

if(fl_DLRESET)

{

NL_reset=1;

fl_DLRESET=0;

stateNL=IDLE;

}

}

break;

case ACTIVE:{

if(fl_GDISC)

{

fl_GDISC=0;

stateNL=IDLE;

fl_rctrl=1;

fl_hook=1;

fl_case=1;

fl_gdsc=1;

}

else if(fl_FDISC)

{

fl_rctrl=1;

fl_hook=1;

}

if(fl_DISCON)

{

fl_DISCON=0;

makeNLpkt(GDISC,0);

stateNL=IDLE;

}

if(fl_rctrl)

{

fl_rctrl=0;

makeNLpkt(RC,0);

}

if(fl_DLRESET)

{

NL_reset=1;

stateNL=IDLE;

fl_DLRESET=0;

}

}

break;

case STATW:{

if(fl_ACKP)

{

stateNL=IDLE;

fl_ACKP=0;

fl_b=1;

fl_case=1;

}

if(fl_ACKN)

{

stateNL=IDLE;

fl_ACKN=0;

fl_p=1;

fl_case=1;

}

}

break;

case SEGTRANSW:{

if(fl_ACKP)

{

stateNL=IDLE;

fl_ACKP=0;

fl_sstb=1;

fl_case=1;

}

if(fl_ACKN)

{

stateNL=IDLE;

fl_ACKN=0;

fl_sstp=1;

fl_case=1;

}

if(fl_FDISC)

{

fl_FDISC=0;

stateNL=IDLE;

}

if(fl_DISCON)

{

fl_DISCON=0;

makeNLpkt(FDISC,0);

stateNL=IDLE;

}

if(fl_DLRESET)

{

NL_reset=1;

stateNL=IDLE;

fl_DLRESET=0;

}

}

break;

}

}

void main(void)

{

init_resurse();

init_var();

fl_PON=1;

fl_RW=1;

sprintf((char*)bfemcons, "\n\r Modem FSK pentru comunicatii de tip MPT1327\n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, " Va rugam asteptati ridicarea legaturii de date \n\r");

decl_em_cons();

while(fl_emcons);

while(1)

{

if(fRecOctRd)

{

getoct();

REC_pkt_R();

if(fl_pkt_R)

{

fl_pkt_R=0;

test_pkt_R();

if(fl_LW) LINK_WAIT();

if(fl_RW) RESET_WAIT();

if(fl_READY) STATE_READY();

}

}

else if(fl_RW) RESET_WAIT();

if(fl_READY) STATE_READY();

if(fl_READY) NetLayer();

if(fl_case) meniu();

}

}

void meniu()

{

unsigned char *ptloc;

fl_case=0;

switch(afis)

{

case 1: {

sprintf((char*)bfemcons, "Legatura de date ridicata\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

break;

case 2: {

sprintf((char*)bfemcons, "Pentru mesaj de tip STATUS apasati 1 si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, "Pentru mesaj de tip SST apasati 2 si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, "Pentru un apel de voce apasati 3 si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

afis=3;

}

break;

case 3: {

if(flag_rec_cons)

{

flag_rec_cons=0;

if(lgreccons==2)

{

if((bfreccons[0]-0x30)==1)

{

sprintf((char*)bfemcons, "Introduceti un numar intre 0 si 31 si apasati ENTER \n\r");

decl_em_cons();

while(fl_emcons);

afis=4;

fl_case=1;

}

else if((bfreccons[0]-0x30)==2)

{

sprintf((char*)bfemcons, "Introduceti un mesaj de maxim 20 de caractere si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

afis=6;

fl_case=1;

}

else if((bfreccons[0]-0x30)==3)

{

fl_mdm=1;

afis=8;

}

else

{

sprintf((char*)bfemcons, "\n\rNumar invalid\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

}

if(fl_recsts)

{

sprintf((char*)bfemcons, "Am primit un mesaj de status cu numarul %d\n\r",(int)bfrecNL[5]);

decl_em_cons();

while(fl_emcons);

fl_recsts=0;

}

if(fl_rsst)

{

fl_rsst=0;

sprintf((char*)bfemcons, "Am primit un mesaj SST:\n\r");

decl_em_cons();

while(fl_emcons);

ptloc=bfemcons;

sprintf((char*)ptloc, "M: ");

ptloc+=3;

for(i=0;(i<lgrecNL-6);i++)

{

if((*ptloc=recload[i])!=0x00)

{

ptloc++;

}

else i=lgrecNL-6;

}

*(ptloc++) = 0x0d;

*(ptloc++) = 0x0a;

*ptloc = 0x0;

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

if(fl_icall)

{

fl_icall=0;

sprintf((char*)bfemcons, "Apel in desfasurare ! Pentru deconectare apasati 1 si ENTER\n\r");

decl_em_cons();

while(fl_emcons);

afis=9;

}

}

break;

case 4:{

if(flag_rec_cons)

{

flag_rec_cons=0;

if(lgreccons==2)

{

stsmsg=bfreccons[0]-0x30;

fl_sts=1;

afis=5;

}

else if(lgreccons==3)

{

stsmsg=(bfreccons[0]-0x30)*10;

stsmsg=stsmsg+(bfreccons[1]-0x30);

if(stsmsg<32)

{

fl_sts=1;

afis=5;

}

else

{

sprintf((char*)bfemcons, "\n\rNumar invalid,introduceti un numar mai mic decat 31 si ENTER\n\r");

decl_em_cons();

while(fl_emcons);

}

}

else

{

sprintf((char*)bfemcons, "\n\rNumar invalid\n\r");

decl_em_cons();

while(fl_emcons);

}

}

}

break;

case 5: {

if(fl_b)

{

fl_b=0;

sprintf((char*)bfemcons, "Transactie reusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

else if(fl_p)

{

fl_p=0;

sprintf((char*)bfemcons, "Tranzactie nereusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

break;

case 6:

{

if(flag_rec_cons)

{

fl_sst=1;

memmove(payload,bfreccons,lgreccons-1);

afis=7;

}

}break;

case 7 : {

if(fl_sstb)

{

fl_sstb=0;

sprintf((char*)bfemcons, "Transactie reusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

else if(fl_sstp)

{

fl_sstp=0;

sprintf((char*)bfemcons, "Tranzactie nereusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

break;

case 8: {

if(fl_callb)

{

fl_sstb=0;

sprintf((char*)bfemcons, "Apel reusit\n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, "Pentru deconectare apasati 1 si tasta ENTER\n\r");

decl_em_cons();

while(fl_emcons);

afis=9;

fl_case=1;

}

else if(fl_callp)

{

fl_sstp=0;

sprintf((char*)bfemcons, "Apel esuat\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

break;

case 9: {

if(lgreccons==2)

{

if((bfreccons[0]-0x30)==1)

{

fl_DISCON=1;

afis=2;

fl_case=1;

sprintf((char*)bfemcons, "Apel terminat\n\r");

decl_em_cons();

while(fl_emcons);

}

}

if(fl_gdsc)

{

fl_gdsc=0;

afis=2;

fl_case=1;

sprintf((char*)bfemcons, "Apel terminat\n\r");

decl_em_cons();

while(fl_emcons);

}

}break;

}

}

SALTURI.ASM

PUBLIC initasm, armezCM1

PUBLIC endemr, fRecOctRd

PUBLIC R0_2, R1_2, R2_2, R3_2, R4_2, R5_2, R6_2, R7_2, bfOctRcSt

EXTRN CODE (contor)

EXTRN CODE (cons_ser)

CTI0 equ 0c8h CTI3 equ 0cbh CMI0 equ 0cch CMI1 equ 0cdh ECM0 equ 0ech ECM1 equ 0edh ECT0 equ 0e8h CTCON equ 0ebh

CTH0 equ 0cch CTL0 equ 0ach

CTH3 equ 0cfh CTL3 equ 0afh

CMH0 equ 0c9h

CML0 equ 0a9h

CMH1 equ 0cah

CML1 equ 0aah

tm2con equ 0eah

P1_0 equ 090h P4_0 equ 0c0h

DRBIT equ 0aeh DRSTART equ 0d6h HFBIT equ 057h

;––––––––––––––

BSEG AT 0

endemr: dbit 1

fRecOctRd:dbit 1

DSEG AT 010h

R0_2: ds 1

R1_2: ds 1

R2_2: ds 1

R3_2: ds 1

R4_2: ds 1

R5_2: ds 1

R6_2: ds 1

R7_2: ds 1

DSEG AT 040h

bfOctRcSt: ds 1

CSEG AT 8000h LJMP blkx

CSEG AT 800bh

LJMP contor

CSEG AT 8023h

LJMP cons_ser

CSEG AT 8033h LJMP START_RxD_statie

CSEG AT 805bh LJMP RxD_statie

CSEG AT 8063h LJMP TxD_statie

;––––––––––––––––-

CSEG AT 807bh

blkx:

MOV DPTR,#0fb00h

MOV R7, #0

MOV R6, #03h

CLR A

XDATALOOP:

MOVX @DPTR,A

INC DPTR

DJNZ R7, XDATALOOP

DJNZ R6, XDATALOOP

LJMP 8200h

initasm:

push psw

clr fRecOctRd

setb endemr setb 0d4h clr 0d3h

mov r4, #8

mov r2, #9

pop psw

mov ctcon, #082h

mov tm2con, #01h

clr CTI0

setb ect0

clr CMI1

clr ECM1

ret

;––––––––––––––––––––––––––

PUBLIC sdebug

sdebug:

clr ea

push dpl

push dph

push acc

mov a, r0

mov dptr, #0f900h

movx @dptr, a inc dptr

mov r0, #1

bsav: mov a, @r0

movx @dptr, a

inc dptr

inc r0

cjne r0, #0, bsav

pop acc

movx @dptr, a inc dptr

pop acc movx @dptr, a

inc dptr

pop acc movx @dptr, a

mov sp, #0

ljmp 0

;

;–––––––––––––––––––––––––––-

START_RxD_statie:

push acc push psw

clr CTI0 clr ECT0 mov a, CTL0

add a, #DRSTART

mov CML0, a

mov a, CTH0

addc a, #0

mov CMH0, a

pop psw

pop acc

clr CMI0 setb ECM0 reti

RxD_statie:

push acc push psw

clr CMI0 setb 0d4h clr 0d3h

cjne r4, #0, mairec

mov r4, #8 mov bfOctRcSt, r5 setb fRecOctRd

clr ECM0 clr CTI0

setb ECT0 sjmp exitRcRd

mairec:

mov a, r5

rr a

mov c, P1_0

mov 0e7h, c

mov r5, a

mov a, CML0

add a, #DRBIT

mov CML0, a

mov a, CMH0

addc a, #0

mov CMH0, a

dec r4

exitRcRd:

pop psw

pop acc

reti

armezCM1: mov a, CTL3

add a, #DRBIT

mov CML1, a

mov a, CTH3

addc a, #0

mov CMH1, a

clr CMI1 setb ECM1 ret

TxD_statie: push acc push psw

clr CMI1

setb 0d4h clr 0d3h

cjne r2, #0, maiem

mov r2, #9

clr ECM1 setb endemr

sjmp exitem

maiem:

mov a, r3

setb c rrc a mov P4_0, c

mov r3, a

mov a, CML1

add a, #DRBIT

mov CML1, a

mov a, CMH1

addc a, #0

mov CMH1, a

dec r2

exitem:

pop psw

pop acc

reti

;

; End of salturi.asm

END

; File Name: STARTUP.A51 – (c) Copyright Franklin Software, Inc. 1989

;

;––––––––––––––––––––––––––

;

; STARTUP.A51: This code is executed after processor reset.

;

; To ASSEMBLE this file use A51 (ver. 4.3 & up), with the following

; invocation:

;

; A51 STARTUP.A51

;

; To LINK the modified STARTUP.OBJ file into your application use the

; following L51 (ver. 2.4 & up) invocation:

;

; L51 STARTUP.OBJ, <your object file list> <controls>

;

;––––––––––––––––––––––––––

;

;

; User-defined Power-On Initialization of Memory

;

; With the following EQU statements the initialization of memory

; at processor reset can be defined:

;

; Note: the absolute start-address of IDATA memory is always 0

IDATALEN EQU 100H ; the length of IDATA memory in bytes.

;

XDATASTART EQU 0FB00H ; the absolute start-address of XDATA memory

XDATALEN EQU 0H ; the length of XDATA memory in bytes.

;

PDATASTART EQU 0H ; the absolute start-address of PDATA memory

PDATALEN EQU 0H ; the length of PDATA memory in bytes.

;

; Notes: The IDATA space overlaps physically the DATA and BIT areas of the

; 8051 CPU. At a minimum, the memory space occupied from the C-51

; run-time routines must be set to zero.

;

;––––––––––––––––––––––––––

;

;

NAME ?C_STARTUP

?C_C51STARTUP SEGMENT CODE

?STACK SEGMENT IDATA

RSEG ?STACK

STACK: DS 1

EXTRN CODE (?C_START)

PUBLIC ?C_STARTUP

?C_STARTUP: LJMP STARTUP1

RSEG ?C_C51STARTUP

STARTUP1:

;

; Setup for and execute the IDATALEN init sequence

IF IDATALEN <> 0

MOV R0,#IDATALEN – 1

CLR A

IDATALOOP: MOV @R0,A

DJNZ R0,IDATALOOP

ENDIF

;

; Setup for and execute the XDATA init sequence

XDATALEN EQU 0H

IF XDATALEN <> 0

MOV DPTR,#XDATASTART

MOV R7,#LOW (XDATALEN)

IF (LOW (XDATALEN)) <> 0

MOV R6,#(HIGH XDATALEN) +1

ELSE

MOV R6,#HIGH (XDATALEN)

ENDIF

CLR A

XDATALOOP: MOVX @DPTR,A

INC DPTR

DJNZ R7,XDATALOOP

DJNZ R6,XDATALOOP

ENDIF

;

; Setup for and execute the PDATA init. sequences.

IF PDATALEN <> 0

MOV R0,#PDATASTART

MOV R7,LOW (PDATALEN)

CLR A

PDATALOOP: MOVX @R0,A

INC R0

DJNZ R7,PDATALOOP

ENDIF

;

; Install the stack value and jump through the startup location

MOV SP,#LOW (STACK-1)

LJMP ?C_START

END

;

; End of STARTUP.A51

Bibliografie

1. http://www.ofcom.org.uk/static/archive/ra/publication/mpt/mpt_pdf/mpt1327.pdf – Protocolul MAP27.

2. http://www.mpt1327-usa.org/downloads/map27.pdf – Standardul MPT1327.

3. ***: Phillips Semiconductors, 8051 family derivates,1996.

4. ***: Phillips Semiconductors, DATA SHEET 80C552/83C552, 2002.

5. http://www.8052.com/book – informații legate de familia 8051

6. ***: Keil Elektronik GmbH., and Keil Software, Inc. , C51 Compiler, 1997.

7. ***: Keil Elektronik GmbH and Keil Software, Inc. , 8051/251 Evaluation kit, 1998.

8. ***: Costin Ștefănescu , Nicolae Cupcea , Electronică aplicată – Sisteme inteligente hardware – Software de măsurare și control , București 2003.

9. ***: Mazilu Alexandru, Calil Nadir, Coordonatori Științifici V.Croitoru , T.Voica, Modem radio FSK pentru comunicații de tip MPT1327, cu implementarea protocolului MAP27, Sesiunea de Comunicări Științifice,București,2014.

10. http://www.hobbyprojects.com/8051_tutorial/special_function_registers.html – explicații legate de registrele SFR

11. ***: Temic Semiconductors, C51 Family, 1997.

12. ***: Phillips Semiconductors, 80C51 programmer's guide and instruction set,1997.

Anexă – codul sursă

#pragma SYMBOLS

#pragma CODE

#pragma DEBUG

#pragma LARGE

#include <stdio.h>

#include <ctype.h>

#include <string.h>

#include <stdlib.h>

#include <math.h>

#include <porturi.h>

#include "reg552.h"

#define TERM 0x0d

#define ML 0x0b

#define WS 0x01

#define VER 0x01

#define SYN 0x16

#define DLE 0x10

#define STX 0x02

#define ETX 0x03

#define LR 0x01

#define NUL 0x00

#define N2 0x0A

#define N3 0x02

#define LA 0x02

#define LT 0x04

#define N1 0x0A

#define STATUS 0x80

#define ACKP 0xC0

#define ACKN 0xE0

#define SST 0x81

#define MDM 0xA4

#define PROGP 0xC4

#define PROGN 0xE4

#define RPROGP 0xC5

#define RPROGN 0xE5

#define MDMDATA 0xA3

#define GDISC 0x86

#define FDISC 0xA6

#define RC 0xb2

#define RM 0xb3

#define IDLE 0xAA

#define OUTCW 0xBB

#define ACTIVE 0xCC

#define INCCW 0xDD

#define STATW 0xEE

#define SEGTRANSW 0xFF

extern bit endemr, fRecOctRd;

extern data char R0_2, R1_2, R2_2, R3_2, R4_2, R5_2, R6_2, R7_2, bfOctRcSt;

extern code initasm();

extern code armezCM1();

extern code sdebug();

void cons_ser(void);

void decl_em_cons(void);

void cvchar(unsigned char, unsigned char *);

void init_var(void);

void init_resurse(void);

void decl_em_radio(unsigned char);

void em_radio(void);

void contor(void);

void CheckSumCalc (unsigned char * buff, unsigned int len);

void pkt(void);

void REC_pkt_R(void);

void test_pkt_C(void);

void test_pkt_R(void);

void SND_LR(void);

void SND_LA(void);

void SND_LR(void);

void START_T0(void);

void STOP_T0(void);

void START_T1(void);

void STOP_T1(void);

void START_T3(void);

void STOP_T3(void);

void START_T4(void);

void STOP_T4(void);

void initialise_variables(void);

void record_send_credit(void);

void rewind_packet_no(void);

void setC1(void);

void decC1(void);

void START_Tpack(void);

void checkDLE(void);

void getoct(void);

void putDLE(unsigned char *buff, int lungime);

int checkCRC(void);

void testLR(void);

void testLA(void);

void testLT(void);

void RESET_WAIT(void);

void RESET_PON(void);

void LINK_WAIT(void);

void STATE_READY(void);

void NetLayer(void);

void makeNLpkt( unsigned char msgtip,unsigned char len);

void test_pktNL(void);

void START_T5(void);

void meniu(void);

bit flag_rec_cons,fl_emcons,flag_start_rec;

bit fl_pkt_rec ,fl_pkt_R,fl_AR, fl_LR, fl_LA, fl_LT, fl_RW,fl_LW;

bit fl_READY,fl_PON,NL_reset, chix, fpkt_err, flzec,fl_NLP, fl_Prej ,fl_Acc;

bit fl_LTresend,fl_DLerr,fl_LAresend,fl_LAgood,fl_T0, fl_T1,fl_T3, fl_T4, fl_recNL;

bit fl_hook,fl_treq,fl_sst,fl_mdm,fl_rctrl,fl_mgmt,fl_recsst, fl_recmdm, fl_RPROGP;

bit fl_PROGP,fl_PROGN,fl_DISCON,fl_RPROGN,fl_FDISC, fl_GDISC, fl_ACKP,fl_ACKN,fl_DLRESET,fl_sts;

bit fl_b,fl_p,fl_case,fl_sstp,fl_sstb,fl_callb,fl_callp,fl_recsts, fl_icall,fl_gdsc,fl_rsst;

data char idx_em_cons, idx_rec_cons, lgreccons,idx_R,secT5,sts ,stsmsg;

data char idx_emchar_radio, lgrecradio,idx_rec_radio,i,j,index;

data unsigned char bfemr,bfrecr, bftempr,varRX_seqNo,RX_seqNo,RX_credNo,TX_seqNo,TX_credNo,varTX_seqNo,RX_acked,C1,crcHi,crcLo;

data unsigned char stare,stRX_cred,lgemradio,lenNL,stateNL,afis,lgrecNL;

data unsigned char zecimi,sutimi,miimi, secunde,idx_pc,idx_pr,sutT1,secT3,secT4,miiToct,idx_retT0;

data unsigned char PFIX1,PFIX2,IDENT1a,IDENT1b,IDENT2a,IDENT2b,ADESC,LENGTH,NLB,ADDRESS;

data unsigned int CRC,RCRC, lmesrec, ctTm0;

xdata unsigned char bfLR[12]={SYN,DLE,STX,LR,N1,WS,VER,DLE,ETX};

xdata unsigned char bfLA[12]={SYN,DLE,STX,LA,ML,WS,NUL,DLE,ETX};

xdata unsigned char bfemcons[120], bfreccons[80], bfemradio[100],BFpktR[50], bfrecradio[100];

xdata unsigned char bfrecNL[100],bfLT[40]={SYN,DLE,STX,LT,0x00,0x01,0x00}, bfemNL[50],payload[30],recload[30];

code unsigned int mtab [] =

{

0x0000, 0xC1C0, 0x81C1, 0x4001, 0x01C3, 0xC003, 0x8002, 0x41C2, 0x01C6, 0xC006, 0x8007, 0x41C7, 0x0005, 0xC1C5, 0x81C4, 0x4004,

0x01CC, 0xC00C, 0x800D, 0x41CD, 0x000F, 0xC1CF, 0x81CE, 0x400E, 0x000A, 0xC1CA, 0x81CB, 0x400B, 0x01C9, 0xC009, 0x8008, 0x41C8,

0x01D8, 0xC018, 0x8019, 0x41D9, 0x001B, 0xC1DB, 0x81DA, 0x401A, 0x001E, 0xC1DE, 0x81DF, 0x401F, 0x01DD, 0xC01D, 0x801C, 0x41DC,

0x0014, 0xC1D4, 0x81D5, 0x4015, 0x01D7, 0xC017, 0x8016, 0x41D6, 0x01D2, 0xC012, 0x8013, 0x41D3, 0x0011, 0xC1D1, 0x81D0, 0x4010,

0x01F0, 0xC030, 0x8031, 0x41F1, 0x0033, 0xC1F3, 0x81F2, 0x4032, 0x0036, 0xC1F6, 0x81F7, 0x4037, 0x01F5, 0xC035, 0x8034, 0x41F4,

0x003C, 0xC1FC, 0x81FD, 0x403D, 0x01FF, 0xC03F, 0x803E, 0x41FE, 0x01FA, 0xC03A, 0x803B, 0x41FB, 0x0039, 0xC1F9, 0x81F8, 0x4038,

0x0028, 0xC1E8, 0x81E9, 0x4029, 0x01EB, 0xC02B, 0x802A, 0x41EA, 0x01EE, 0xC02E, 0x802F, 0x41EF, 0x002D, 0xC1ED, 0x81EC, 0x402C,

0x01E4, 0xC024, 0x8025, 0x41E5, 0x0027, 0xC1E7, 0x81E6, 0x4026, 0x0022, 0xC1E2, 0x81E3, 0x4023, 0x01E1, 0xC021, 0x8020, 0x41E0,

0x01A0, 0xC060, 0x8061, 0x41A1, 0x0063, 0xC1A3, 0x81A2, 0x4062, 0x0066, 0xC1A6, 0x81A7, 0x4067, 0x01A5, 0xC065, 0x8064, 0x41A4,

0x006C, 0xC1AC, 0x81AD, 0x406D, 0x01AF, 0xC06F, 0x806E, 0x41AE, 0x01AA, 0xC06A, 0x806B, 0x41AB, 0x0069, 0xC1A9, 0x81A8, 0x4068,

0x0078, 0xC1B8, 0x81B9, 0x4079, 0x01BB, 0xC07B, 0x807A, 0x41BA, 0x01BE, 0xC07E, 0x807F, 0x41BF, 0x007D, 0xC1BD, 0x81BC, 0x407C,

0x01B4, 0xC074, 0x8075, 0x41B5, 0x0077, 0xC1B7, 0x81B6, 0x4076, 0x0072, 0xC1B2, 0x81B3, 0x4073, 0x01B1, 0xC071, 0x8070, 0x41B0,

0x0050, 0xC190, 0x8191, 0x4051, 0x0193, 0xC053, 0x8052, 0x4192, 0x0196, 0xC056, 0x8057, 0x4197, 0x0055, 0xC195, 0x8194, 0x4054,

0x019C, 0xC05C, 0x805D, 0x419D, 0x005F, 0xC19F, 0x819E, 0x405E, 0x005A, 0xC19A, 0x819B, 0x405B, 0x0199, 0xC059, 0x8058, 0x4198,

0x0188, 0xC048, 0x8049, 0x4189, 0x004B, 0xC18B, 0x818A, 0x404A, 0x004E, 0xC18E, 0x818F, 0x404F, 0x018D, 0xC04D, 0x804C, 0x418C,

0x0044, 0xC184, 0x8185, 0x4045, 0x0187, 0xC047, 0x8046, 0x4186, 0x0182, 0xC042, 0x8043, 0x4183, 0x0041, 0xC181, 0x8180, 0x4040,

};

void init_resurse(void)

{

PCON|=0x80;

S0CON=0x50;

TMOD=0x21;

TCON=0x50;

TH1=0xF5;

PT0=0;

PS0=0;

PCM0=1;

PCM1=1;

PCT0=1;

ET0=1;

ET2=0;

ECM1=0;

ES0=1;

EA=1;

initasm();

}

void init_var(void)

{

idx_rec_radio=8;

idx_rec_cons=0;

flag_rec_cons=0;

fl_emcons=0;

idx_emchar_radio=0;

fl_pkt_rec=0;

NL_reset=0;

RX_seqNo=1;

miimi=10;

flzec = 0;

secunde=60;

sutimi=10;

zecimi=10;

stare=1;

idx_pc=0;

sutT1=0;

ctTm0=1;

secT3=0;

secT4=0;

i=0;

j=0;

fl_AR=0;

fl_pkt_R=0;

index=0;

crcHi=0;

crcLo=0;

fl_LR=0;

fl_LA=0;

fl_LT=0;

idx_R=0;

idx_retT0=3;

miimi= 10;

idx_pc=0;

idx_pr=0;

lmesrec=0;

fl_NLP=0;

fl_Prej=0;

fl_Acc=0;

stRX_cred=0;

fl_LTresend=0;

fl_DLerr=0;

fl_LAresend=0;

fl_LAgood=0;

fl_LAresend=0;

fl_T0=0;

fl_T1=0;

fl_T3=0;

fl_T4=0;

varTX_seqNo=1;

fl_recNL=0;

lenNL=0;

stateNL=IDLE;

fl_hook=1;

fl_treq=0;

fl_rctrl=0;

fl_mgmt=0;

fl_sst=0;

fl_mdm=0;

fl_recsst=0;

fl_recmdm=0;

fl_RPROGP=0;

fl_PROGP=0;

fl_PROGN=0;

fl_DISCON=0;

fl_RPROGN=0;

fl_FDISC=0;

fl_GDISC=0;

fl_ACKP=0;

fl_ACKN=0;

fl_DLRESET=0;

fl_sts=0;

PFIX1=11;

PFIX2=11;

IDENT1a=24;

IDENT1b=196;

IDENT2a=24;

IDENT2b=197;

stsmsg=20;

fl_case=0;

afis=0;

fl_b=0;

fl_p=0;

lgrecNL=0;

fl_sstb=0;

fl_sstp=0;

fl_callb=0;

fl_callp=0;

fl_recsts=0;

fl_icall=0;

fl_gdsc=0;

fl_rsst=0;

}

void decl_em_cons(void)

{

idx_em_cons=1;

fl_emcons=1;

S0BUF=bfemcons[0];

}

void cons_ser(void) interrupt 4 using 1

{

if(TI)

{

TI=0;

if(bfemcons[idx_em_cons])

{

S0BUF=bfemcons[idx_em_cons++];

}

else fl_emcons=0;

}

if (RI)

{

RI=0;

if((bfreccons[idx_rec_cons++]=S0BUF)==TERM)

{

flag_rec_cons=1;

lgreccons=idx_rec_cons;

idx_rec_cons=0;

fl_case=1;

ECT0=1;

}

}

}

void contor(void) interrupt 1 using 3

{

TL0=0x7d;

TH0=0xf9;

miimi–;

if(miiToct)

{

miiToct–;

}

if(!miimi)

{

miimi=10;

sutimi–;

if(ctTm0)

{

ctTm0–;

}

}

if(!sutimi)

{

sutimi=10;

flzec=1;

}

}

void timp()

{

if(flzec)

{

flzec=0;

zecimi–;

if(!zecimi)

{

zecimi=10;

secunde–;

if(secT3)

{

secT3–;

}

if(secT4)

{

secT4–;

}

if(!secunde)

{

secunde=60;

}

}

}

}

void cvchar(unsigned char cint, unsigned char * bem)

{

unsigned char b;

b = (cint>>4)&0x0f;

if(b<0x0A) b+=0x30;

else b+=0x37;

*bem = b;

bem++;

b = cint&0x0f;

if(b<0x0A) b+=0x30;

else b+=0x37;

*bem = b;

bem++;

*bem = ' ';

}

void decl_em_radio(unsigned char lgem1)

{

ECT0=0;

idx_emchar_radio=0;

endemr=1;

while(idx_emchar_radio<lgem1)

{

if(endemr)

{

endemr=0;

R3_2=bfemradio[idx_emchar_radio++];

P4_0=0;

armezCM1();

}

}

ECT0=1;

}

void START_Tpack()

{

miiToct=20;

}

void START_T0()

{

ctTm0=idx_retT0*10;

if (idx_retT0>150)

{

idx_retT0=1;

}

idx_retT0++;

fl_T0=1;

}

void STOP_T0()

{

idx_retT0=3;

ctTm0=1;

fl_T0=0;

}

void START_T1()

{

sutT1=50;

fl_T1=1;

}

void STOP_T1()

{

sutT1=0;

fl_T1=0;

}

void START_T3()

{

secT3=6;

fl_T3=1;

}

void STOP_T3()

{

secT3=0;

fl_T3=0;

}

void START_T4()

{

secT4=20;

fl_T4=1;

}

void STOP_T4()

{

secT4=0;

fl_T4=0;

}

void START_T5()

{

secT5=10;

}

void SND_LR()

{

CheckSumCalc((unsigned char*)bfLR,9);

bfLR[10]=(unsigned char)CRC;

bfLR[9]=(unsigned char)(CRC>>8);

putDLE((unsigned char *)bfLR,11);

lgemradio = 11;

decl_em_radio(lgemradio);

return;

}

void SND_LA()

{

bfLA[4]=varRX_seqNo;

bfLA[5]=RX_credNo;

CheckSumCalc((unsigned char*)bfLA,9);

bfLA[10]=(unsigned char)CRC;

bfLA[9]=(unsigned char)(CRC>>8);

putDLE((unsigned char *)bfLA,11);

decl_em_radio(lgemradio);

}

void SND_LT()

{

bfLT[4]=varTX_seqNo;

TX_seqNo=varTX_seqNo;

varTX_seqNo++;

TX_credNo–;

lenNL+=7;

bfLT[lenNL++]=DLE;

bfLT[lenNL++]=ETX;

CheckSumCalc((unsigned char *)bfLT,lenNL);

bfLT[lenNL+1]=(unsigned char)CRC;

bfLT[lenNL]=(unsigned char)(CRC>>8);

putDLE((unsigned char *)bfLT,lenNL+2);

decl_em_radio(lgemradio);

}

void putDLE(unsigned char *buff, int lungime)

{

char i,j;

bfemradio[0]=buff[0];

bfemradio[1]=buff[1];

bfemradio[2]=buff[2];

j=3;

for(i=3;i<lungime-4;i++)

{

if(buff[i]==DLE)

{

bfemradio[j++]=DLE;

bfemradio[j++]=DLE;

}

else

{

bfemradio[j++]=buff[i];

}

}

for(;i<lungime;i++)

{

bfemradio[j++]=buff[i];

}

lgemradio=j;

}

void CheckSumCalc (unsigned char * buff, unsigned int len)

{

unsigned int q;

buff+=3;

len-=3;

CRC = 0xffff;

while (len–)

{

q = * (mtab + (* buff++ ^(CRC >> 8)));

CRC = ((q & 0xff00) ^ (CRC << 8)) | (q & 0x00ff);

}

CRC = CRC^0xffff;

return;

}

void RecSumCalc (unsigned char * buff, unsigned int len)

{

unsigned int q;

RCRC = 0xffff;

while (len–)

{

q = * (mtab + (* buff++ ^(RCRC >> 8)));

RCRC = ((q & 0xff00) ^ (RCRC << 8)) | (q & 0x00ff);

}

RCRC = RCRC^0xffff;

return;

}

void test_pkt_R()

{

timp();

if(checkCRC())

{

if(BFpktR[0]==LR) testLR();

else if(BFpktR[0]==LA) testLA();

else if(BFpktR[0]==LT) testLT();

}

return;

}

void testLR()

{

if(BFpktR[2]==WS&&BFpktR[3]==VER )

{

fl_LR=1;

}

return;

}

void testLA()

{

if(BFpktR[1]==varTX_seqNo)

{

fl_LA=1;

fl_LAgood=1;

TX_credNo=BFpktR[2];

}

else if(BFpktR[1]==(varTX_seqNo-1))

{

fl_LTresend=1;

fl_LA=1;

}

return;

}

void testLT()

{

if(BFpktR[1]==varRX_seqNo)

{

RX_seqNo=varRX_seqNo;

varRX_seqNo++;

fl_LT=1;

}

else if(BFpktR[1]==(varRX_seqNo-1))

{

fl_LAresend=1;

fl_LT=1;

}

else

{

fl_DLerr=1;

fl_LT=1;

}

return;

}

void initialise_variables()

{

varTX_seqNo=1;

varRX_seqNo=1;

RX_credNo=1;

TX_credNo=0;

RX_acked=1;

C1=N2;

}

void record_send_credit()

{

TX_credNo=RX_credNo;

return;

}

void rewind_packet_no()

{

varTX_seqNo=TX_seqNo;

return;

}

void setC1()

{

C1=N2;

return;

}

void decC1()

{

C1–;

return;

}

void REC_pkt_R(void)

{

timp();

char i;

idx_R=0;

stare=1;

chix=0;

for(i=0;i<lgrecradio;i++)

{

switch(stare)

{

case 1: {

if(bfrecradio[idx_R++]==SYN) stare=2;

else chix=1;

}

break;

case 2: {

if(bfrecradio[idx_R++]==DLE) stare=3;

else chix=1;

}

break;

case 3: {

if(bfrecradio[idx_R++]==STX) stare=4;

else chix=1;

}

break;

case 4: {

if(bfrecradio[idx_R++]==DLE) stare=5;

}

break;

case 5: {

if(bfrecradio[idx_R++]==ETX) stare=6;

else stare=4;

}

break;

case 6: {

crcHi=bfrecradio[idx_R++];

stare=7;

}

break;

case 7: {

crcLo=bfrecradio[idx_R];

checkDLE();

}

break;

}

if(chix)

{

stare=1;

return;

}

}

if(stare==7)

{

stare=1;

fl_pkt_R=1;

}

lgrecradio=0;

return;

}

void getoct(void)

{

lgrecradio=0;

bfrecradio[lgrecradio++]=bfOctRcSt;

fRecOctRd=0;

START_Tpack();

while(1)

{

timp();

if (miiToct)

{

if(fRecOctRd)

{

fRecOctRd=0;

bfrecradio[lgrecradio++]=bfOctRcSt;

START_Tpack();

}

}

else break;

}

}

void checkDLE()

{

j=0;

for (i=3;i<(lgrecradio-2);i++)

{

if((bfrecradio[i]==DLE)&&(bfrecradio[i+1]==DLE))

{

BFpktR[j]=bfrecradio[i];

j++;

i++;

}

else

{

BFpktR[j]=bfrecradio[i];

j++;

}

}

lmesrec= (unsigned int)j;

}

int checkCRC()

{

RecSumCalc((unsigned char*)BFpktR, lmesrec);

if((crcLo==(unsigned char)RCRC)&&(crcHi==(unsigned char)(RCRC>>8))) return 1;

else return 0;

}

void RESET_WAIT()

{

timp();

fl_RW=1;

if (NL_reset)

{

NL_reset=0;

RESET_PON();

return;

}

else if(!fl_LR&&fl_PON)

{

RESET_PON();

fl_PON=0;

return;

}

else if(fl_LR)

{

fl_LR=0;

SND_LR();

START_T0();

fl_RW=0;

fl_LW=1;

return;

}

else if(fl_LA||fl_LT||ctTm0==0)

{

fl_LA=0;

fl_LT=0;

SND_LR();

START_T0();

return;

}

}

void RESET_PON()

{

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

return;

}

void LINK_WAIT()

{

timp();

if(fl_LR)

{

S0BUF='d';

fl_LR=0;

initialise_variables();

STOP_T0();

SND_LA();

START_T4();

fl_LW=0;

fl_READY=1;

START_T3();

S0BUF='E';

fl_case=1;

afis=1;

return;

}

if(fl_LA)

{

fl_LA=0;

initialise_variables();

record_send_credit();

STOP_T0();

SND_LA();

START_T3();

START_T4();

fl_LW=0;

fl_case=1;

fl_READY=1;

afis=1;

return;

}

else if((ctTm0==0)||fl_LT)

{

fl_LT=0;

SND_LR();

START_T0();

fl_RW=1;

return;

}

}

void STATE_READY()

{

timp();

if(fl_NLP)

{

if(TX_credNo)

{

fl_Acc=1;

fl_NLP=0;

setC1();

SND_LT();

START_T1();

return;

}

else fl_Prej=1;

}

if((!sutT1)&&fl_T1)

{

decC1();

if(!C1)

{

STOP_T1();

STOP_T3();

STOP_T4();

fl_RW=1;

fl_READY=0;

SND_LR();

return;

}

else

{

rewind_packet_no();

SND_LT();

START_T1();

return;

}

}

if(fl_LA)

{

fl_LA=0;

START_T4();

record_send_credit();

if(fl_LAgood)

{

STOP_T1();

fl_LAgood=0;

setC1();

}

else if(fl_LTresend)

{

fl_LTresend=0;

decC1();

if(!C1)

{

STOP_T1();

STOP_T3();

STOP_T4();

fl_RW=1;

fl_READY=0;

SND_LR();

return;

}

else

{

rewind_packet_no();

SND_LT();

START_T1();

return;

}

}

}

if(fl_LR)

{

fl_LR=0;

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

fl_LW=1;

fl_READY=0;

return;

}

if (NL_reset)

{

NL_reset=0;

fl_READY=0;

fl_RW=1;

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

return;

}

if(fl_LT)

{

fl_LT=0;

START_T4();

if(fl_DLerr)

{

fl_DLerr=0;

fl_READY=0;

STOP_T1();

STOP_T3();

STOP_T4();

SND_LR();

START_T0();

fl_RW=1;

return;

}

else if(fl_LAresend)

{

fl_LAresend=0;

SND_LA();

START_T3();

return;

}

if(RX_credNo)

{

memmove(bfrecNL,BFpktR+4,(lmesrec-4));

lgrecNL=lmesrec-4;

fl_recNL=1;

SND_LA();

START_T3();

return;

}

}

if(!secT3&&fl_T3)

{

SND_LA();

START_T3();

return;

}

if((!secT4)&&fl_T4)

{

STOP_T1();

STOP_T3();

STOP_T4();

fl_RW=1;

fl_READY=0;

SND_LR();

START_T0();

return;

}

return;

}

void test_pktNL()

{

switch(bfrecNL[0])

{

case STATUS:

{ if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_recsts=1;

}

}

break;

case ACKP:

{

if((PFIX1=bfrecNL[1]&0x7F)&&(IDENT1a=bfrecNL[2]&0x1F)&&(IDENT1b=bfrecNL[3]))

{

fl_ACKP=1;

}

}

break;

case ACKN:

{

if((PFIX1=bfrecNL[1]&0x7F)&&(IDENT1a=bfrecNL[2]&0x1F)&&(IDENT1b=bfrecNL[3]))

{

fl_ACKN=1;

}

}

break;

case SST: {

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_recsst=1;

memmove(recload,bfrecNL+6,lgrecNL-6);

}

}

break;

case PROGP:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_PROGP=1;

}

}

break;

case PROGN: {

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_PROGN=1;

}

}

break;

case MDM:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_recmdm=1;

}

}

break;

case RPROGP:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_RPROGP=1;

}

}

break;

case RPROGN:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_RPROGN=1;

}

}

break;

case GDISC:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_GDISC=1;

}

}

break;

case FDISC:

{

if((PFIX2=bfrecNL[1]&0x7F)&&(IDENT2a=bfrecNL[2]&0x1F)&&(IDENT2b=bfrecNL[3]))

{

fl_FDISC=1;

}

}

break;

}

}

void makeNLpkt( unsigned char msgtip,unsigned char len)

{

char i=0,j=0;

if(msgtip==RC)

{

bfemNL[i++]=RC;

if(fl_hook) // testez daca on hook

{

if(fl_treq) // flag transmit on request

{

bfemNL[i++]=0x01;

}

else bfemNL[i++]=0x00;

}

else{

if(fl_treq) // flag transmit on request

{

bfemNL[i++]=0x03;

}

else bfemNL[i++]=0x02;

}

}

else {

i++;

bfemNL[i++]=PFIX1;

bfemNL[i++]=IDENT1a;

bfemNL[i++]=IDENT1b;

bfemNL[i++]=0x0;

if(msgtip==SST)

{

bfemNL[0]=SST;

bfemNL[i++]=0x07;

while(len–)

{

bfemNL[i++]=payload[j++];

}

}

if(msgtip==STATUS)

{

bfemNL[0]=STATUS;

bfemNL[i++]=stsmsg;

}

if(msgtip==MDM)

{

bfemNL[0]=MDM;

bfemNL[i++]=0x00;

}

if(msgtip==GDISC)

{

bfemNL[0]=GDISC;

bfemNL[4]=0x07;

i–;

}

if(msgtip==FDISC)

{

bfemNL[0]=FDISC;

bfemNL[4]=0x08;

i–;

}

lenNL=i;

memmove(bfLT+7,bfemNL,lenNL);

fl_NLP=1;

}

}

void NetLayer()

{

if(fl_recNL)

{

fl_recNL=0;

test_pktNL();

}

switch(stateNL)

{

case IDLE:

{

if(fl_recsst)

{

fl_recsst=0;

fl_rsst=1;

fl_case=1;

}

if(fl_recsts)

{

fl_case=1;

}

if(fl_recmdm)

{

fl_recmdm=0;

if(bfrecNL[5]==0x08)

{fl_rctrl=1;

fl_hook=0;

stateNL=INCCW;

}

else {

stateNL=ACTIVE;

fl_case=1;

fl_icall=1;

}

if(fl_sts)

{

fl_sts=0;

stateNL=STATW;

makeNLpkt(STATUS,0);

}

if(fl_sst)

{

fl_sst=0;

stateNL=SEGTRANSW;

makeNLpkt(SST,lgreccons-1);

}

else if(fl_mdm)

{

fl_mdm=0;

stateNL=OUTCW;

makeNLpkt(MDM,0);

}

else if(fl_rctrl)

{

fl_rctrl=0;

makeNLpkt(RC,0);

return;

}

else if(fl_mgmt)

{

fl_mgmt=0;

makeNLpkt(RM,0);

return;

}

if(fl_DLRESET)

{

NL_reset=1;

fl_DLRESET=0;

stateNL=IDLE;

}

}

break;

case OUTCW:

{

if(fl_PROGP)

{

fl_PROGP=0;

stateNL=ACTIVE;

fl_callb=1;

fl_case=1;

}

else if(fl_PROGN)

{

fl_PROGN=0;

stateNL=IDLE;

fl_callp=1;

fl_case=1;

}

}

break;

if(fl_DISCON)

{

fl_DISCON=0;

makeNLpkt(FDISC,0);

stateNL=IDLE;

}

if(fl_DLRESET)

{

NL_reset=1;

fl_DLRESET=0;

stateNL=IDLE;

}

}

break;

case INCCW:{

if(fl_RPROGP)

{

fl_RPROGP=0;

stateNL=ACTIVE;

fl_case=1;

fl_icall=1;

}

else if(fl_RPROGN)

{

fl_RPROGN=0;

stateNL=IDLE;

}

else if(fl_FDISC)

{

fl_FDISC=0;

stateNL=IDLE;

fl_rctrl=1;

fl_hook=1;

}

if(fl_rctrl)

{

fl_rctrl=0;

makeNLpkt(RC,0);

}

if(fl_DLRESET)

{

NL_reset=1;

fl_DLRESET=0;

stateNL=IDLE;

}

}

break;

case ACTIVE:{

if(fl_GDISC)

{

fl_GDISC=0;

stateNL=IDLE;

fl_rctrl=1;

fl_hook=1;

fl_case=1;

fl_gdsc=1;

}

else if(fl_FDISC)

{

fl_rctrl=1;

fl_hook=1;

}

if(fl_DISCON)

{

fl_DISCON=0;

makeNLpkt(GDISC,0);

stateNL=IDLE;

}

if(fl_rctrl)

{

fl_rctrl=0;

makeNLpkt(RC,0);

}

if(fl_DLRESET)

{

NL_reset=1;

stateNL=IDLE;

fl_DLRESET=0;

}

}

break;

case STATW:{

if(fl_ACKP)

{

stateNL=IDLE;

fl_ACKP=0;

fl_b=1;

fl_case=1;

}

if(fl_ACKN)

{

stateNL=IDLE;

fl_ACKN=0;

fl_p=1;

fl_case=1;

}

}

break;

case SEGTRANSW:{

if(fl_ACKP)

{

stateNL=IDLE;

fl_ACKP=0;

fl_sstb=1;

fl_case=1;

}

if(fl_ACKN)

{

stateNL=IDLE;

fl_ACKN=0;

fl_sstp=1;

fl_case=1;

}

if(fl_FDISC)

{

fl_FDISC=0;

stateNL=IDLE;

}

if(fl_DISCON)

{

fl_DISCON=0;

makeNLpkt(FDISC,0);

stateNL=IDLE;

}

if(fl_DLRESET)

{

NL_reset=1;

stateNL=IDLE;

fl_DLRESET=0;

}

}

break;

}

}

void main(void)

{

init_resurse();

init_var();

fl_PON=1;

fl_RW=1;

sprintf((char*)bfemcons, "\n\r Modem FSK pentru comunicatii de tip MPT1327\n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, " Va rugam asteptati ridicarea legaturii de date \n\r");

decl_em_cons();

while(fl_emcons);

while(1)

{

if(fRecOctRd)

{

getoct();

REC_pkt_R();

if(fl_pkt_R)

{

fl_pkt_R=0;

test_pkt_R();

if(fl_LW) LINK_WAIT();

if(fl_RW) RESET_WAIT();

if(fl_READY) STATE_READY();

}

}

else if(fl_RW) RESET_WAIT();

if(fl_READY) STATE_READY();

if(fl_READY) NetLayer();

if(fl_case) meniu();

}

}

void meniu()

{

unsigned char *ptloc;

fl_case=0;

switch(afis)

{

case 1: {

sprintf((char*)bfemcons, "Legatura de date ridicata\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

break;

case 2: {

sprintf((char*)bfemcons, "Pentru mesaj de tip STATUS apasati 1 si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, "Pentru mesaj de tip SST apasati 2 si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, "Pentru un apel de voce apasati 3 si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

afis=3;

}

break;

case 3: {

if(flag_rec_cons)

{

flag_rec_cons=0;

if(lgreccons==2)

{

if((bfreccons[0]-0x30)==1)

{

sprintf((char*)bfemcons, "Introduceti un numar intre 0 si 31 si apasati ENTER \n\r");

decl_em_cons();

while(fl_emcons);

afis=4;

fl_case=1;

}

else if((bfreccons[0]-0x30)==2)

{

sprintf((char*)bfemcons, "Introduceti un mesaj de maxim 20 de caractere si ENTER \n\r");

decl_em_cons();

while(fl_emcons);

afis=6;

fl_case=1;

}

else if((bfreccons[0]-0x30)==3)

{

fl_mdm=1;

afis=8;

}

else

{

sprintf((char*)bfemcons, "\n\rNumar invalid\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

}

if(fl_recsts)

{

sprintf((char*)bfemcons, "Am primit un mesaj de status cu numarul %d\n\r",(int)bfrecNL[5]);

decl_em_cons();

while(fl_emcons);

fl_recsts=0;

}

if(fl_rsst)

{

fl_rsst=0;

sprintf((char*)bfemcons, "Am primit un mesaj SST:\n\r");

decl_em_cons();

while(fl_emcons);

ptloc=bfemcons;

sprintf((char*)ptloc, "M: ");

ptloc+=3;

for(i=0;(i<lgrecNL-6);i++)

{

if((*ptloc=recload[i])!=0x00)

{

ptloc++;

}

else i=lgrecNL-6;

}

*(ptloc++) = 0x0d;

*(ptloc++) = 0x0a;

*ptloc = 0x0;

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

if(fl_icall)

{

fl_icall=0;

sprintf((char*)bfemcons, "Apel in desfasurare ! Pentru deconectare apasati 1 si ENTER\n\r");

decl_em_cons();

while(fl_emcons);

afis=9;

}

}

break;

case 4:{

if(flag_rec_cons)

{

flag_rec_cons=0;

if(lgreccons==2)

{

stsmsg=bfreccons[0]-0x30;

fl_sts=1;

afis=5;

}

else if(lgreccons==3)

{

stsmsg=(bfreccons[0]-0x30)*10;

stsmsg=stsmsg+(bfreccons[1]-0x30);

if(stsmsg<32)

{

fl_sts=1;

afis=5;

}

else

{

sprintf((char*)bfemcons, "\n\rNumar invalid,introduceti un numar mai mic decat 31 si ENTER\n\r");

decl_em_cons();

while(fl_emcons);

}

}

else

{

sprintf((char*)bfemcons, "\n\rNumar invalid\n\r");

decl_em_cons();

while(fl_emcons);

}

}

}

break;

case 5: {

if(fl_b)

{

fl_b=0;

sprintf((char*)bfemcons, "Transactie reusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

else if(fl_p)

{

fl_p=0;

sprintf((char*)bfemcons, "Tranzactie nereusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

break;

case 6:

{

if(flag_rec_cons)

{

fl_sst=1;

memmove(payload,bfreccons,lgreccons-1);

afis=7;

}

}break;

case 7 : {

if(fl_sstb)

{

fl_sstb=0;

sprintf((char*)bfemcons, "Transactie reusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

else if(fl_sstp)

{

fl_sstp=0;

sprintf((char*)bfemcons, "Tranzactie nereusita\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

break;

case 8: {

if(fl_callb)

{

fl_sstb=0;

sprintf((char*)bfemcons, "Apel reusit\n\r");

decl_em_cons();

while(fl_emcons);

sprintf((char*)bfemcons, "Pentru deconectare apasati 1 si tasta ENTER\n\r");

decl_em_cons();

while(fl_emcons);

afis=9;

fl_case=1;

}

else if(fl_callp)

{

fl_sstp=0;

sprintf((char*)bfemcons, "Apel esuat\n\r");

decl_em_cons();

while(fl_emcons);

afis=2;

fl_case=1;

}

}

break;

case 9: {

if(lgreccons==2)

{

if((bfreccons[0]-0x30)==1)

{

fl_DISCON=1;

afis=2;

fl_case=1;

sprintf((char*)bfemcons, "Apel terminat\n\r");

decl_em_cons();

while(fl_emcons);

}

}

if(fl_gdsc)

{

fl_gdsc=0;

afis=2;

fl_case=1;

sprintf((char*)bfemcons, "Apel terminat\n\r");

decl_em_cons();

while(fl_emcons);

}

}break;

}

}

SALTURI.ASM

PUBLIC initasm, armezCM1

PUBLIC endemr, fRecOctRd

PUBLIC R0_2, R1_2, R2_2, R3_2, R4_2, R5_2, R6_2, R7_2, bfOctRcSt

EXTRN CODE (contor)

EXTRN CODE (cons_ser)

CTI0 equ 0c8h CTI3 equ 0cbh CMI0 equ 0cch CMI1 equ 0cdh ECM0 equ 0ech ECM1 equ 0edh ECT0 equ 0e8h CTCON equ 0ebh

CTH0 equ 0cch CTL0 equ 0ach

CTH3 equ 0cfh CTL3 equ 0afh

CMH0 equ 0c9h

CML0 equ 0a9h

CMH1 equ 0cah

CML1 equ 0aah

tm2con equ 0eah

P1_0 equ 090h P4_0 equ 0c0h

DRBIT equ 0aeh DRSTART equ 0d6h HFBIT equ 057h

;––––––––––––––

BSEG AT 0

endemr: dbit 1

fRecOctRd:dbit 1

DSEG AT 010h

R0_2: ds 1

R1_2: ds 1

R2_2: ds 1

R3_2: ds 1

R4_2: ds 1

R5_2: ds 1

R6_2: ds 1

R7_2: ds 1

DSEG AT 040h

bfOctRcSt: ds 1

CSEG AT 8000h LJMP blkx

CSEG AT 800bh

LJMP contor

CSEG AT 8023h

LJMP cons_ser

CSEG AT 8033h LJMP START_RxD_statie

CSEG AT 805bh LJMP RxD_statie

CSEG AT 8063h LJMP TxD_statie

;––––––––––––––––-

CSEG AT 807bh

blkx:

MOV DPTR,#0fb00h

MOV R7, #0

MOV R6, #03h

CLR A

XDATALOOP:

MOVX @DPTR,A

INC DPTR

DJNZ R7, XDATALOOP

DJNZ R6, XDATALOOP

LJMP 8200h

initasm:

push psw

clr fRecOctRd

setb endemr setb 0d4h clr 0d3h

mov r4, #8

mov r2, #9

pop psw

mov ctcon, #082h

mov tm2con, #01h

clr CTI0

setb ect0

clr CMI1

clr ECM1

ret

;––––––––––––––––––––––––––

PUBLIC sdebug

sdebug:

clr ea

push dpl

push dph

push acc

mov a, r0

mov dptr, #0f900h

movx @dptr, a inc dptr

mov r0, #1

bsav: mov a, @r0

movx @dptr, a

inc dptr

inc r0

cjne r0, #0, bsav

pop acc

movx @dptr, a inc dptr

pop acc movx @dptr, a

inc dptr

pop acc movx @dptr, a

mov sp, #0

ljmp 0

;

;–––––––––––––––––––––––––––-

START_RxD_statie:

push acc push psw

clr CTI0 clr ECT0 mov a, CTL0

add a, #DRSTART

mov CML0, a

mov a, CTH0

addc a, #0

mov CMH0, a

pop psw

pop acc

clr CMI0 setb ECM0 reti

RxD_statie:

push acc push psw

clr CMI0 setb 0d4h clr 0d3h

cjne r4, #0, mairec

mov r4, #8 mov bfOctRcSt, r5 setb fRecOctRd

clr ECM0 clr CTI0

setb ECT0 sjmp exitRcRd

mairec:

mov a, r5

rr a

mov c, P1_0

mov 0e7h, c

mov r5, a

mov a, CML0

add a, #DRBIT

mov CML0, a

mov a, CMH0

addc a, #0

mov CMH0, a

dec r4

exitRcRd:

pop psw

pop acc

reti

armezCM1: mov a, CTL3

add a, #DRBIT

mov CML1, a

mov a, CTH3

addc a, #0

mov CMH1, a

clr CMI1 setb ECM1 ret

TxD_statie: push acc push psw

clr CMI1

setb 0d4h clr 0d3h

cjne r2, #0, maiem

mov r2, #9

clr ECM1 setb endemr

sjmp exitem

maiem:

mov a, r3

setb c rrc a mov P4_0, c

mov r3, a

mov a, CML1

add a, #DRBIT

mov CML1, a

mov a, CMH1

addc a, #0

mov CMH1, a

dec r2

exitem:

pop psw

pop acc

reti

;

; End of salturi.asm

END

; File Name: STARTUP.A51 – (c) Copyright Franklin Software, Inc. 1989

;

;––––––––––––––––––––––––––

;

; STARTUP.A51: This code is executed after processor reset.

;

; To ASSEMBLE this file use A51 (ver. 4.3 & up), with the following

; invocation:

;

; A51 STARTUP.A51

;

; To LINK the modified STARTUP.OBJ file into your application use the

; following L51 (ver. 2.4 & up) invocation:

;

; L51 STARTUP.OBJ, <your object file list> <controls>

;

;––––––––––––––––––––––––––

;

;

; User-defined Power-On Initialization of Memory

;

; With the following EQU statements the initialization of memory

; at processor reset can be defined:

;

; Note: the absolute start-address of IDATA memory is always 0

IDATALEN EQU 100H ; the length of IDATA memory in bytes.

;

XDATASTART EQU 0FB00H ; the absolute start-address of XDATA memory

XDATALEN EQU 0H ; the length of XDATA memory in bytes.

;

PDATASTART EQU 0H ; the absolute start-address of PDATA memory

PDATALEN EQU 0H ; the length of PDATA memory in bytes.

;

; Notes: The IDATA space overlaps physically the DATA and BIT areas of the

; 8051 CPU. At a minimum, the memory space occupied from the C-51

; run-time routines must be set to zero.

;

;––––––––––––––––––––––––––

;

;

NAME ?C_STARTUP

?C_C51STARTUP SEGMENT CODE

?STACK SEGMENT IDATA

RSEG ?STACK

STACK: DS 1

EXTRN CODE (?C_START)

PUBLIC ?C_STARTUP

?C_STARTUP: LJMP STARTUP1

RSEG ?C_C51STARTUP

STARTUP1:

;

; Setup for and execute the IDATALEN init sequence

IF IDATALEN <> 0

MOV R0,#IDATALEN – 1

CLR A

IDATALOOP: MOV @R0,A

DJNZ R0,IDATALOOP

ENDIF

;

; Setup for and execute the XDATA init sequence

XDATALEN EQU 0H

IF XDATALEN <> 0

MOV DPTR,#XDATASTART

MOV R7,#LOW (XDATALEN)

IF (LOW (XDATALEN)) <> 0

MOV R6,#(HIGH XDATALEN) +1

ELSE

MOV R6,#HIGH (XDATALEN)

ENDIF

CLR A

XDATALOOP: MOVX @DPTR,A

INC DPTR

DJNZ R7,XDATALOOP

DJNZ R6,XDATALOOP

ENDIF

;

; Setup for and execute the PDATA init. sequences.

IF PDATALEN <> 0

MOV R0,#PDATASTART

MOV R7,LOW (PDATALEN)

CLR A

PDATALOOP: MOVX @R0,A

INC R0

DJNZ R7,PDATALOOP

ENDIF

;

; Install the stack value and jump through the startup location

MOV SP,#LOW (STACK-1)

LJMP ?C_START

END

;

; End of STARTUP.A51

Similar Posts