Está en la página 1de 808

FACULTAD DE INGENIERA

DE LA
UNIVERSIDAD DE BUENOS AIRES

Tesis de Grado
en
Ingeniera Informtica

Diseo de un Sistema de Intercambio de Informacin


para Dispositivos Intercomunicados por Redes PLC
de Automviles

Tesista: Sr. Fernando Ariel Beunza


Director: Ing. Jorge Alberto

SEPTIEMBRE 2011

Tesis de Grado en Ingeniera Informtica

Facultad de Ingeniera
Universidad de Buenos Aires

Diseo de un Sistema de Intercambio de Informacin


para Dispositivos Intercomunicados por Redes PLC
de Automviles

Sr. Fernando Ariel Beunza


Tesista

Ing. Jorge Alberto


Director

SEPTIEMBRE 2011

Tesis de Grado en Ingeniera Informtica

Resumen
Desde hace aos para mejorar las prestaciones de dispositivos que cada vez presentan ms
cantidad de componentes electrnicos las interconexiones dedicadas estn siendo reemplazadas por
buses de datos. Un mbito en donde esto sucede es en la industria automotriz, en donde los
vehculos actuales trabajan con redes como CAN [Bosch91], J1850 [SAE94], entre otras; en donde
los dispositivos electrnicos comparten informacin por medio de un nico cableado para datos.
En los ltimos aos ha surgido la idea de combinar en un nico cableado la energa de
alimentacin y la informacin, lo que se conoce como PLC. Los avances, respecto a la tecnologa
PLC, se encuentran destinados ms que nada a infraestructura edilicia, existiendo una variedad de
estndares de los cuales muchos no implementan todas las capas del modelo OSI [ISO7498-1].
Respecto a los avances de sta tecnologa en el ambiente automotriz, se han desarrollado trabajos
que slo tratan las capas fsica y enlace del modelo OSI.
La idea del presente trabajo es tomar como punto de partida los antecedentes mencionados y
construir un sistema que permita compartir informacin encapsulando toda la complejidad
involucrada en el proceso de comunicacin y brindando una interfaz que sea simple de utilizar para
los dispositivos clientes del sistema.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

ndice
1. Introduccin....................................................................................................................................15
2. Antecedentes...................................................................................................................................17
2.1. Tecnologa PLC.......................................................................................................................17
2.1.1. X10...................................................................................................................................18
2.1.1.1. Mtodo de transmisin..............................................................................................18
2.1.1.2. Estructura de mensaje................................................................................................19
2.1.1.3. Esquema de direccionamiento...................................................................................19
2.1.2.4. Funciones...................................................................................................................20
2.1.2. CEBus...............................................................................................................................21
2.1.2.1. Mtodo de transmisin..............................................................................................21
2.1.2.2. Estructura de paquete.................................................................................................22
2.1.2.3. Esquema de direccionamiento...................................................................................22
2.1.2.4. Lenguaje de aplicacin..............................................................................................23
2.1.3. CENELEC 50065.............................................................................................................25
2.1.4. UPB..................................................................................................................................26
2.1.4.1. Mtodo de transmisin..............................................................................................27
2.1.4.2. Estructura de paquete.................................................................................................28
2.1.4.3. Esquema de direccionamiento...................................................................................29
2.1.4.4. Comandos..................................................................................................................30
2.1.5. LonWorks.........................................................................................................................31
2.1.5.1. Protocolo CNP...........................................................................................................31
2.1.5.2. Capa fsica.................................................................................................................32
2.1.5.3. Capa de enlace...........................................................................................................33
2.1.5.4. Capa de red................................................................................................................34
2.1.5.5. Capa de transporte.....................................................................................................35
2.1.5.6. Capa de sesin...........................................................................................................36
2.1.5.7. Capa de presentacin.................................................................................................37
2.1.5.8. Capa de aplicacin.....................................................................................................38
2.1.6. HomePlug.........................................................................................................................39
2.1.6.1. HomePlug 1.0............................................................................................................39
2.1.6.2. HomePlug AV...........................................................................................................42
2.1.6.3. HomePlug Green PHY..............................................................................................44
2.2. Redes en automviles..............................................................................................................46
2.2.1. CAN..................................................................................................................................46
2.2.1.1. Modelo de capas........................................................................................................46
2.2.1.2. Capa fsica.................................................................................................................47
2.2.1.3. Capa de enlace...........................................................................................................49
2.2.2. J1850.................................................................................................................................52
2.2.2.1. Modelo de capas........................................................................................................52
2.2.2.2. Capa fsica.................................................................................................................54
2.2.2.3. Capa de enlace...........................................................................................................55
2.2.2.4. Capa de aplicacin.....................................................................................................56
2.2.3. OSEK/VDX......................................................................................................................57
2.2.3.1. Arquitectura...............................................................................................................57
2.2.3.2. Implementacin.........................................................................................................58
2.2.4. LIN....................................................................................................................................58
FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


2.2.4.1. Capa fsica.................................................................................................................59
2.2.4.2. Capa de enlace...........................................................................................................60
2.2.5. D2B...................................................................................................................................61
2.2.5.1. Medio fsico...............................................................................................................62
2.2.5.2. Control de acceso al medio........................................................................................63
2.2.5.3. Estructura de paquete.................................................................................................63
2.2.6. MOST...............................................................................................................................64
2.2.6.1. Modelo de dispositivo...............................................................................................64
2.2.6.2. Capa fsica.................................................................................................................64
2.2.6.3. Capa de red................................................................................................................65
2.2.6.4. Capa de aplicacin.....................................................................................................67
2.2.7. FlexRay.............................................................................................................................68
2.2.7.1. Capa fsica.................................................................................................................68
2.2.7.2. Capa lgica................................................................................................................71
2.3. Redes PLC en automviles......................................................................................................73
2.3.1. DC-BUS............................................................................................................................73
2.3.1.1. mbitos de aplicacin...............................................................................................73
2.3.1.2. Medio de comunicacin.............................................................................................74
2.3.1.3. Implementacin.........................................................................................................75
2.3.2. Trabajos sobre PLC en la industria automotriz................................................................75
2.3.2.1. Canal de comunicaciones..........................................................................................76
2.3.2.2. Mtodo de acoplamiento...........................................................................................79
2.3.2.3. Tcnica de modulacin..............................................................................................80
2.3.2.4. Tcnicas modificadas................................................................................................83
3. Descripcin del problema...............................................................................................................85
3.1. Alcance de las soluciones existentes.......................................................................................85
3.1.1. Comunicaciones PLC.......................................................................................................85
3.1.2. Redes de automviles.......................................................................................................86
3.1.3. PLC en automviles..........................................................................................................87
3.2. Requerimientos para la propuesta del presente trabajo...........................................................88
4. Solucin propuesta.........................................................................................................................91
4.1. Capa fsica...............................................................................................................................91
4.1.1. Mtodo de acoplamiento..................................................................................................91
4.1.2. Tcnica de modulacin.....................................................................................................93
4.1.3. Modem PLC.....................................................................................................................94
4.1.4. Implementacin del sistema de comunicaciones..............................................................95
4.1.4.1. Implementacin fsica................................................................................................95
4.1.4.2. Implementacin lgica...............................................................................................97
4.1.5. Estructura de tramas.......................................................................................................102
4.1.6. Funciones adicionales.....................................................................................................102
4.1.7. Primitivas de manejo de la capa fsica............................................................................103
4.2. Capa de enlace.......................................................................................................................105
4.2.1. Subcapa de control de acceso al medio..........................................................................106
4.2.1.1. Caractersticas del medio.........................................................................................106
4.2.1.2. Mtodo de acceso al medio.....................................................................................106
4.2.1.3. Fragmentacin.........................................................................................................109
4.2.1.4. Esquema de direccionamiento.................................................................................111
4.2.1.5. Estructura de tramas................................................................................................111
4.2.1.6. Control de errores....................................................................................................112
8

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


4.2.1.7. Filtrado de tramas....................................................................................................113
4.2.1.8. Primitivas de manejo de la subcapa de control de acceso al medio........................114
4.2.2. Subcapa de control de lgica de enlace..........................................................................115
4.2.2.1. Multiplexado de protocolos.....................................................................................115
4.2.2.2. Control de flujo de datos.........................................................................................116
4.2.2.3. Estructura de paquetes.............................................................................................117
4.2.2.4. Control de errores....................................................................................................117
4.2.2.5. Primitivas de manejo de la subcapa de control de lgica de enlace........................117
4.2.3. Protocolo de resolucin de direcciones..........................................................................119
4.2.3.1. Principio de funcionamiento....................................................................................119
4.2.3.2. Estructura de mensajes............................................................................................120
4.2.3.3. Primitivas de manejo del protocolo de resolucin de direcciones...........................120
4.2.4. Primitivas de manejo de la capa de enlace.....................................................................121
4.3. Capa de red............................................................................................................................123
4.3.1. Modelo de comunicaciones............................................................................................123
4.3.2. Esquema de direccionamiento........................................................................................124
4.3.3. Estructura de mensajes...................................................................................................125
4.3.4. Primitivas de manejo de la capa de red..........................................................................126
4.4. Capa de transporte.................................................................................................................128
4.4.1. Comunicacin por grupos de difusin............................................................................128
4.4.2. Esquema de identificacin..............................................................................................130
4.4.3. Mensajes.........................................................................................................................130
4.4.4. Primitivas de manejo de la capa de transporte................................................................131
4.5. Capa de sesin.......................................................................................................................132
4.5.1. Establecimiento de sesiones...........................................................................................133
4.5.2. Control del dilogo.........................................................................................................134
4.5.3. Grupos de difusin..........................................................................................................134
4.5.4. Estructura de los mensajes..............................................................................................136
4.5.5. Primitivas de manejo de la capa de sesin.....................................................................136
4.6. Capa de presentacin.............................................................................................................138
4.6.1. Implementacin de datos estructurados..........................................................................138
4.6.2. Esquema multiplataforma...............................................................................................140
4.6.3. Estructura de los mensajes..............................................................................................141
4.6.4. Primitivas de manejo de la capa de presentacin...........................................................141
4.7. Capa de aplicacin.................................................................................................................143
4.7.1. Servicio de mensajera....................................................................................................144
4.7.2. Esquema multiplataforma...............................................................................................145
4.7.3. Primitivas de manejo de la capa de aplicacin...............................................................145
4.7.4. Interfaz C++....................................................................................................................148
4.7.5. Biblioteca de bloques Simulink......................................................................................150
5. Evaluacin de la solucin propuesta............................................................................................151
5.1. Comparacin con redes PLC para automviles.....................................................................151
5.1.1. Evaluacin del mdulo analgico...................................................................................151
5.1.2. Evaluacin del mdulo de procesamiento de seales.....................................................164
5.1.3. Evaluacin del canal de comunicacin...........................................................................168
5.1.4. Comparacin con DC-BUS............................................................................................178
5.1.5. Comparacin con los trabajos sobre PLC en la industria automotriz.............................179
5.2. Comparacin con redes existentes para automviles............................................................180
5.2.1. Comparacin con CAN..................................................................................................180
FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


5.2.2. Comparacin con J1850.................................................................................................181
5.2.3. Comparacin con OSEK/VDX.......................................................................................182
5.2.4. Comparacin con LIN....................................................................................................182
5.2.5. Comparacin con D2B...................................................................................................183
5.2.6. Comparacin con MOST................................................................................................184
5.2.7. Comparacin con FlexRay.............................................................................................184
5.3. Caractersticas particulares de la solucin propuesta............................................................185
5.4. Desempeo de la solucin propuesta.....................................................................................186
6. Conclusiones.................................................................................................................................189
6.1. Anlisis de resultados............................................................................................................189
6.2. Trabajos futuros.....................................................................................................................191
7. Referencias...................................................................................................................................193
Apndice A: Implementacin del hardware del modem PLC..........................................................199
A.1. Organizacin del hardware...................................................................................................199
A.2. Implementacin del mdulo analgico.................................................................................201
A.3. Implementacin del mdulo de procesamiento de seales...................................................207
A.4. Implementacin del mdulo de procesamiento....................................................................214
A.5. Implementacin del mdulo de adaptacin RS232..............................................................219
Apndice B: Simulacin del hardware del modem PLC..................................................................221
B.1. Organizacin del hardware...................................................................................................221
B.2. Implementacin del mdulo analgico.................................................................................221
B.3. Implementacin del mdulo de procesamiento de seales...................................................228
Apndice C: Cdigo fuente..............................................................................................................239
C.1. Organizacin del cdigo fuente............................................................................................239
C.2. Especificacin del cdigo fuente de las bibliotecas de uso del modem PLC (plataforma
AT89X5X)....................................................................................................................................241
C.2.1. Archivo config.h............................................................................................................242
C.2.2. Archivo modplcap.h.......................................................................................................243
C.2.3. Archivo modplcap__init.c..............................................................................................247
C.2.4. Archivo modplcap_release.c..........................................................................................248
C.2.5. Archivo modplcap_publish.c.........................................................................................248
C.2.6. Archivo modplcap_subscribe.c......................................................................................249
C.2.7. Archivo modplcap_leave.c............................................................................................250
C.2.8. Archivo modplcap_newmsg.c........................................................................................250
C.2.9. Archivo modplcap_copymsg.c.......................................................................................251
C.2.10. Archivo modplcap_putfield.c......................................................................................252
C.2.11. Archivo modplcap_sendmsg.c.....................................................................................252
C.2.12. Archivo modplcap_receivemsg.c.................................................................................253
C.2.13. Archivo modplcap_getfield.c.......................................................................................254
C.2.14. Archivo modplcap_getgrpid.c......................................................................................255
C.2.15. Archivo modplcap_getmsgid.c....................................................................................255
C.2.16. Archivo modplcap_destroymsg.c.................................................................................256
C.2.17. Archivo modplcap_setbuffer.c.....................................................................................257
C.2.18. Archivo modplcap_notify.c.........................................................................................257
C.2.19. Archivo modplcap_poll.c.............................................................................................259
C.2.20. Archivo modplcap_status.c..........................................................................................260
C.2.21. Archivo modplcpp.h....................................................................................................260
C.2.22. Archivo modplcpp__init.c...........................................................................................265
C.2.23. Archivo modplcpp_release.c........................................................................................265
10

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


C.2.24. Archivo modplcpp_publish.c.......................................................................................266
C.2.25. Archivo modplcpp_subscribe.c....................................................................................267
C.2.26. Archivo modplcpp_leave.c..........................................................................................267
C.2.27. Archivo modplcpp_newmsg.c.....................................................................................268
C.2.28. Archivo modplcpp_copymsg.c....................................................................................269
C.2.29. Archivo modplcpp_putfield.c......................................................................................270
C.2.30. Archivo modplcpp_sendmsg.c.....................................................................................272
C.2.31. Archivo modplcpp_receivemsg.c.................................................................................272
C.2.32. Archivo modplcpp_getfield.c......................................................................................273
C.2.33. Archivo modplcpp_getgrpid.c.....................................................................................275
C.2.34. Archivo modplcpp_destroymsg.c................................................................................276
C.2.35. Archivo modplcpp_setbuffer.c....................................................................................276
C.2.36. Archivo modplcpp_notify.c.........................................................................................277
C.2.37. Archivo modplcpp_poll.c............................................................................................279
C.2.38. Archivo modplcpp_status.c..........................................................................................279
C.2.39. Archivo modplcsp.h.....................................................................................................280
C.2.40. Archivo modplcsp__init.c............................................................................................283
C.2.41. Archivo modplcsp_release.c........................................................................................285
C.2.42. Archivo modplcsp_publish.c.......................................................................................286
C.2.43. Archivo modplcsp_subscribe.c....................................................................................287
C.2.44. Archivo modplcsp_leave.c...........................................................................................287
C.2.45. Archivo modplcsp_send.c............................................................................................288
C.2.46. Archivo modplcsp_receive.c........................................................................................290
C.2.47. Archivo modplcsp_setbuffer.c.....................................................................................291
C.2.48. Archivo modplcsp_notify.c..........................................................................................292
C.2.49. Archivo modplcsp_poll.c.............................................................................................293
C.2.50. Archivo modplcsp_status.c..........................................................................................294
C.2.51. Archivo modplcsp_getpayloadsize.c...........................................................................295
C.2.52. Archivo __modplcsp_getbyte__.c...............................................................................295
C.2.53. Archivo __modplcsp_getresult__.c.............................................................................296
C.2.54. Archivo __modplcsp_putbyte__.c...............................................................................297
C.2.55. Archivo __modplcsp_putcmd__.c...............................................................................298
C.2.56. Archivo __modplcsp_puthex__.c................................................................................299
C.2.57. Archivo __modplcsp_putint__.c..................................................................................299
C.2.58. Archivo __modplcsp_sendcmd0__.c...........................................................................300
C.2.59. Archivo __modplcsp_sendcmd1__.c...........................................................................301
C.2.60. Archivo __modplcsp_waitchar__.c.............................................................................302
C.2.61. Archivo serial.h............................................................................................................302
C.2.62. Archivo serial.c............................................................................................................303
C.3. Especificacin del cdigo fuente de las bibliotecas de uso del modem PLC (plataforma
Windows).....................................................................................................................................304
C.3.1. Interfaz capa de aplicacin modplcap.dll.......................................................................305
C.3.1.1. Archivo config.h.....................................................................................................305
C.3.1.2. Archivo modplcsp.h................................................................................................306
C.3.1.3. Archivo modplcsp.c................................................................................................307
C.3.1.4. Archivo modplcpp.h...............................................................................................316
C.3.1.5. Archivo modplcpp.c................................................................................................319
C.3.1.6. Archivo modplcap.h................................................................................................327
C.3.1.7. Archivo modplcap.c................................................................................................331
FernandoArielBeunza79156

11

Tesis de Grado en Ingeniera Informtica


C.3.2. Interfaz capa de enlace modplcdl.dll..............................................................................337
C.3.2.1. Archivo config.h.....................................................................................................337
C.3.2.2. Archivo modplcdl.h................................................................................................337
C.3.2.3. Archivo modplcdl.c.................................................................................................341
C.3.3. Interfaz capa fsica modplcphy.dll.................................................................................354
C.3.3.1. Archivo config.h.....................................................................................................354
C.3.3.2. Archivo modplcphy.h..............................................................................................355
C.3.3.3. Archivo modplcphy.c..............................................................................................358
C.3.4. Driver del Modem PLC modem_driver.exe..................................................................369
C.3.4.1. Archivo config.h.....................................................................................................370
C.3.4.2. Archivo serial.h.......................................................................................................372
C.3.4.3. Archivo serial.c.......................................................................................................373
C.3.4.4. Archivo modplc.h...................................................................................................378
C.3.4.5. Archivo modplc.c....................................................................................................381
C.3.4.6. Archivo modsp.h.....................................................................................................399
C.3.4.7. Archivo modsp.c.....................................................................................................401
C.3.4.8. Archivo moddl.h.....................................................................................................407
C.3.4.9. Archivo moddl.c.....................................................................................................410
C.3.4.10. Archivo modphy.h................................................................................................418
C.3.4.11. Archivo modphy.c.................................................................................................420
C.3.4.12. Archivo modrv.h...................................................................................................427
C.3.4.13. Archivo moddrv.c.................................................................................................428
C.3.4.14. Archivo modem_driver.c......................................................................................443
C.4. Especificacin del cdigo fuente de las bibliotecas de uso del modem PLC (plataforma
Linux)...........................................................................................................................................444
C.4.1. Interfaz capa de aplicacin modplcap.so.......................................................................444
C.4.1.1. Archivo config.h.....................................................................................................445
C.4.1.2. Archivo modplcsp.h................................................................................................445
C.4.1.3. Archivo modplcsp.c................................................................................................447
C.4.1.4. Archivo modplcpp.h...............................................................................................456
C.4.1.5. Archivo modplcpp.c................................................................................................459
C.4.1.6. Archivo modplcap.h................................................................................................467
C.4.1.7. Archivo modplcap.c................................................................................................470
C.4.2. Interfaz capa de enlace modplcdl.so..............................................................................475
C.4.2.1. Archivo config.h.....................................................................................................476
C.4.2.2. Archivo modplcdl.h................................................................................................476
C.4.2.3. Archivo modplcdl.c.................................................................................................478
C.4.3. Interfaz capa fsica modplcphy.so..................................................................................492
C.4.3.1. Archivo config.h.....................................................................................................492
C.4.3.2. Archivo modplcphy.h..............................................................................................492
C.4.3.3. Archivo modplcphy.c..............................................................................................494
C.4.4. Driver del Modem PLC modem_driver.........................................................................506
C.4.4.1. Archivo config.h.....................................................................................................507
C.4.4.2. Archivo serial.h.......................................................................................................509
C.4.4.3. Archivo serial.c.......................................................................................................510
C.4.4.4. Archivo modplc.h...................................................................................................512
C.4.4.5. Archivo modplc.c....................................................................................................516
C.4.4.6. Archivo modsp.h.....................................................................................................534
C.4.4.7. Archivo modsp.c.....................................................................................................536
12

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


C.4.4.8. Archivo moddl.h.....................................................................................................542
C.4.4.9. Archivo moddl.c.....................................................................................................544
C.4.4.10. Archivo modphy.h................................................................................................553
C.4.4.11. Archivo modphy.c.................................................................................................555
C.4.4.12. Archivo modrv.h...................................................................................................562
C.4.4.13. Archivo moddrv.c.................................................................................................563
C.4.4.14. Archivo modem_driver.c......................................................................................580
C.5. Especificacin del cdigo fuente del firmware del modem PLC..........................................582
C.5.1. Archivo config.h............................................................................................................583
C.5.2. Archivo common.h........................................................................................................587
C.5.3. Archivo common.c.........................................................................................................587
C.5.4. Archivo serial.h..............................................................................................................588
C.5.5. Archivo serial.c..............................................................................................................588
C.5.6. Archivo phy.h.................................................................................................................588
C.5.7. Archivo phy.c.................................................................................................................590
C.5.8. Archivo mac.h................................................................................................................599
C.5.9. Archivo mac.c................................................................................................................601
C.5.10. Archivo llc.h................................................................................................................611
C.5.11. Archivo llc.c.................................................................................................................612
C.5.12. Archivo arp.h...............................................................................................................616
C.5.13. Archivo arp.c................................................................................................................617
C.5.14. Archivo dl.h.................................................................................................................621
C.5.15. Archivo dl.c..................................................................................................................623
C.5.16. Archivo net.h................................................................................................................625
C.5.17. Archivo net.c................................................................................................................626
C.5.18. Archivo tp.h.................................................................................................................633
C.5.19. Archivo tp.c..................................................................................................................635
C.5.20. Archivo sp.h.................................................................................................................640
C.5.21. Archivo sp.c.................................................................................................................642
C.5.22. Archivo modem.c.........................................................................................................645
C.6. Especificacin del cdigo fuente del firmware procesador de seales.................................655
C.6.1. Archivo config.h............................................................................................................655
C.6.2. Archivo phy.h.................................................................................................................656
C.6.3. Archivo phy.c.................................................................................................................657
C.6.4. Archivo main.c...............................................................................................................695
C.7. Especificacin del cdigo fuente del firmware cargador......................................................695
C.7.1. Archivo config.h............................................................................................................696
C.7.2. Archivo common.h........................................................................................................697
C.7.3. Archivo common.c.........................................................................................................697
C.7.4. Archivo serial.h..............................................................................................................697
C.7.5. Archivo serial.c..............................................................................................................697
C.7.6. Archivo interrupts.h.......................................................................................................697
C.7.7. Archivo interrupts.c.......................................................................................................698
C.7.8. Archivo memory.h.........................................................................................................699
C.7.9. Archivo memory.c.........................................................................................................700
C.7.10. Archivo boot.c..............................................................................................................706
C.8. Especificacin del cdigo fuente comn utilizado por el firmware del modem PLC y el
firmware cargador.........................................................................................................................707
C.8.1. Archivo common.h........................................................................................................708
FernandoArielBeunza79156

13

Tesis de Grado en Ingeniera Informtica


C.8.2. Archivo common.c.........................................................................................................710
C.8.3. Archivo serial.h..............................................................................................................717
C.8.4. Archivo serial.c..............................................................................................................718
Apndice D: Interfaz C++................................................................................................................721
D.1. Descripcin...........................................................................................................................721
D.2. Cdigo fuente........................................................................................................................721
D.2.1. Archivo modplcapcpp.h (plataforma Windows)...........................................................721
D.2.2. Archivo modplcapcpp.h (plataforma Linux).................................................................727
Apndice E: Interfaz Simulink.........................................................................................................733
E.1. Descripcin...........................................................................................................................733
E.2. Biblioteca de bloques Simulink............................................................................................733
E.3. Cdigo fuente........................................................................................................................736
E.3.1. Archivo modplc_simulink.c...........................................................................................737
E.3.2. Archivo MODEM_PLC_INTERFACE.C.....................................................................749
E.3.3. Archivo MODEM_PLC_CREATE_MESSAGE.C.......................................................751
E.3.4. Archivo MODEM_PLC_PUT_FIELD.C.......................................................................754
E.3.5. Archivo MODEM_PLC_SEND_MESSAGE.C............................................................756
E.3.6. Archivo MODEM_PLC_RECEIVE.C...........................................................................759
E.3.7. Archivo MODEM_PLC_GET_FIELD.C......................................................................761
E.3.8. Archivo MODEM_PLC_REAL_TIME.C.....................................................................764
Apndice F: Implementacin del dispositivo cliente........................................................................767
F.1. Descripcin del dispositivo...................................................................................................767
F.2. Implementacin del dispositivo.............................................................................................767
F.3. Cdigo fuente........................................................................................................................771
Apndice G: Implementacin de pruebas.........................................................................................775
G.1. Descripcin...........................................................................................................................775
G.2. Red de prueba implementada................................................................................................775
G.3. Modelo Simulink de prueba..................................................................................................778
G.4. Aplicaciones C/C++ de prueba.............................................................................................778
G.4.1. Plataforma Windows.....................................................................................................779
G.4.1.1. Archivo testphy.c....................................................................................................779
G.4.1.2. Archivo testap.c......................................................................................................783
G.4.1.3. Archivo testapcpp.cpp............................................................................................785
G.4.2. Plataforma Linux...........................................................................................................788
G.4.2.1. Archivo testphy.c....................................................................................................788
G.4.2.2. Archivo testap.c......................................................................................................792
G.4.2.3. Archivo testapcpp.cpp............................................................................................794
Glosario............................................................................................................................................799

14

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

1. Introduccin
Desde hace algunos aos se estn empleando buses de datos en aplicaciones integradas por
diversos dispositivos que necesitan estar intercomunicados entre s para llevar a cabo las tareas para
los cuales fueron diseados. Un ejemplo de esto son los automviles, que debido al aumento de la
cantidad de componentes electrnicos utilizados, cada vez resulta ms dificultoso emplear
interconexiones dedicadas debido al gran volumen de cables requeridos para interconectar todos los
dispositivos entre s.
En la actualidad se trabajan con redes como CAN, J1850, entre otras; por la cual, los
dispositivos se intercomunican enviando mensajes entre s por medio de un bus de datos comn,
eliminando la necesidad de que cada dispositivo tenga una conexin dedicada con cada uno de los
dispositivos con los cuales necesita comunicarse. Esto ya reduce el volumen de conductores
utilizados, pero puede reducirse an ms debido a que todava se encuentran presentes dos redes
diferentes de cableado: una para datos y una para alimentacin.
Esta razn es la que motiva la idea de utilizar comunicaciones PLC, en las cuales la
alimentacin y la informacin comparte un mismo canal: la red de alimentacin; por el cual los
dispositivos que necesariamente deben conectarse a la red de alimentacin para poder funcionar,
pueden aprovechar la misma para intercambiar mensajes entre s.
Existen diversos antecedentes que fundamentan esta idea de los cuales se pueden destacar: el
DC-BUS [Maryanka00] desarrollado por la empresa Yamar Electronics Ltd. y trabajos realizados
sobre comunicaciones PLC por la Facultad de Ingeniera Elctrica de la Universidad Tcnica
Checa de Praga. Estos trabajos ponen su atencin en las capas fsica y de enlace, propuestas por el
modelo OSI, dejando de lado la implementacin de las restantes capas.
EL objetivo de ste trabajo es desarrollar un sistema prototipo que implemente las capas del
modelo OSI no implementadas por los antecedentes mencionados anteriormente, y con esto,
analizar la viabilidad de aplicar la ciencia de la informtica como complemento a la electrnica
existente con la finalidad de aumentar funcionalidad y disminuir costos de implementacin. Para
llevar a cabo dicho anlisis, el presente trabajo se encuentra organizado de la siguiente manera:

En el captulo 2 se realiza un anlisis del estado del arte del tema tratado en ste trabajo.
Se comienza con la descripcin de los orgenes y evolucin de la tecnologa PLC en
general, luego se presentan los estndares de comunicacin utilizados en la actualidad en
aplicaciones para automviles, y finalmente se trata en mayor profundidad la tecnologa
PLC aplicada al ambiente automotriz.

En el captulo 3 se detalla el problema que se pretende resolver. Los antecedentes


estudiados en el captulo anterior dejan la posibilidad de continuar avanzando en la
materia, planteando diversos problemas a resolver. ste captulo presenta el problema de
las capas del modelo OSI no implementadas, y define los requerimientos que debe
cumplir el sistema para resolver el problema planteado.

En el captulo 4 se propone un sistema prototipo que cumpla con los requerimientos


definidos en el captulo anterior. Se realiza una descripcin del diseo del sistema
prototipo capa por capa, siguiendo el modelo planteado por OSI.

En el captulo 5 se evala el cumplimiento de lo requerimientos planteados en el captulo


3. Se compara el sistema prototipo propuesto con otras alternativas existentes, realizando

FernandoArielBeunza79156

15

Tesis de Grado en Ingeniera Informtica


una evaluacin del diseo expuesto en el captulo 4 frente a las alternativas enumeradas
en el captulo 2.

16

En el captulo 6 se detallan las conclusiones extradas a partir de la evaluacin


mencionada anteriormente. Se describen los xitos y dificultades del diseo propuesto en
el presente trabajo, y se abren futuras lneas de investigacin.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

2. Antecedentes
En ste captulo se describe la evolucin de la tecnologa PLC desde sus orgenes hasta la
actualidad. En la primer parte se presentan los estndares utilizados en infraestructura edilicia, que
fueron los destinatarios iniciales de la sta tecnologa. En la segunda parte, se trata especficamente
la adaptacin de la tecnologa PLC al ambiente del automvil. Para finalizar, se presentan los
estndares que utilizan los automviles en la actualidad, que no utilizan la tecnologa PLC, pero
plantean soluciones a problemas propios de ste entorno, que pueden tenerse en cuenta para adaptar
la tecnologa PLC al ambiente automotriz.

2.1. Tecnologa PLC


La idea de transmitir informacin sobre un medio ya existente destinado a brindar otro
servicio, se remonta a la dcada del 30, cuando Alemania utiliz la red de telefona para brindar el
servicio de radio por cable llamado HF-Drahtfunk [HF-Drahtfunk]. ste sistema le brindaba al
usuario el servicio de telefona y radio, en forma simultnea, cosa que no ocurra en sistemas
anteriores similares. Suiza contaba con un sistema similar, llamado Telefonrundspruch
[Linjesender], debido a que su geografa montaosa no permita una cobertura nacional por medio
de radio inalmbrica.
La primera vez que se implement la tecnologa PLC fue para brindar el mismo servicio de
radio que brindaban Alemania y Suiza. En ste caso, en vez de utilizar las lneas telefnicas
disponibles, se decidi utilizar las lneas elctricas para la transmisin de voz. Gran Bretaa realiz
experimentos con este sistema, pero la Unin Sovitica fue la que adopt ste medio para la
difusin de programas de radio. Tambin lo hizo Noruega, el servicio en ste pas fue llamado
Linjesender [Linjesender].
Todos los sistemas anteriormente mencionados en la actualidad ya no existen, HFDrahtfunk desapareci en 1967, Linjesender lo hizo en 1987 y Telefonrundspruch en 1997; pero
demostraron que era posible la transmisin de informacin utilizando redes ya existentes. HFDrahtfunk y Telefonrundspruch, fueron los precursores de los servicios de banda ancha que se
brindan hoy en da; mientras que el sistema sovitico y Linjesender, son los precursores de la
tecnologa PLC que hoy en da no tiene tanta difusin que la anterior, pero cada da est cobrando
ms relevancia debido al alcance que tiene la red elctrica frente a otras.
La tecnologa PLC fue adoptada por las compaas de electricidad para transmisin de datos
a baja velocidad. En la dcada del 50 crearon un sistema que permita a las compaas controlar el
consumo, el encendido del alumbrado pblico y el valor de las tarifas elctricas por medio de una
seal de baja frecuencia. A fines de la dcada del 80, se logr realizar transmisiones de datos
bidireccionales; y a fines de la dcada del 90, se pudo elevar la velocidad de transmisin. sto
instal la idea de poder utilizar la red elctrica para brindar servicios de voz y datos. En la
actualidad, compaas como DS2, disean chips capaces de alcanzar velocidades de transmisin que
rondan los 200 Mbps sobre lneas de baja y media tensin, para aplicaciones dentro de un hogar o
una oficina y de ltima milla [Alcar07].

FernandoArielBeunza79156

17

Tesis de Grado en Ingeniera Informtica

2.1.1. X10
ste estndar fue desarrollado para controlar de forma remota dispositivo elctricos en un
hogar u oficina. Para la transmisin de datos utiliza como medio fsico las lneas elctricas presentes
en cualquier establecimiento.

2.1.1.1. Mtodo de transmisin


Las transmisiones son sincronizadas por el punto de cruce por cero de la seal que
proporciona energa (senoidal de 50 o 60 Hz). La informacin se enva por medio de rfagas de
pulsos de 120 KHz durante un semiciclo de la seal que proporciona energa, empleando la
siguiente codificacin: la presencia de un pulso en un semiciclo y la ausencia del mismo en el
siguiente, representa un uno lgico; en cambio, la ausencia de un pulso en un semiciclo seguido de
la presencia del mismo en el siguiente semiciclo, representa un cero lgico. A continuacin, en la
figura 2.1 se puede observar el esquema de codificacin anterior.

Figura 2.1. Codificacin de bits utilizada por el protocolo X10 [X10SignalTheory].

Para permitir el uso del protocolo en instalaciones de red trifsica, se transmiten tres pulsos
que coinciden cada uno de ellos con el cruce por cero de las seales de potencia de cada una de las
fases, como se puede observar en la figura 2.2.

Figura 2.2. Transmisin sobre red trifsica [X10SignalTheory].

18

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


El mecanismo de codificacin de los bits de informacin implementado por X10, permite
una velocidad de transmisin equivalente a la frecuencia de la seal de potencia utilizada para
sincronizacin, si la frecuencia es de 50 Hz la velocidad es de 50 bps, en cambio si la frecuencia es
de 60 Hz la velocidad es de 60 bps.

2.1.1.2. Estructura de mensaje


La estructura de un mensaje se encuentra conformada por cuatro campos utilizados para
marcar el comienzo de un mensaje, identificar el lugar (casa) donde se encuentra el dispositivo al
cual se le quiere enviar el comando, identificar el dispositivo o la funcin, y por ltimo marcar el fin
del mensaje (ver figura 2.3). El tamao de un mensaje es de 11 bits, que corresponden a 11 ciclos de
la seal de potencia.
Start Cdigo
Cdigo de
Bit
code de casa dispositivo/funcin de fin
2 bits

4 bits

4 bits

1 bit

Figura 2.3. Estructura de un mensaje X10.

Cada bit mencionado en la figura anterior corresponde a dos semiciclos de la seal de potencia. Un
ejemplo de como se transmite un mensaje puede observarse en la figura 2.4, en donde se muestran
los bits enviados (arriba de la seal) junto con su codificacin (abajo de la seal).

Figura 2.4. Ejemplo de comando X10 [X10SignalTheory].

Un comando X10 generalmente involucra dos mensajes: uno para la activacin del
dispositivo destinatario, seguido de otro que le indica al dispositivo destinatario la accin que debe
ejecutar. El comando de la figura anterior corresponde a la activacin del dispositivo 2 ubicado en la
casa A. En el primer mensaje, se identifica la casa y el dispositivo al cual se le desea dar la orden;
en cambio, en el segundo mensaje se indica la orden. El bit final de cada mensaje es utilizado para
indicar que a continuacin se transmitir otro mensaje (bit cero) o para dar fin a la secuencia de
mensajes (bit uno).

2.1.1.3. Esquema de direccionamiento


Para hacer referencia al lugar donde se encuentra el dispositivo destinatario se emplea el
cdigo de casa. Cada casa se identifica por medio de una letra que se codifica por medio de una
secuencia de bits, como se indica en la tabla 2.1.

FernandoArielBeunza79156

19

Tesis de Grado en Ingeniera Informtica

Letra Cdigo de casa

Letra Cdigo de casa

0110

0111

1110

1111

0010

0011

1010

1011

0001

0000

1001

1000

0101

0100

1101

1100

Tabla 2.1. Cdigos de casa [X10TechNote].

De similar forma, el cdigo de dispositivo simplemente corresponde a un nmero entre 0 y


15. Este esquema permite trabajar con 256 dispositivos sobre una misma lnea de alimentacin, a
razn de 16 dispositivos como mximo por casa, con un mximo de 16 casas.

2.1.2.4. Funciones
Las funciones que pueden proveer un dispositivo se codifican por medio de 4 bits. Su
codificacin se encuentra detallada en la tabla 2.2, que se encuentra a continuacin:
Cdigo

Funcin

Descripcin

0000

All units Off

Desconecta todos los dispositivos con el cdigo de casa indicado en el mensaje.

0001

All lights On

Conecta todos los dispositivo de iluminacin (con capacidad de control de brillo).

0010

On

Conecta un dispositivo.

0011

Off

Desconecta un dispositivo.

0100

Dim

Reduce la intensidad luminosa.

0101

Bright

Aumenta la intensidad luminosa.

0111

Extended Code

Cdigo de extensin.

1000

Hail Request

Solicita respuesta de los dispositivos con cdigo de casa indicado en el mensaje.

1001

Hail Acknowledge Respuesta a un comando anterior.

101x

Pre-Set Dim

Permite seleccionar dos niveles de intensidad luminosa predefinidos.

1100

Extended Data

Datos adicionales (seguido por 8 bytes).

1101

Status is On

Respuesta a un pedido de Status Request, indicando que el dispositivo est


conectado.

1110

Status is Off

Respuesta a un pedido de Status Request, indicando que el dispositivo est


desconectado.

1111

Status Request

Pedido solicitando el estado del dispositivo.

Tabla 2.2. Lista de funciones definidas por X10 [X10SignalTheory].

Las funciones ms utilizadas son las seis primeras de la tabla anterior. Las funciones Hail Request y
Hail Acknowledge, se utilizan para comunicacin con casas vecinas. Las funciones Extended Code y

20

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Extended Data son empleadas para expandir la capacidad de comandos y de enviar datos
adicionales, respectivamente.

2.1.2. CEBus
El estndar CEBus implementa un modelo de comunicaciones punto a punto, en donde
cualquier nodo puede comunicarse con otro en cualquier instante. La comunicacin se realiza a
travs de un nico medio compartido, utilizando un protocolo de control de acceso al medio para
resolver las colisiones cuando dos o ms dispositivos quieren acceder al medio fsico en forma
simultnea.
CEBus fue pensado para trabajar sobre diversos medios fsicos: lneas de potencia, par
trenzado, coaxil, radio e infrarrojo. En el presente trabajo slo se trata el primer medio fsico,
aunque muchos conceptos son aplicables tambin a los otros medios.
ste estndar implementa cuatro de las siete capas definidas por el modelo OSI, que son: la
capa fsica, la capa de enlace, la capa de red y la capa de aplicacin. Sobre la capa de aplicacin se
encuentra CAL, que establece un lenguaje comn para permitir la interoperabilidad entre
dispositivos.

2.1.2.1. Mtodo de transmisin


La capa fsica de CEBus se basa en una tecnologa de espectro ensanchado patentada por la
empresa Intellon. La tcnica empleada es diferente a la tecnologa tradicional, ya que el smbolo
utilizado es una seal conocida como Chirp. Una seal Chirp se genera a partir de un barrido en
frecuencia, dentro de un rango determinado, de una seal senoidal, y se caracterizan por presentar
un alto rechazo a interferencias. La seal Chirp empleada por CEBus (figura 2.5) comienza con una
seal senoidal de 200 KHz y aumenta hasta los 400 KHz, para luego saltar a 100 KHz y avanzar
hasta 200 KHz nuevamente. sta seal se genera por medio de un sintetizador a partir de una tabla
compuesta por 360 muestras.

Figura 2.5. Seal Chirp utilizada por CEBus [Montoya06].

Un paquete de datos se transmite utilizando la seal Chirp anterior. La primer secuencia de


seales Chirp constituye el prembulo del paquete y es utilizado por los transmisores para resolver
FernandoArielBeunza79156

21

Tesis de Grado en Ingeniera Informtica


quien tiene derecho a uso del canal de comunicacin. Luego del prembulo, el transmisor que gan
el derecho de utilizar el canal de comunicacin, transmite un conjunto de seales Chirp para marcar
el comienzo del paquete.
Para recuperar los bits del paquete, los receptores se sincronizan aplicando la operacin de
correlacin a la seal recibida. Cuando la seal recibida coincide con la seal Chirp esperada, la
correlacin devuelve un pulso de sincronismo.
CEBus con el mecanismo de transmisin expuesto, puede lograr velocidad de transmisin de
10 kbps.

2.1.2.2. Estructura de paquete


Un paquete CEBus se encuentra constituido fundamentalmente por las siguientes partes: un
prembulo, una unidad de datos del protocolo de capa de enlace, llamado LPDU, y un cdigo CRC.
La LPDU puede contener como mximo 41 bytes, y se conforma de un encabezado (9 bytes) y una
unidad de datos del protocolo de red, llamado NPDU. La NPDU puede contener hasta 32 bytes, de
los cuales uno pertenece al encabezado y el resto se destina a la unidad de datos del protocolo de
aplicacin, llamado APDU. El APDU se compone de un encabezado de 1 byte de longitud y el resto
se destina a instrucciones de la CAL.

Figura 2.6. Estructura de un paquete CEBus [House].

El encabezado de la LPDU contiene un campo de control (1 byte), con informacin de


control, como el nmero de secuencia del paquete, la prioridad del mismo y el tipo. Tambin
contiene la direccin de destino del paquete como la de origen del mismo (4 bytes cada una).
El encabezado de la NPDU contiene informacin acerca del encaminado del paquete y
fragmentacin del mismo.
El encabezado de la APDU contiene informacin sobre como debe responder el receptor
cuando recibe un paquete.

2.1.2.3. Esquema de direccionamiento


El esquema de direccionamiento propuesto por CEBus, utiliza 32 bits para representar las
direcciones de los dispositivos, lo que se traduce en 232 direcciones posibles. Dichos 32 bits se
dividen en dos grupos de 16 bits cada uno: el primer grupo se lo designa direccin de sistema (o
cdigo de hogar), y el segundo grupo se lo designa direccin MAC (o cdigo de unidad).
Cada una de las direcciones anteriores presenta un rango de direcciones utilizables
comprendido entre 1 y 65535. El identificador de cdigo de unidad 0 se reserva para broadcast
22

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


dentro de un grupo de dispositivos asociado a un cdigo de hogar. Si el identificador de cdigo de
hogar tambin es 0, el broadcast incluye a todos los dispositivos de la red sin importar a que cdigo
de hogar se encuentren asociados.

2.1.2.4. Lenguaje de aplicacin


CAL implementa un modelo jerrquico para describir a cada nodo de la red. Un nodo puede
tener varios contextos, y a su vez, cada contexto puede estar compuesto por varios objetos. Los
objetos pueden tener varias variables de instancia.
Todo dispositivo presenta un contexto universal (que se identifica con el cdigo 00). La
funcin de ste contexto es la de controlar la presencia de cada dispositivos dentro de la red. El
contexto universal presenta dos objetos: el objeto de control de nodo (conocido como objeto 0) y el
objeto de control de contexto (objeto 1). El objeto de control de nodo contiene una serie de
variables de instancia con informacin acerca del dispositivo (direcciones, fabricante, etc.). El
objeto de contexto presenta una nica variable de instancia que contiene una lista de identificadores
de objeto del contexto. Adems del contexto universal, los dispositivos pueden presentar varios
contextos adicionales, con mltiples objetos por contexto, dependiendo de las funcionalidades que
provean los dispositivos. En la tabla 2.3 se pueden observar un conjunto de objetos definidos, cada
uno de ellos con sus propias variables de instancia.
Valor
(Hex)

Nombre

Valor
(Hex)

Nombre

01

Node Control

0E

Gagned Analog Control

02

Context Control

0F

Meter

03

Data Channel Receiver

10

Display

04

Data Channel Transmitter

11

Medium Transport

05

Binary Switch

13

Dialer

06

Binary Sensor

14

Keypad

07

Analog Control

15

List Memory

08

Analog Sensor

16

Data Memory

09

Multi-position Switch

17

Motor

0A

Multi-state Sensor

19

Synthesizer/Tuner

0B

Matrix Switch

1A

Tone Generator

0C

Multiplane Switch

1C

Counter

0D

Gagned Analog Control

1D

Clock

Tabla 2.3. Objetos definidos por CEBus [House].

Para acceder a las variables de instancia de cada objeto, CAL define un conjunto de mtodos
enumerados en la tabla 2.4.

FernandoArielBeunza79156

23

Tesis de Grado en Ingeniera Informtica

Valor

Nombre

Parmetros

Tipos de datos

40

nop

41

setOFF

IV

42

setON

IV

43

getValue

IV

BNC

44

getArray

IV [, [<offset>], <count>]

45

setValue

IV

46

setArray

IV [, [<offset>], <data>]

47

add

IV1, IV2, [IV3]

48

increment

IV [, <number>]

49

subtract

IV1, IV2, [IV3]

4A

decrement IV [, <number>]

4B

compare

IV1, IV2

BNCD

4C

comparei

IV1, <data>

BNCD

4D

copyValue IV1, IV2 [, <context>, <object>]

BNCD

4E

swap

IV1, IV2

BNCD

52

exit

[<error number>]

53

alias

<alias ID> [<string>]

54

inherit

IV, <value>

55

disinherit

IV, <value>

56

if

<boolean> BEGIN <message list> [else clause] END

57

do

<boolean> BEGIN <message list> END

58

while

<boolean> BEGIN <message list> END

59

repeat

<boolean> BEGIN <message list> END

5A

build

D
BNC

<macro ID> BEGIN <message list> END

Tabla 2.4. Mtodos definidos por CEBus [House].

Los tipos de datos definidos por CAL son: cadenas de caracteres (strings), datos, nmeros y
booleanos. En la tabla 2.4 se aclaran los tipos de datos que puede manipular cada mtodo.
Por ltimo, CAL tambin define una lista de posibles errores que pueden ocurrir, que se
detallan en la tabla 2.5.

24

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Valor

Descripcin

Valor

Descripcin

Unknown Context ID

10

Inherit Disabled

Unknown Object ID

11

Value out of Range

Unknown Method ID

12

Bad Argument Type

Unknown IV Label

13

Power Off

Malformed Expression

14

Invalid Argument

Macro not defined

15

IV Read Only

Alias not defined

16

No Default

Syntax error

17

Cannot Inherit Resource

Resource in use

18

Precondition Complete

Command too Complex

19

Application Busy

Tabla 2.5. Cdigos de error definidos por CEBus [House].

2.1.3. CENELEC 50065


La norma que regula las comunicaciones PLC en Europa se la conoce como CENELEC
50065-1. sta norma es la encargada de definir el rango de frecuencias que puede ser utilizado para
este tipo de comunicaciones, las amplitudes mximas de las seales y los lmites de interferencia
entre las bandas circundantes. Se definen cuatro bandas para distintas aplicaciones, como se puede
observar en la tabla 2.6.
Banda Rango de frecuencias

Propsito

3 KHz 9 KHz

Para uso de las compaas de distribucin elctrica solamente.

9 KHz 95 KHz

Para uso de las compaas de distribucin elctrica y sus licencias.

95 KHz 125 KHz

Disponible para los consumidores sin restricciones.

125 KHz 140 KHz

Disponible para los consumidores con control de acceso al medio

140 KHz 148.5 KHz Disponible para los consumidores sin restricciones.

Tabla 2.6. Rango de frecuencias establecido por CENELEC 50065-1 [Kaspar].

Cuando se trabaja dentro de la banda A, la norma no exige la utilizacin de protocolos de acceso al


medio. Del mismo modo ocurre con la banda B, destinada a ser utilizada por dispositivos tales
como intercomunicadores. En cambio, la banda C debe utilizar algn mtodo de control de acceso
al medio; ya que fue pensada en escenarios en donde las transmisiones simultneas son altamente
improbables, como por ejemplo comunicaciones internas entre computadoras. Por ltimo, la banda
D presenta caractersticas similares a la A, por lo cual pueden existir colisiones si dos dispositivos
transmiten en simultneo [PLCEc].

FernandoArielBeunza79156

25

Tesis de Grado en Ingeniera Informtica

Figura 2.7. Diferencias entre norma europea y norteamericana [Kaspar].

Como se observa en la figura 2.7, a diferencia de Europa, Estados Unidos y Japn tienen un
lmite superior para el rango de frecuencias destinado para comunicaciones PLC, debido a que stos
ltimos no utilizan sistemas de radio de onda larga.
La norma tambin define las amplitudes mximas que pueden presentar las seales
utilizadas para transmitir la informacin. A continuacin en la figura 2.8, se pueden observar dichos
niveles para cada una de las bandas establecidas.

Figura 2.8. Lmites mximos de nivel de seal permitidos por CENELEC 50065-1 [PLCEc].

Como se puede apreciar, para la banda A, el nivel mximo permitido alcanza los 134 dBuV en 9
KHz y desciende hasta los 120 dBuV en el lmite superior de la banda en 95 KHz. El resto de las
bandas tiene un nivel mximo permitido de 122 dBuV.

2.1.4. UPB
El estndar UPB es una evolucin de X10, que utiliza la misma tcnica de transmisin de
informacin, agregando a la seal de potencia que alimenta a los dispositivos de la red elctrica, la

26

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


seal de informacin. ste estndar introduce algunas mejoras respecto a X10, como el mtodo de
modulacin que permite elevar la velocidad de transmisin, y tambin expande la capacidad de
direccionamiento de los dispositivos.

2.1.4.1. Mtodo de transmisin


UPB utiliza como seal de sincronizacin la seal de potencia utilizada para alimentacin
(seal senoidal de 50 o 60 Hz), tomando como referencia el cruce por cero de sta seal con flanco
ascendente. A diferencia de X10, el pulso no se transmite luego del cruce por cero, sino que en ste
caso se espera un tiempo determinado para iniciar la transmisin. Luego, el siguiente pulso, es
transmitido cuando transcurre medio ciclo de seal de sincronizacin (seal de potencia). ste
estndar tiene la capacidad de transmitir ms bits en un semiciclo de seal de sincronizacin que el
estndar X10, ya que emplea la modulacin PPM, que permite codificar dos bits por semiciclo como
se puede observar en la figura 2.9.

Figura 2.9. Codificacin de bits utilizada por el protocolo UPB [UPB03].

Para enviar los dos bits es emplean 800 microsegundos divididos en cuatro fragmentos de 200
microsegundos cada uno. El fragmento en el cual se emite el pulso depende del valor que tome el
grupo de dos bits que se desean transmitir. Con este esquema de codificacin, un byte de
informacin puede ser enviado en cuatro semiciclos de la seal de potencia. La velocidad de
transferencia lograda de sta forma equivale a cuatro veces la frecuencia de la seal de potencia
utilizada para sincronizacin: 200 bps (para 50 Hz) y 240 bps (para 60 Hz).

FernandoArielBeunza79156

27

Tesis de Grado en Ingeniera Informtica

2.1.4.2. Estructura de paquete


La estructura de paquete propuesta por el UPB, presenta longitud variable, y se compone de
los siguientes campos: un prembulo de longitud fija de 1 byte, un encabezado de 5 bytes, el
mensaje cuya longitud puede variar entre 0 y 18 bytes, una suma de verificacin de 1 byte, y la
confirmacin de recepcin de un bit de longitud.

Figura 2.10. Estructura de un paquete UPB [UPB03].

El prembulo del paquete es utilizado por los receptores para realizar ajustes que le permitan
tener una buena recepcin del resto del paquete.
El encabezado contiene cierta informacin de control, como el dispositivo que dio origen al
paquete, su destinatario, el tamao del mismo, entre otros. La composicin del encabezado se
detalla en la figura 2.11.

Figura 2.11. Estructura del encabezado de un paquete UPB [UPB03].

El campo CTL tiene una longitud de 2 bytes, y es utilizado para indicar el tamao del paquete, como
debe ser recibido el mismo, como se debe responder al mismo y la cantidad de veces que fue
enviado. El campo NID tiene una longitud de 1 byte, y permite identificar la red en la cual se
encuentra el destinatario del paquete. El campo DID, de 1 byte de longitud, permite identificar al
dispositivo destinatario del paquete. El campo SID, de 1 byte de longitud, indica el dispositivo que
envi el paquete.
Luego del encabezado se encuentra el mensaje cuya longitud puede ser de 0 hasta 18 bytes.
El mensaje se compone (figura 2.12) de dos campos identificados como MDID y MDA.

28

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 2.12. Estructura del mensaje de un paquete UPB [UPB03].

El campo MDID, de 1 byte de longitud, es utilizado para identificar un comando o una respuesta a
un comando. El campo MDA puede contener hasta 17 bytes y es el encargado de transportar los
argumentos asociados a un comando o una respuesta a un comando.
A continuacin del mensaje, se encuentra la suma de verificacin que es utilizada por el
destinatario del paquete para determinar si el mismo fue recibido correctamente o presenta errores.
Por ltimo, el bit de confirmacin de recepcin, es un bit que deja disponible en dispositivo
que dio origen al paquete, para que el destinatario pueda indicar al origen si el paquete fue recibido
correctamente o no.

2.1.4.3. Esquema de direccionamiento


El protocolo UPB permite crear redes virtuales sobre una misma red fsica. El estndar
permite un mximo de 255 redes. sto permite agrupar los distintos dispositivos en distintas redes
virtuales sobre una misma lnea de alimentacin. Cada una de las redes virtuales puede contener
hasta 250 dispositivos. El concepto es similar al propuesto por X10, pero con una mayor capacidad,
ya que el esquema propuesto por UPB puede soportar hasta 63750 dispositivos sobre una misma
lnea, mientras que X10 solo soporta 256.
Los identificadores de red vlidos se encuentran comprendidos en el rango de 1 a 255,
reservando el identificador 0 para mensajes de broadcast. El identificador 0 le permite a cualquier
dispositivo poder enviar mensajes a todos los dispositivos conectados en la lnea
independientemente de la red a la cual pertenezcan, ya que cada dispositivo slo recibe los mensajes
pertenecientes a su red.
Los identificadores de dispositivo se encuentran comprendidos en el rango de 1 a 250,
reservando el identificador 0 para mensajes de difusin dentro de la red virtual, y los identificadores
comprendidos entre 251 y 255 para propsitos especiales.
Una funcionalidad adicional que brinda UPB, es la posibilidad de crear grupos de
dispositivos, que respondan a los comandos enviados que contengan como identificador de
dispositivo destino, el identificador de grupo al pertenecen los dispositivos. El rango de
identificadores de grupo vlidos es el mismo al utilizado para los identificadores de direcciones (1 a

FernandoArielBeunza79156

29

Tesis de Grado en Ingeniera Informtica


250), descartando el identificador 0 (identificador de broadcast) y el rango de 251 a 255 (propsitos
especiales).

2.1.4.4. Comandos
La variedad de comandos que brinda UPB es mucho ms amplia que los proporcionados por
X10. La mxima cantidad de comandos soportados es de 256 (frente a los 16 de X10), aunque no se
utilizan todos los identificadores disponibles. En la tabla 2.7 se hace referencia a los comandos
principales implementados por UPB:
MDID
(Hex)

Comando

MDID
(Hex)

Comando

00

Null

0E - 0F Unused

01

Write Enable

10

Get Register Value

02

Write Protect

11

Set Register Value

03

Start SETUP Mode

12

Copy Register Value

04

Stop SETUP Mode

13

Swap Register Nibbles

05

Get SETUP Time

14

Increment Register Value

06

Auto-Address

15

Decrement Register Value

07

Get Device Status

16

Left Shift Register

08

Set Device Control

17

Right Shift Register

09

Get Signal Strength

18

Set Register Bits

0A

Get Noise Level

19

Clear Register Bits

0B

Add Link

1A

Toggle Register Bits

0C

Delete Link

0D

Transmit This Message

1B - 1F Unused

Tabla 2.7. Comandos principales implementados por UPB [UPB03].

Tambin existen una serie de comandos y respuestas especiales dedicados a funciones de control,
como se puede ver en la tabla 2.8.
MDID
(Hex)

Comando / Respuesta

MDID
(Hex)
25

Comando / Respuesta

20

Activate Link

Blink

21

Deactivate Link

22

Goto

30

Report State

23

Start Fade

31

Store State

24

Stop Fade

26 - 2F Unused

32 - 3F Unused

Tabla 2.8. Comandos y respuestas especiales implementados por UPB [UPB03].

Por ltimo, UPB define una serie de respuestas a comandos que se detallan en la tabla 2.9.

30

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

MDID
(Hex)

Respuesta

80 -84 Unused

MDID
(Hex)

Respuesta

90

Register Values

85

Setup Time

91

RAM Values

86

Device State

92

Raw Data

87

Device Status

93

Heartbeat

89

Signal Strength

8A

Noise Level

94 - AE Unused
AF

Acknowledgement

8B - 8F Unused

Tabla 2.9. Respuestas implementados por UPB [UPB03].

2.1.5. LonWorks
ste estndar se basa en el esquema propuesto por LON, que consisten en un conjunto de
dispositivos que se conectan por medio de uno o varios medios fsicos, y emplean para comunicarse
un protocolo comn. Cada dispositivo tiene la capacidad de generar acciones en respuesta a
mensajes recibidos de otros dispositivos, y/o generar mensajes ante el cumplimiento de
determinadas condiciones.

2.1.5.1. Protocolo CNP


Del mismo modo que las redes de datos e internet se basan en el protocolo TCP/IP
[RFC793] [RFC791], LonWorks se basa en el protocolo CNP [ISO/IEC14908-1]. ste ltimo
protocolo fue diseado para cubrir los requerimientos de las aplicaciones de control. ste protocolo
implementa siete capas siguiendo las recomendaciones sugeridas por el modelo OSI. El propsito y
servicios que provee cada una de las capas definidas se describe en la tabla 2.10.

FernandoArielBeunza79156

31

Tesis de Grado en Ingeniera Informtica

Capas OSI
Fsica

Enlace

Red

Propsito

Servicios provistos

Interconexin elctrica

Medios fsicos.
Esquemas de modulacin.

Acceso al medio y armado de tramas

Armado y desarmado de tramas.


Verificacin de errores.
Control de acceso al medio.
Prioridad.

Envo de mensajes

Comunicaciones unicast y multicast.


Encaminado de mensajes.

Envo de mensajes con o sin confirmacin de recepcin.


Transporte Confiabilidad en el envo de mensajes Ordenamiento de mensajes.
Deteccin de mensajes duplicados.
Sesin

Pedido y respuesta.
Autenticacin.

Control

Variables de red.
Mensajes de aplicacin.

Presentacin Interpretacin de datos

Configuracin de red.
Diagnstico de red.
Transferencia de archivos.
Configuracin de aplicaciones.
Especificacin de aplicaciones.
Alarmas.
Registro de datos.
Planificacin.

Aplicacin Compatibilidad

Tabla 2.10. Capas CNP [Echelon99].

La organizacin de los datos para el transporte de los mismos, en cada una de las capas
presentadas anteriormente se detallan en la tabla 2.11.
Capa

Organizacin de datos

Fsica

Bits en bruto

Enlace

Trama

Red

Datagrama

Transporte

Paquete de transporte

Sesin

Paquete de sesin

Presentacin Paquete de presentacin


Aplicacin

Mensaje

Tabla 2.11. Organizacin de datos utilizada por cada capa [Echelon99].

2.1.5.2. Capa fsica


La capa fsica se encarga de definir como se transmiten los bits de datos en bruto sobre un
determinado medio fsico. El protocolo CNP fue diseado para ser independiente del medio fsico,
lo que permite que LonWorks pueda ser implementado sobre diferentes tipos de redes.

32

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Los diferentes tipos de medio que pueden utilizarse permiten comunicaciones
bidireccionales entre cualquiera de los dispositivos conectados a la red. En la tabla 2.12 se detallan
cada uno de los medios fsicos con los cuales LonWorks puede trabajar.
Nombre

Medio

Velocidad

Definicin

IP-852

IP-852 Tunneling

N/A

ISO/IEC 14908-4

PL-20A

CENELEC A-band Power Line

2613bps

ISO/IEC 14908-3

PL-20C

CENELEC C-band
Power Line w/access protocol

156.3k/3987bps

ISO/IEC 14908-3

PL-20N

CENELEC C-band
Power Line w/o access protocol

156.3k/3987bps

ISO/IEC 14908-3

TP/FT-10

Free Topology Twisted Pair

78.13kbps

ISO/IEC 14908-2

1.25Mbps

LONMARK Interoperability
Guidelines

TP/XF-1250 Transformer-Isolated Twisted Pair

Tabla 2.12. Organizacin de datos utilizada por cada capa [Echelon99].


El objetivo del presente trabajo no es tratar todos los medios fsicos sobre los cuales puede
implementarse LonWorks sino que analizar los medios relacionados con las lneas de potencia,
cuyos nombres (segn tabla 2.12) son PL-20A, PL-20C y PL-20N.
Las velocidad de transferencia que se pueden alcanzar depende del medio fsico sobre el cual
se trabaje. Como se puede observar en la tabla 2.12, cuando se trabajan con lneas de potencia, se
obtienen las velocidades de transferencia ms bajas comparadas con los otros medios fsicos
existentes.
LonWorks, sobre lneas de potencia, puede trabajar dentro del rango de frecuencias
pertenecientes a la banda A y a la banda C definidas por CENELEC 50065-1. El sistema de
modulacin utilizado es BPSK combinado con espectro ensanchado de banda estrecha
[Montoya06], que para el caso de la banda A, el rango de frecuencias utilizado se extiende desde
los 75 KHz hasta 86 KHz; mientras que para el caso de la banda C, el rango de frecuencias se
extiende comprende desde los 115 KHz hasta los 132 KHz.

2.1.5.3. Capa de enlace


El protocolo CNP define establece varios mecanismos para controlar el acceso al medio
fsico, de los cuales se analizar el CSMA, dado que es el utilizado cuando se trabaja sobre lneas de
potencia. Dentro de todas las variantes de CSMA, ste protocolo implementa una variante propia
llamada p-persistente CSMA predictivo. El mecanismo consiste en que previo al envi de una
trama, se establece un tiempo de espera (dividido en ranuras), y transcurrido dicho tiempo, si el
medio se encuentra disponible, se enva la trama. La cantidad de ranuras que se deben esperar se
establece en forma aleatoria, a partir de un conjunto de valores posibles, para evitar colisiones. La
cantidad de valores de dicho conjunto se ajusta dependiendo de la actividad que haya sobre el medio
fsico. Si el medio no es utilizado por ningn dispositivo, todos los dispositivos establecen 16
ranuras de espera, entre los cuales cada uno de los dispositivos que deseen enviar algo deber elegir
en forma aleatoria cuantas ranuras esperar (entre 1 y 16). stas 16 ranuras de espera pueden
aumentar, dependiendo del trfico de la red, para evitar colisiones, hasta un mximo de 63 ranuras
El protocolo tambin ofrece la posibilidad de utilizar un sistema de prioridad para el envo
de paquetes crticos. Dicho sistema de prioridad se basa en la introduccin de ranuras de tiempo

FernandoArielBeunza79156

33

Tesis de Grado en Ingeniera Informtica


adicionales previo a las ranuras utilizados para evitar las colisiones. El nmero de ranuras
destinadas a prioridad puede variar entre 0 y 127.
Una trama se encuentra conformada por los siguientes campos: un prembulo, un
encabezado con informacin de control, los datos (datagrama de capa de red), un cdigo de
deteccin de errores y un indicador de final de trama.

Figura 2.13. Estructura de trama [Echelon99].

El prembulo es utilizado por los receptores para sincronicen sus relojes de modo de poder
recibir la trama. ste se compone de dos campos llamados: un bit-sync y un byte sync. El primero
consiste en 6 bits utilizados para sincronizacin, mientras que el segundo consiste en 1 bit que
indica el fin del prembulo.
El encabezado contiene tres campos: priority, path y delta backlog. El primer campo
especifica la prioridad de trama. El segundo campo identifica a la medio fsico por el cual se envi
la trama. Por ltimo, el tercer campo contiene informacin para el ajuste del tiempo de espera del
mecanismo de acceso al medio.
El cdigo de verificacin de errores se compone de un cdigo CRC de 16 bits, utilizado para
determinar si la trama fue recibida sin errores.

2.1.5.4. Capa de red


La capa de red establece como se encaminan los paquetes de mensajes desde el origen de los
mismos hasta el o los destinatarios. Tambin define los nombres y direcciones de los dispositivos.
Los mensajes pueden enviarse a un destinatario, a un grupo de dispositivos o a todos los
dispositivos.
El nombre es un identificador nico utilizado para individualizar a un simple objeto dentro
de una clase de objetos. ste es asignado al momento de la creacin del objeto y no se modifica
durante la vida del objeto.
Una direccin es un identificador nico que individualiza a un objeto o a un grupo de
objetos dentro de una clase de objetos. A diferencia del nombre, una direccin puede ser modificada
en todo momento. La direccin se compone de tres partes: dominio, subred y nodo.
Tambin existe el Neuron ID, que es un identificador de 48 bits que puede ser utilizado
como direccin, ya que es nico y es asignado en el momento de fabricacin del dispositivo, y no
puede ser modificado.
Un dominio es una coleccin lgica de dispositivos que pueden estar conectados a diferentes
medios fsicos creando una red virtual, o bien pueden existir varias colecciones de dispositivos
sobre un mismo medio fsico formando varias redes lgicas sobre un mismo medio. La cantidad de
bytes utilizada para identificar un dominio puede configurarse en 0, 1, 3 o 6 bytes.
Una subred es una coleccin lgica de dispositivos dentro de un dominio. Pueden existir
hasta 255 subredes dentro de un dominio. Todos los dispositivos pertenecientes a una subred deben
estar conectados al mismo segmento.

34

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Un nodo es un identificador de dispositivo de 7 bits de longitud que permite individualizar
un dispositivo dentro de una subred. Con ste esquema, una subred puede contener hasta 127
dispositivos.
Un grupo es una coleccin de dispositivos dentro de un dominio, que a diferencia de una
subred no importa donde se encuentre ubicados (pueden pertenecer a diferentes segmentos). Para
identificar a los grupo se utiliza 1 byte, lo que permite tener hasta 256 grupos dentro de un mismo
dominio.
Existe diversos modos de direccionamiento, y segn cual sea utilizado, la cantidad de bytes
requeridos. En la tabla 2.13 se describen los 5 modos de direccionamiento posibles.
Modo de direccionamiento

Formato de direccin

Destino

Tamao de la
direccin

Broadcast dentro del dominio Dominio (Subred = 0)

Todos los dispositivos dentro del dominio

Broadcast dentro de la subred Dominio, Subred

Todos los dispositivos dentro de la subred

Multicast

Dominio, Grupo

Todos los dispositivos dentro del grupo

Unicast

Dominio, Subred, Nodo Dispositivo especfico dentro de una subred

Dominio, Neuron ID

Neuron ID

Dispositivo especfico

Tabla 2.13. Modos de direccionamiento [Echelon99].

Un datagrama se encuentra conformado de los siguientes campos: versin, formato de


paquete, formato de direccin, tamao del dominio, direccin, dominio y el paquete.

Figura 2.14. Estructura de datagrama [Echelon99].

La versin especifica la versin del protocolo, y siempre toma el valor cero. El formato del paquete
especifica el formato del contenido del paquete, que puede ser: un paquete de transporte, un paquete
de sesin, un paquete autenticado o un paquete de presentacin. El formato de la direccin indica
que tipo de direccin contiene el paquete, pudiendo existir cuatro variantes: broadcast (subred),
grupo, subred/nodo o grupo con confirmacin de recepcin, o Neuron ID. El tamao del dominio
determina cuantos bytes se destinan para especificar el dominio, existiendo 4 variantes: 0 bytes, 1
byte, 3 bytes o 6 bytes. El campo direccin contiene la direccin del mensaje con el formato
especificado en el formato de direccin.

2.1.5.5. Capa de transporte


La capa de transporte cumple la misin de asegurar la entrega confiable de paquetes de
mensaje. Los tipos de envi que ofrece sta capa son: con confirmacin de recepcin, repetido sin
confirmacin de recepcin y sin confirmacin de recepcin.
Un envo con confirmacin de recepcin es aquel en donde el emisor del paquete de
mensaje, una vez enviado ste ltimo permanece en espera hasta que responda el destinatario. El
destinatario de un paquete puede ser un dispositivo o un grupo de ellos, se considera que el envo

FernandoArielBeunza79156

35

Tesis de Grado en Ingeniera Informtica


fue satisfactorio cuando todos los destinatarios confirman la recepcin, salvo que se trate de un
paquete broadcast en el cual el envo se considera satisfactorio cuando llega solamente una
confirmacin de recepcin. El emisor puede reenviar el paquete varias veces hasta que reciba la
confirmacin de recepcin o hasta que supere el lmite de cantidad de reenvos.
Un envo repetido es similar al anterior, pero en ste caso, los paquetes se envan una
cantidad determinada de veces sin esperar un confirmacin de recepcin. ste tipo de envo es
menos confiable que el primero, pero recomendable en situaciones en donde el cantidad de
miembros del grupo destinatario es mayor a la cantidad de reenvos utilizando el tipo de envo
anterior.
Por ltimo, existe el envo sin confirmacin, en el cual un paquete es enviado una sola vez si
esperar la confirmacin de recepcin. ste tipo de envo es el menos confiable de todos, pero til
cuando la informacin a enviar no es crtica.
El paquete de transporte se compone de los siguientes campos: autenticacin, formato de
paquete de transporte, nmero de transaccin y datos que transporta el paquete.

Figura 2.15. Estructura de paquete de transporte [Echelon99].

El campo de autenticacin es utilizado para indicar si el mensaje es autenticado o no. El formato de


paquete de transporte define el formato del contenido transportado por el paquete, existiendo cinco
tipos de formato: mensaje con confirmacin de recepcin, mensaje repetido, confirmacin de
recepcin, resto de prembulo y resto de mensaje. Los dos primeros formatos de paquete son
utilizados por la capa de presentacin para el envo de informacin. El tercer formato es empleado
para confirmar la recepcin de mensaje y el contenido del paquete es el encabezado del mensaje
recibido. Los ltimos dos formatos de paquete son utilizados para la confirmacin de recepcin de
paquetes multicast.

2.1.5.6. Capa de sesin


La capa de sesin agrega control al intercambio de datos. Un dispositivo que necesita un
servicio que brinda otro dispositivo, enva un pedido, y ste ltimo en respuesta a ese pedido enva
una respuesta. ste mecanismo de pedido-respuesta puede ser implementado sobre todas las formas
de comunicacin posible provista por las capas inferiores. El caso especial, es un pedido broadcast,
en donde slo se tiene en cuenta la respuesta del primer dispositivo que responde.
Tambin la presente capa define un protocolo de autenticacin, que permite a los
dispositivos receptores, aceptar o rechazar mensajes segn el dispositivo emisor que los envi. sto
es utilizado para prevenir el uso no autorizado a dispositivos y sus aplicaciones. La autenticacin de
los mensajes se realiza por medio de una clave de 48 bits de longitud, y tanto el emisor como el
receptor deben poseer la misma clave para que el mensaje sea aceptado.
El paquete de sesin se conforma de los siguientes campos: autenticacin, formato de
paquete de sesin, nmero de transaccin y datos que transporta el paquete.

36

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 2.16. Estructura de paquete de sesin [Echelon99].

El campo de autenticacin es utilizado para indicar si el mensaje es autenticado o no. El formato de


paquete de sesin define el formato del contenido transportado por el paquete, que puede ser: un
pedido, una respuesta, un resto de prembulo o un resto de mensaje. Los dos primeros formatos se
utilizan en transacciones en donde se involucran un origen y un destino, en cambio los dos segundos
formatos son empleados en transacciones multicast.

2.1.5.7. Capa de presentacin


El objetivo de la capa de presentacin es agregar estructura a los datos que intercambian los
dispositivos. Hasta esta capa, los datos enviados no se encontraban organizados dentro de ninguna
estructura.
La presente capa se encarga de definir un conjunto de tipos de datos que pueden ser simples
(nmero enteros, punto flotante, etc.) o compuestos (estructuras conformadas a partir de tipos
simples). Los datos organizados en las estructuras anteriores son designados variables de red, y un
dispositivo puede tener mltiples variables de red. Una variable de red se caracteriza por tener: una
direccin (lectura o escritura), un tipo (ver tabla 2.14) y una longitud.
Tipo de dato

Descripcin

Bitfield

Bit con o sin signo de 1 a 8 bits de longitud. Slo disponible dentro de una estructura o unin.

Double Float

Punto flotante de 64 bits.

Enumerated

Enumeracin de 8 bits con signo.

Float

Punto flotante de 32 bits.

Reference

Referencia a un tipo de variable de red.

Signed Character

Caracter de 8 bits con signo.

Signed Long

Entero de 16 bits con signo. Rango -32768 a 32767

Signed Quad

Entero de 32 bits con signo.

Signed Short

Entero de 8 bits con signo. Rango -128 a 127.

Unsigned Character Caracter de 8 bits sin signo.


Unsigned Long

Entero de 16 bits sin signo. Rango 0 a 65536

Unsigned Quad

Valor de 32 bits sin signo.

Unsigned Short

Entero de 8 bits sin signo. Rango de 0 a 255.

Tabla 2.14. Tipos de datos definidos por la capa de presentacin [Echelon99].

Cada uno de los tipos anteriores puede combinarse para formar estructuras compuestas. Existen dos
tipos de estructuras compuestas: estructuras y uniones. Una estructura se compone de cualquiera de
los tipos descriptos en la tabla 2.14. En cambio, una unin puede contener una estructura o
cualquier tipo de dato simple de la tabla 2.14.

FernandoArielBeunza79156

37

Tesis de Grado en Ingeniera Informtica


Un paquete de capa de presentacin se encuentra compuesto de los siguientes campos:
direccin, parte alta y baja del selector de variable de red, y contenido del paquete.

Figura 2.17. Estructura de paquete de presentacin [Echelon99].

El campo direccin es utilizado para indicar la direccin de la variables de red (entrada o salida). El
selector de variable de red es el identificador de variable de red asociado a la variable contenida en
el paquete de sesin.

2.1.5.8. Capa de aplicacin


La capa de aplicacin define un conjunto estndar de servicios de red para el intercambio de
datos entre dispositivos de distintos fabricantes. A continuacin se describen los grupos en los
cuales se clasifican los distintos servicios brindados por sta capa:

38

Configuracin de redes: provee un conjunto de comandos para configurar los parmetros


de red de los dispositivos.

Diagnstico de redes: provee un conjunto de comandos para que las herramientas de red
puedan diagnosticar problemas en la red.

Transferencia de archivos: soporta la transferencia de bloques de datos entre dispositivos


y herramientas de red.

Configuracin de aplicaciones: provee una interfaz estndar para configurar el


comportamiento de los dispositivos.

Especificacin de aplicaciones: provee un conjunto estndar de interfaces para


documentar las tareas que realiza un dispositivo. Cada tarea se expone como un bloque
funcional que se define como un conjunto de variables de red y propiedades de
configuracin del bloque.

Diagnstico de aplicaciones: provee una interfaz estndar para realizar pruebas sobre
bloques funcionales y dispositivos.

Administracin de aplicaciones: provee una interfaz estndar para activar, desactivar o


modificar bloques funcionales de un dispositivo.

Alarmas: provee una interfaz estndar que permite reportar advertencias.

Registro de datos: provee una interfaz estndar para la recoleccin de datos de los
dispositivos, que tambin pueden ser transferidos a otros dispositivos por medio de una
interfaz estndar.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Planificacin: provee una interfaz estndar para la planificacin de eventos basados en el


tiempo.

Administracin de fecha y hora: provee una interfaz estndar para sincronizar la fecha y
hora de los dispositivos dentro de una red.

2.1.6. HomePlug
Homeplug es el nombre para una familia de especificaciones sobre la implementacin de
redes de datos a travs del cableado elctrico existente en un hogar. La primera especificacin
creada de sta familia fue denominada HomePlug 1.0, pensada para reemplazar a las redes de
computadoras cableadas (par trenzado) e inalmbricas, aprovechando la red de electricidad existente
en un hogar. Dicha especificacin evolucion en HomePlug AV, que ampli la velocidad de
transferencia de la primera para permitir el transporte de audio, video y datos. De HomePlug AV,
deriv HomePlug Green PHY, orientada al ahorro de energa y el aumento de la interoperabilidad.

2.1.6.1. HomePlug 1.0


HomePlug 1.0 fue especificado para el funcionamiento sobre las redes de alimentacin
residencial. Define solamente dos capas de las propuestas por el modelo OSI: capa fsica y capa de
control de acceso al medio MAC. Tambin especifica dos interfaces: la interfaz de cableado entre el
dispositivo y la lnea de potencia (designado P1 en la figura 2.18), y la interfaz de uso de HomePlug
con la que interactan los protocolos de capas superiores del modelo OSI (designado M1 en la
figura 2.18).

Figura 2.18. Capas implementas [HomePlug1.0 ].

La capa fsica se compone de los bloques detallados en la figura 2.19. Recibe de la capa
superior datos e informacin de control, ambos con diferentes codificaciones. El esquema de
modulacin utilizado es OFDM, independientemente de la codificacin utilizada.

FernandoArielBeunza79156

39

Tesis de Grado en Ingeniera Informtica

Figura 2.19. Esquema del transceptor [HomePlug1.0 ].

La informacin de control es codificada aplicando un FEC implementado por un bloque codificador


de producto seguido de un bloque intercalador, que convierten 25 bits del paquete de control
original en cuatro smbolos OFDM de 84 bits por smbolo. En cambio los datos aplican otro FEC
ms complejo compuesto fundamentalmente por un codificador Reed Solomon y un codificador
convolucional, y el resultado final puede pasar por medio de un bloque intercalador o un bloque
ROBO, segn el grado de redundancia requerido para enviar la informacin. Luego de codificar la
informacin, segn el tipo que sea, es el tipo de modulacin que se aplica a cada portadora para
transmitir dicha informacin, siendo que para la informacin de control se emplea modulacin
BPSK, y para los datos pueden utilizarse DBPSK, DQPSK o ROBO. Del sistema de modulacin
utilizado, depende la velocidad de transferencia alcanzada, cuyo rango oscila entre 1 y 14 Mbps. El
smbolo OFDM utilizado se compone de 83 portadoras entre el rango de frecuencia de 4.5 a 20.7
MHz.
Los dispositivos HomePlug 1.0 estn pensado para servir de puente entre las redes de
informacin a travs de las lneas de potencia y otros tipos de redes de datos, como por ejemplo las
redes Ethernet. La capa de control de acceso al medio se encarga de proveer a la capa superior (otras
redes de datos) un mecanismo de transporte de datos por medio de las lneas de potencia de forma

40

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


confiable. Por ste motivo, la trama puede transportar entre 46 y 1500 bytes, ya que se adapta al
tamao que pueden tener los paquetes Ethernet.

Figura 2.20. Estructura de trama de capa de control de acceso al medio [HomePlug1.0].

En la figura 2.20 se describe la composicin de una trama utilizada por la capa de control de
acceso al medio, en donde se distinguen tres parte: un delimitador al comienzo, la trama
propiamente dicha y un delimitador final. El delimitador de comienzo comienza con un prembulo,
un indicador de comienzo de trama y 25 bits de informacin de control, en donde se indica entre
otras cosas, el tamao de la trama. La trama comienza con un encabezado de la misma, en donde se
encuentra informacin de control, direccin de origen y destino (48 bits cada una). Inmediatamente
se encuentra el campo donde se transporta los datos provistos por la capa superior, seguido de un
campo de relleno, y una suma de verificacin de 16 bits para deteccin de errores. Separado por un
intervalo de tiempo, se encuentra el delimitador final compuesto por un prembulo e informacin de
control.
Como el canal de comunicacin que brinda las lneas de potencia es nico con varios
dispositivos intentando hacer uso del mismo, es necesario la existencia de un mecanismo de control
de acceso al medio. HomePlug 1.0 utiliza CSMA/CA con un esquema de prioridad para determinar
que dispositivo tiene derecho a utilizar el canal en cada momento. Cuando varios dispositivos
desean enviar una trama, primero se verifica la prioridad de cada uno de ellos, los que posean la
prioridad ms alta entran al perodo de contencin, en donde de forma aleatoria se determina el
quien gana el derecho de utilizar el canal de comunicacin. En la figura 2.21 se puede observar
como transcurre en el tiempo el proceso anterior.

Figura 2.21. Control de acceso al medio [HomePlug1.0].

El perodo de resolucin de prioridad (PRS0 y PRS1), implementan un esquema de prioridad basado


en cuatro niveles posibles. El perodo de Backoff es donde se desarrolla la contencin que termina
resolviendo que dispositivo hace uso del canal de comunicacin.
FernandoArielBeunza79156

41

Tesis de Grado en Ingeniera Informtica


La capa de control de acceso al medio tambin implementa un esquema de fragmentacin y
reensamblado para poder soportar el envo de paquetes de informacin, provenientes de la capa
superior, cuya longitud supera la capacidad mxima que brinda la capa de control de acceso al
medio. Un paquete puede transportar entre 210 y 1680 bytes, lo que permite encapsular un paquete
Ethernet sin necesidad de fragmentacin.
Los dispositivos se agrupan en redes lgicas, pudiendo existir varias de stas ltimas sobre
una misma red elctrica. Cada red lgica tiene asociada una clave, utilizada por los dispositivos para
el envo de paquetes, ya que stos se envan encriptados. Todos los dispositivos pertenecientes a una
red lgica deben conocer la clave. Un dispositivo que quiera pertenecer a una red lgica debe
conocer la clave, suministrada por el usuario del dispositivo, o por otro dispositivo que conozca la
clave. Para la segunda alternativa, la clave es enviada por medio de un paquete encriptado con una
clave que conocen los dos dispositivos involucrados.

2.1.6.2. HomePlug AV
HomePlug AV fue pensado para cubrir los requerimientos de las redes orientadas a
entretenimiento (audio, video y datos) utilizando el cableado de electricidad existente en un hogar.
Al mismo tiempo HomePlug AV brinda la posibilidad de coexistir con HomePlug 1.0 y servicios de
BPL.
La arquitectura de HomePlug AV (figura 2.22) se encuentra preparada para aceptar paquetes
Ethernet por medio de la interfaz H1, lo que permite utilizar adaptar cualquier protocolo basado en
IP a la tecnologa HomePlug AV. Existen dos planos diferentes dentro de la arquitectura: el plano de
datos y el plano de control. El primer plano se conforma siguiendo el modelo tradicional de capas,
capa de control de acceso al medio y capa fsica, con un capa de Convergencia por encima de la
pila de protocolos. El segundo plano se conforma de un Administrador de Conexiones y un
Coordinador Central, aunque l ltimo slo se encuentra activo en una de las estaciones de la red.

Figura 2.22. Arquitectura HomePlug AV [HomePlugAV].

La capa fsica trabaja sobre el rango de frecuencias comprendido entre los 2 y 28 MHz,
empleando OFDM con 917 portadoras utilizables, combinado con un cdigo convolucional turbo
TCC. Los mtodos de modulacin empleados para las portadoras varias desde BPSK hasta 1024
QAM . Todas estas caractersticas mencionadas logran una velocidad de transferencia de 200 Mbps.
El transmisor se encuentra ligado a la capa de control de acceso al medio por tres entradas
diferentes: HomePlug 1.0, HomePlug AV (control) y HomePlug AV (datos). La primera existe para
garantizar la compatibilidad con el protocolo HomePlug 1.0. Las dos restantes responden a los dos
42

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


planos mencionados anteriormente, uno referidos a los datos y otro al control. En cambio, el
receptor se encuentra diseado para recibir por un lado todo lo referente a HomePlug 1.0, y por el
otro todo lo referente a HomePlug AV (datos y control) de forma conjunta. Los bloques que
componen tanto el transmisor como el receptor se detallan en la figura 2.23.

Figura 2.23. Esquema del transmisor y receptor [HomePlugAV].

La capa de control de acceso al medio de HomePlug AV tiene la capacidad de brindar


servicios orientados a la conexin libre de contencin, garantizando ancho de banda para
aplicaciones de audio y video basado en el mecanismo de TDMA. Tambin ofrece servicios no
orientados a la conexin con contencin y esquema de prioridad, para aplicaciones que slo
requieran comunicaciones del tipo mejor esfuerzo, basado en el mecanismo CSMA/CA. Para proveer
de forma eficiente los servicios anteriores, HomePlug AV implementa una arquitectura flexible
centralmente administrada, por medio del Coordinador Central (figura 2.22). Dicho coordinador es
el encargado de establecer el perodo de sealizacin y como se ubican temporalmente cada tipo de
servicio provisto (figura 2.24).

FernandoArielBeunza79156

43

Tesis de Grado en Ingeniera Informtica

Figura 2.24. Distribucin temporal de cada tipo de servicio [HomePlugGP].

La figura anterior muestra como se compone el perodo de sealizacin, existiendo tres regiones:
regin de sealizacin, regin CSMA y regin reservada. El perodo de sealizacin comienza un
instante luego de la deteccin de cruce por cero de la seal de potencia, siendo durante la primer
regin en donde el Coordinador Central transmite la organizacin del perodo de sealizacin. La
siguiente regin se reserva para el trfico que utiliza contencin. Por ltimo, la regin reservada, es
un perodo de tiempo libre de contencin donde se emplea TDMA.
La capa de control de acceso tambin contiene un Administrador de Conexiones encargado
de recibir las especificaciones de calidad de servicio requeridas de la capa superior a HomePlug AV,
y en base a sto determinar que tipo de servicio de los provistos conviene utilizar (CSMA o TDMA).
Tambin debe controlar si la calidad de servicio brindada corresponde a la solicitada, que en caso de
no ser as, el Administrador de Conexiones debe aplicar las correcciones necesarias para cumplir
con lo solicitado.
La capa de Convergencia se encarga de encapsular los paquetes de datos provenientes de la
capa superior a HomePlug AV, agregndoles un encabezado y una suma de verificacin,
conformando un paquete MAC. ste ltimo paquete, para ser transmitido, es particionado en
fragmentos de 512 bytes de longitud. Cada fragmento es encriptado y encapsulado dentro de un
paquete de capa fsica, para luego ser enviado a su destino. En el receptor, se lleva a cabo los pasos
inversos a los anteriores (desencriptacin y reeensamblaje), y el paquete recibido es despachado por
la capa de Convergencia hacia la capa superior.
Sobre la red elctrica de un hogar pueden existir varias redes lgicas conformadas por
distintos dispositivos. Cada una de stas redes lgicas tiene asociado una clave utilizada para el
encriptado de los paquetes que intercambian de forma segura los diferentes dispositivos de la red
lgica.
Otro elemento importante que poseen las redes lgicas es un Coordinador Central. Cada una
de stas redes presenta un coordinador. La funcin de un Coordinador Central es administrar el
ancho de banda de la red al cual pertenece, y controlar la admisin de nuevos dispositivos a la red
lgica.

2.1.6.3. HomePlug Green PHY


Una red inteligente se define como la entrega de electricidad desde los proveedores hasta
los consumidores utilizando dos vas de comunicacin digital para el control de los aparatos en los
hogares de los consumidores, ahorro de energa, reducir costos y aumentar la fiabilidad y
transparencia [HomePlugGP].
44

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Un sistema de comunicaciones confiable, que est presente en todas partes, es un elemento
fundamental para la implementacin exitosa de una red inteligente. Debido a los diferentes
requisitos existentes dentro de un hogar y la red de servicios pblicos, es necesario dividir las
comunicaciones en dos partes: WAN (servicios pblicos de electricidad hacia el exterior) y HAN
(electricidad hacia el interior).
La implementacin de redes inteligentes hasta la fecha ha demostrado el gran potencial que
tienen los usuarios de participar activamente en la conservacin de energa y reducir
significativamente su el uso de electricidad en general.

Figura 2.25. Esquema de red inteligente [HomePlugGP].

Una de las diferencias ms importantes entre redes WAN y HAN, es que en las primeras las
aplicaciones que hacen uso de la red tiene ms libertad para la adopcin de estndares, cosa que no
ocurre en HAN, ya que la amplia gama de dispositivos que pueden estar presentes en un hogar
requieren, para que puedan interoperar sin inconvenientes, la adopcin de estndares ampliamente
aceptados por todos los fabricantes.
Las especificaciones HomePlug Green PHY han sidos diseadas especficamente para
soportar aplicaciones sobre redes del tipo HAN, sin afectar a otras aplicaciones existentes dentro del
hogar. Dichas especificaciones derivan de HomePlug AV, lo que permite la interoperabilidad con el
estndar IEEE P1901 [IEEEP1901].
La capa fsica de Home Plug Green PHY trabaja con un esquema de modulacin OFDM
dentro del rango de frecuencias de 2 a 30 MHz. Las subportadoras empleadas son 1155, con una
separacin entre subportadoras de 24,414 KHz, y moduladas utilizando QPSK. La velocidad
mxima de transferencia que puede alcanzar es de 10 Mbps, implementando varios modos ROBO,
pudiendo bajar dicha velocidad mxima a 5 Mbps y 4 Mbps ganando confiabilidad, con el agregado
del mtodo FEC cdigo turbo . Comparado con Home Plug AV, las caractersticas anteriores
parecen un retroceso (un solo esquema de modulacin de subportadora, velocidad de transferencia
menor, implementacin de un slo mtodo FEC), pero viene de la mano de una reduccin de costos,
de consumo de los dispositivos y de una mayor interoperabilidad.
En cuanto a la capa de enlace de Home Plug Green PHY, resulta bsicamente en una
simplificacin de la versin implementada en Home Plug AV, conservando el mismo mtodo CSMA
y el mecanismo de prioridad, pero perdiendo en mecanismo opcional de TDMA.

FernandoArielBeunza79156

45

Tesis de Grado en Ingeniera Informtica

2.2. Redes en automviles


Los automviles hace tiempo requieren de redes para interconectar los diferentes
dispositivos que los constituyen. El nmero de dispositivo va en aumento a medida que las
regulaciones se hacen mas exigentes y los usuarios requieren cada da ms un mayor nivel de
equipamiento. La utilizacin de cableado dedicado para cada dispositivo, en la actualidad, con el
gran nmero de dispositivos presentes en un automvil, hace de sta una alternativa costosa. Se
requiere de una forma de interconexin de los dispositivos que utilice una menor cantidad de
cableado (por ejemplo topologa bus o anillo). Trabajar con un medio fsico compartido por varios
dispositivos, vuelven ms complejas a las comunicaciones entre ellos. Pero sto ltimo, puede ser
resuelto con la introduccin de microcontroladores cada vez ms poderosos y econmicos, haciendo
que la ltima alternativa frente a la primera.
Ya analizado el estado del arte de la tecnologa PLC, es necesario estudiar los estndares
existentes en redes de automviles que no utilizan como medio fsico la tecnologa PLC, ya que
algunas ideas que proponen pueden ser de utilidad para la integracin de ambas tecnologas.

2.2.1. CAN
El estndar CAN fue desarrollado por la empresa Robert Bosch GmbH a principios de la
dcada de los 90, con el objeto de proveer un esquema de comunicaciones que soporte sistemas de
control distribuido. ste estndar originalmente se encontraba orientado a la industria automotriz,
pero con el tiempo tambin fue adoptado por la industria en general.
Las especificaciones del estndar CAN se componen de dos partes conocidas como parte A y
parte B. La parte A se encarga de definir el formato estndar de mensaje compatible con versiones
anteriores. La parte B define el formato estndar y extendido de mensaje.

2.2.1.1. Modelo de capas


CAN adopta el modelo de capas como lo hacen otros estndares. Comparando CAN con el
modelo de capas propuesto por OSI, CAN solamente define la capa fsica y la capa de enlace. La
parte A (figura 2.26) define tres capas: fsica, transferencia y objeto; siendo stas dos ltimas
equivalentes a la capa de enlace del modelo OSI. La parte B (figura 2.27) toma la misma
organizacin que emplea OSI, y define las capas fsica y de enlace, sta ltima dividida en dos
subcapas: control de acceso al medio (llamada MAC) y control de enlace lgico (llamada LLC).

46

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 2.26. Modelo de capas propuesto por CAN A Figura 2.27. Modelo de capas propuesto por CAN B
[Bosch91].
[Bosch91].

Respecto a la capa fsica, CAN no define especficamente el medio fsico utilizado como
canal de comunicacin. De las diferentes variantes existentes, en el presente trabajo se tratar la que
emplea cable par trenzado como canal de comunicacin, en donde las seales son codificadas
utilizando tensin diferencial.
La capa de enlace es la responsable del armado y desarmado de los mensajes, de la deteccin
de errores, de controlar el acceso al medio (resolver el arbitraje), el filtrado de mensajes, entre otras
funciones.

2.2.1.2. Capa fsica


La capa fsica de CAN se compone de tres subcapas (figura 2.48): sealizacin fsica,
acoplamiento al medio fsico e interfaz dependiente del medio. El estndar slo define la subcapa de
sealizacin fsica en donde se especifica la codificacin de los bits, la duracin de los mismos y el
mecanismo de sincronizacin Las restantes subcapas son dependientes del medio fsico utilizado.
En el presente trabajo se estudiar el medio definido por la norma ISO 11898-2.

FernandoArielBeunza79156

47

Tesis de Grado en Ingeniera Informtica

Figura 2.28. Subcapas que conforman la capa fsica de CAN [Zeltwanger].

Las redes CAN presentan topologa tipo bus, en donde la longitud del cable y la velocidad de
transferencia se encuentran estrechamente relacionadas. La utilizacin de tensin diferencial sobre
par trenzado le brinda mayor inmunidad al ruido electromagntico aumentando la confiabilidad. El
bus requiere del agregado de dos resistencias de 120 ohms en los extremos del mismo para eliminar
los reflejos de seal. Un bus CAN es capaz de soportar hasta 30 dispositivos. En la figura 2.29 se
puede observar un ejemplo de como se constituye una red CAN.

Figura 2.29. Configuracin de una red CAN [StrangRckl].

Las velocidades de transferencia que soporta CAN estn comprendidas en el rango de los 10 Kbps a
1 Mbps. La velocidad est dada por el tiempo de duracin del bit empleado que sta en relacin a la
longitud de bus. En la tabla 2.15 se puede observar la relacin que existe entre la velocidad de
transferencia, la longitud del bus y el tiempo de duracin del bit.
Velocidad de
transferencia

Longitud
del bus

Duracin
del bit

1 Mbps

30 metros

1 microsegundo

800 Kbps

50 metros

1,25 microsegundos

500 Kbps

100 metros

2 microsegundos

250 Kbps

250 metros

4 microsegundos

125 Kbps

500 metros

8 microsegundos

62,5 Kbps

1000 metros

20 microsegundos

20 Kbps

2500 metros

50 microsegundos

10 Kbps

5000 metros 100 microsegundos

Tabla 2.15. Relacin entre velocidad de transferencia, del longitud del bus y el tiempo de duracin del bit
[Zeltwanger]

48

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Segn la clasificacin de redes propuesta por SAE sobre la clasificacin de redes, se puede decir que
los buses de longitud mayor a 500 metros entran dentro de la clase B (aplicaciones de propsito
general), y los de longitud inferior a 500 metros entran dentro de la clase C (aplicaciones de control
en tiempo real). La relacin entre velocidad y longitud muestra un cada exponencial (figura 2.30) a
medida que crece la longitud del cable utilizado en el bus.

Figura 2.30. Velocidad de transferencia en funcin de la longitud del bus [Zeltwanger].

Los smbolos utilizados por CAN para codificar los valores de los bits permiten la existencia
de un valor dominante sobre un recesivo. En ste caso particular el smbolo utilizado para el valor
de bit cero corresponde al dominante, mientras que el valor uno corresponde al recesivo. ste
esquema permite que en todo momento se pueda leer un estado vlido del bus (colisin no
destructiva). sto es necesario, ya que CAN basa su sistema de resolucin de colisiones en la
existencia de un estado dominante sobre uno recesivo, como se explicar ms en detalle cuando se
hable sobre la capa de enlace.

2.2.1.3. Capa de enlace


Las funciones bsicas que cumple la capa de enlace implementada por CAN consisten en
controlar el acceso al nico medio de comunicacin (el bus de datos), armar y desarmar tramas, y
garantizar que los datos lleguen a su destino libre de errores.
Una red CAN es una red multimaestro, es decir que no hay ningn dispositivo que tenga
funciones especiales sobre el resto encargadas de la administracin de la red. Todos los dispositivos
son capaces de hacer uso del bus para intercambiar informacin con otros dispositivos, siguiendo
reglas sobre el uso del nico medio de comunicacin disponible (mecanismo de control de acceso al
medio).
El mecanismo de control de acceso al medio propuesto por CAN se basa en un sistema de
prioridad mediante el cual se establece la urgencia de envo que presenta cada trama. sto se
combina con el mtodo de acceso al medio CSMA/CR, que consiste en la deteccin y resolucin de
las colisiones de tramas. El esquema propuesto por CAN, consiste en que los dispositivos que
desean transmitir en un determinado instante, lo hagan, y mientras emiten los bits de la trama
escuchen el canal de comunicacin. Como existe un estado dominante y uno recesivo, siempre los
dispositivos detectarn un estado vlido en todo momento. En caso de que un dispositivo que se
encuentre transmitiendo, detecte un estado del canal distinto al valor del bit emitido, ste cesa la
transmisin, y comienza a recibir todos los bits que escucha del canal. sto ltimo se va repitiendo
con el resto de los dispositivos que se encuentran transmitiendo en simultneo, hasta que solamente
FernandoArielBeunza79156

49

Tesis de Grado en Ingeniera Informtica


quede uno, quien es el ganador del arbitraje. Cuando el ganador del arbitraje termina de transmitir
su trama, el resto de los dispositivos que perdieron la contienda, tienen una nueva trama recibida
proveniente del ganador del arbitraje. Los perdedores del arbitraje deben repetir el intento de envo
de sus respectivas tramas hasta que logren ganar el acceso al bus de datos. Para que ste esquema
funcione, cada trama debe comenzar con una secuencia de bits que sea diferente en todas las tramas.
sta secuencia constituye el campo de arbitraje de la trama, y con el esquema de bit dominante y
recesivo, el dispositivo ganador del arbitraje siempre ser quien est enviando la trama de mayor
prioridad (todos los bits con valor cero tienen la mxima prioridad y todos los bits con valor uno
tiene la mnima prioridad).

Figura 2.31. Ejemplo de arbitraje [Zeltwanger].

En la figura 2.31 se puede observar un ejemplo de funcionamiento del mtodo de control de acceso
al medio por prioridad. Como se puede ver existen tres dispositivos transmitiendo en simultneo. El
primer dispositivo en abandonar la contienda es el nmero 2, ya que ste emite un bit de valor uno
mientras que el resto emiten un bit de valor cero. Luego el siguiente en abandonar la contienda es el
dispositivo 1, quedando solamente el dispositivo nmero 3 quien continua transmitiendo hasta el
final de la trama. ste sistema no solamente resuelve las contienda en forma no destructiva, sino que
tambin garantiza un tiempo determinstico para el envo de las tramas, ya que el tiempo que
demora la transmisin de las tramas depende de la prioridad de los mismos.
Una de las caractersticas particulares de CAN que la diferencia de otras redes, es que no
existe el concepto de direccin de dispositivo. Lo nico que existe es el identificador de trama, que
los dispositivos son capaces de filtrar, y de sta forma pueden determinar que tramas procesar. ste
esquema de identificacin permite a CAN ser muy flexible en el agregado de nuevos dispositivos a
la red, ya que no requiere de configuracin de los mismos. Adems el identificador de trama forma
parte del campo de arbitraje de la trama, permitiendo que stas puedan ser asociadas a funciones,
siendo algunas ms crticas que otras, pudiendo asignar mayor prioridad a las funciones crticas.
Puede decirse tambin que cada identificador constituye una direccin de multicast debido a que el
destinatario de una trama puede ser un dispositivo o un grupo de dispositivos, adems de existir una
direccin de broadcast para el envo de tramas a todos los dispositivos del bus.
La estructura de una trama utilizada por CAN para el envo de datos, bsicamente es similar
tanto para la parte A como para la parte B. La diferencia existe en que la parte B implementa una
estructura de mensaje extendido que permite utilizar identificadores de mensaje ms extensos. La
estructura de mensaje propuesta por la parte A se puede observar en la figura 2.32, mientras que las
estructuras definidas por la parte B pueden verse en la figura 2.33 (mensaje estndar) y la figura
2.34 (mensaje extendido).

50

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 2.32. Estructura de trama estndar utilizada por CAN parte A [Reuss93].

Figura 2.33. Estructura de trama estndar utilizada por CAN parte B [Reuss93].

Figura 2.34. Estructura de trama extendida estndar utilizada por CAN parte B [Reuss93].

Una trama comienza con un bit de comienzo de trama (SOF) para indicar el comienzo de la misma,
seguida de un identificador de 11 bits, seguido de un grupo de indicadores (varan segn la
estructura de trama), y 4 bits que indican la cantidad de datos que transporta el mensaje (DLC). A
continuacin se encuentran los datos que pueden ocupar de 0 a 8 bytes, segn lo especificado en el
campo DLC. Luego de los datos se encuentra un cdigo de deteccin de errores CRC de 15 bits, un
bit indicador de fin del cdigo CRC, 2 bits de ACKN utilizado por los receptores para indicar la
correcta recepcin, y por ltimo 7 bits que indica el fin de la trama (EOF). El bit de RTR presente en
todas las estructuras de tramas es utilizado para indicar si la trama es de datos (valor cero) o es una
trama remota (valor uno). El bit de IDE solamente existen en las tramas de la parte B para indicar si
en mensaje es estndar (valor cero) o extendido (valor uno). El bit SRR solamente se encuentra en la
trama extendida de la parte B, y su finalidad debe a razones de compatibilidad con la trama estndar
(reemplaza al bit RTR). Los bits destinados al identificador de trama y el bit RTR constituyen el
campo de arbitraje utilizado para resolver colisiones.
Adems de la trama utilizada para el envo de datos, existen otro tipo de tramas. La trama
remota tiene una estructura similar a la de datos pero sin el campo de datos, y es enviada cuando un
dispositivo requiere que le enven una trama de datos con el mismo identificador. Tambin existen
otras tramas como la trama de error, enviada cuando un dispositivo detecta un error en el bus, y la
trama de sobrecarga, enviada cuando un dispositivo se encuentra sobrecargado y necesita un tiempo
adicional para terminar de procesar la ltima trama recibida.
A cualquier tipo de trama, una vez armada, se le adiciona cada 5 bits consecutivos de igual
valor uno de diferente valor (tcnica de bit stuffing). Luego se le aplica codificacin NRZ (Non
Return to Zero), y finalmente se enva.
Los dispositivos slo procesan tramas recibidas sin error. Cuando un dispositivo enva una
trama, emite una secuencia de dos bits de valor uno en el campo ACKN de la trama. Cuando uno o
varios de los dispositivos receptores detectan un error por medio del cdigo CRC, stos fuerzan una
secuencia de bits 01 que colisionan con la secuencia original indicando la presencia de un error
error de recepcin, forzando a los dems dispositivos receptores a no procesar la trama (aunque la
recepcin haya sido correcta), y a que el emisor vuelva a reenviar la trama. El mecanismo de
confirmacin de recepcin descripto permite que CAN brinde un servicio de comunicacin multicast

FernandoArielBeunza79156

51

Tesis de Grado en Ingeniera Informtica


confiable (una trama es recibida de forma correcta por todos los receptores o por ninguno en caso de
error).
Los dispositivos tiene la capacidad de aislar fallas para no afectar el funcionamiento de la
red entera. Cada dispositivo presenta un contador de errores, que cuando supera cierto lmite
preestablecido, provoca la desconexin lgica del dispositivo (no recibe ninguna trama enviada ni
interviene en la confirmacin de recepcin).

2.2.2. J1850
El estndar J1850 fue reconocido por SAE en el ao 1994, como una red para automviles
clase B (segn clasificacin empleada por SAE). La idea de ste estndar es proponer una
arquitectura abierta de bus de datos de topologa simple de bajo costo, que no necesitara de un
dispositivo maestro para administrar el bus.

2.2.2.1. Modelo de capas


J1850 como otros estndares implementa una serie de capas que pueden ser comparadas con
el modelo OSI. El objetivo de las capas es resolver los problemas relacionados con el proceso de
comunicacin en diferentes niveles. En la figura 2.35 se puede observar el modelo de capas
propuesto por J1850, en los cuales se implementan tres capas de las siete propuestas por el modelo
OSI.

52

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 2.35. Modelo de capas propuesto por J1850 [SAE94].

Como se puede observar en la figura anterior J1850 establece que la capa de aplicacin es la
encargada de definir los tipos de mensajes, cdigos de diagnstico y parmetros; de sta forma
todos los dispositivos interactan por medio de una interfaz nica permitiendo la interoperabilidad
entre diferentes fabricantes de dispositivos. La capa de enlace se encarga de controlar el acceso al
medio, resolviendo los conflictos que puedan existir cuando varios dispositivos intenten hacer uso
del canal de comunicacin, y de permitir el flujo de datos libre de errores. La capa fsica es la
encargada de codificar los datos empaquetados por la capa de enlace a travs de seales elctricas,
existiendo dos variantes posibles, cada una con sus caractersticas fsicas particulares.

FernandoArielBeunza79156

53

Tesis de Grado en Ingeniera Informtica

2.2.2.2. Capa fsica


El estndar propone dos formas de codificar los datos en seales elctricas. La primer
variante es la llamada VPW, que codifica los datos empleando ancho de pulso variable. La figuras
2.36 y 2.37 muestran los smbolos utilizados para codificar un bit de valor cero y un bit de valor
uno, respectivamente. A su vez existen dos modos de codificacin, la denominada pasiva (a la
izquierda de las figuras 2.36 y 2.37), y la denominada activa (a la derecha de las figuras 2.36 y
2.37). El modo pasivo viene dado por la forma de representar el smbolo utilizando el nivel bajo de
tensin. El modo activo, al contrario del modo pasivo, emplea el nivel alto de tensin. En ambos
modos, existe el concepto de bit dominante y recesivo, en el cual, ante una colisin de bits, el valor
dominante prevalece sobre el valor recesivo. El valor del bit dominante es cero, mientras que el
valor del bit recesivo es uno, independientemente del modo utilizado. Empleando stos smbolos,
J1850 VPW puede transferir datos a una velocidad de 10,4 Kbps.

Figura 2.36. Codificacin de bit valor cero utilizado Figura 2.37. Codificacin de bit valor uno utilizado
por J1850 VPW [SAE94].
por J1850 VPW [SAE94].

La otra variante llamada PWM, emplea modulacin de ancho de pulso para la codificacin
de los datos. En la figura 2.38 se puede observar el smbolo utilizado para codificar un bit de valor
cero, y en la figura 2.39 se puede observar el smbolo empleado para codificar un bit de valor uno.
En J1850 PWM tambin existe el concepto de dominante y recesivo, en este caso un bit de valor
cero es dominante frente a un bit de valor uno, ya que para el primero se emplea un pulso ms ancho
que para el segundo. Gracias a stos smbolos, J1850 PWM puede transferir datos a una velocidad
de 41,6 Kbps.

Figura 2.38. Codificacin de bit valor cero utilizado Figura 2.39. Codificacin de bit valor uno utilizado
por J1850 PWM [SAE94].
por J1850 PWM [SAE94].

Los mecanismos de codificacin de bits anteriores tiene en comn el concepto de bit


dominante y recesivo. sto es necesario para el mecanismo de resolucin de colisiones
implementado por la capa de enlace.
La topologa de red propuesta por J1850 consiste simplemente en una lnea a la cual se
conectan todos los dispositivos del automvil. La longitud mxima que puede alcanzar la lnea es de
35 metros dentro del automvil, y 5 metros fuera de l, que se pueden combinar alcanzando los 40
metros en total. La cantidad mxima de dispositivos que pueden ser conectados a la lnea es 32,
incluyendo tambin a los dispositivos que pueden encontrarse fuera del automvil. La lnea
utilizada puede estar constituida por un solo cable (J1850 VPW) o por dos cables (J1850 PWM).

54

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

2.2.2.3. Capa de enlace


Una de las funciones que tiene la capa de enlace es controlar el acceso al canal de
comunicacin. Al ser el bus de datos, el nico medio que poseen todos los dispositivos para
transmitir informacin, es necesario establecer un protocolo que determine que dispositivo
transmite cuando existen varios dispositivos queriendo hacer lo mismo. El protocolo propuesto por
J1850 es similar al utilizado por CAN, se basa tambin en un esquema de prioridades para el envo
de mensajes utilizando el concepto de bit dominante y recesivo, para resolver que dispositivo
continua transmitiendo y que dispositivo cesa su transmisin. En las figuras 2.40 y 2.41 se pueden
observar ejemplos de resolucin de colisiones para J1850 VPW y J1850 PWM.

Figura 2.40. Ejemplo de arbitraje J1850 VPW [SAE94].

Figura 2.41. Ejemplo de arbitraje J1850 PWM [SAE94].

El protocolo de resolucin de colisiones se basa en que los dispositivos pueden enviar bits y
escuchar el canal en forma simultnea. Varios dispositivos pueden comenzar en un determinado
momento a transmitir un mensaje. Cada mensaje tiene un encabezado constitudo por un campo de
prioridad que especifica la prioridad del mensaje. Los bits de prioridad, como el resto de la
informacin, es codificada empleando cualquiera de las variantes propuestas por J1850 (VPW o
PWM). A medida que los dispositivos transmiten y detectan en el canal de comunicacin diferencias
entre lo enviado y recibido, los dispositivos cesan sus transmisiones, hasta que uno ellos quede
transmitiendo hasta el final del mensaje, porque que no detect diferencias. stas diferencias
pueden ser detectadas gracias a que existe un valor de bit que es dominante sobre el otro,
permitiendo en todo momento, que a pesar de la colisin de seales, siempre se pueda establecer el
valor del bit.
Un mensaje se encuentra compuesto por cinco partes: un indicador de comienzo de mensaje
(llamado SOF), un encabezado, un campo de datos, un cdigo de deteccin de errores CRC y un
FernandoArielBeunza79156

55

Tesis de Grado en Ingeniera Informtica


indicador de fin de mensaje (llamado EOF). stas partes se disponen conforme lo muestra la figura
2.42.

Figura 2.42. Estructura de mensaje [Oliver].

Los indicadores de comienzo y fin de mensaje son delimitadores que avisan a los receptores cuando
comienza y termina un mensaje. El encabezado de contiene informacin de control detallada en la
figura 2.43.
Prioridad
3bits

Tipode
Modode
Tipode
IFR
encabezado
direccionamiento mensaje
1bit

1bit

1bit

2bits

Figura 2.43. Estructura de encabezado de mensaje.


Prioridad
3bits

Tipode
Modode
Tipode Direccin Direccin
IFR
encabezado
direccionamiento mensaje deorigen dedestino
1bit

1bit

1bit

2bits

8bits

8bits

Figura 2.44. Estructura de encabezado extendido de mensaje.

La prioridad especifica la prioridad que presenta el mensaje y se utiliza para la resolucin de


colisiones. El tipo de encabezado indica si el mensaje emplea el encabezado comn (figura 2.43) o
el extendido (figura 2.44). El encabezado extendido tiene una longitud de 3 bytes, el primer byte
corresponde al encabezado comn y el resto de los bytes se destina a la direccin del dispositivo que
dio origen al mensaje y a la direccin a quien se destina el mensaje. El campo IFR indica si el
mensaje requiere de una respuesta o no. El modo de direccionamiento indica si el mensaje
especifica como destino una direccin fsica o una direccin funcional. El tipo de mensaje
especifica el tipo de mensaje enviado que se encuentra relacionado con el IFR y el modo de
direccionamiento. La longitud mxima que puede tener un mensaje, incluyendo informacin de
control, es de 12 bytes.
Existen dos tipos de direcciones que se pueden especificar en los mensajes: las fsicas y las
funcionales. Las direcciones fsica identifican a dispositivos en particular y son nicas, no hay dos
dispositivos con la misma direccin. Son utilizadas cuando un dispositivo quiere enviar un mensaje
a otro en particular. Las direcciones funcionales identifican a una funcin que puede ser ejecutada
por varios dispositivos, lo que implica que un mensaje con este tipo de direccin puede tener varios
destinatarios. Cada dispositivo tiene definido un conjunto de funciones, y a partir de ste conjunto la
capa de aplicacin decide que mensaje es aceptado.

2.2.2.4. Capa de aplicacin


La capa de aplicacin implementa una interfaz que permite la transferencia de informacin
de uno dispositivo a otros. Los dispositivos intercambian informacin por medio de mensajes.
Existen dos grupos de mensajes: los mensajes en modo normal de operacin definidos en el
estndar SAE J2178 y los mensajes de diagnstico definidos en los estndares SAE J1979 y SAE
56

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


J2190. Tambin sta capa implementa una serie de cdigos de falla asociados a un conjunto de
averas definidas en el estndar SAE J2012.
Otra funcin que brinda est capa es la de filtrado de mensajes. Debido a que los mensajes
enviados por medio del bus de datos son recibidos en todos los dispositivos, pueden que stos no
estn interesados en todos los mensajes. Para evitar la sobrecarga de trabajo de los dispositivos, se
dispone de un mecanismo de filtrado que permita discriminar los mensajes por medio de un
identificador.

2.2.3. OSEK/VDX
El proyecto OSEK fue iniciado en el ao 1993 por un conjunto de empresas pertenecientes a
la industria del automvil alemana. El objetivo principal del proyecto es proponer una arquitectura
de control distribuido dentro de los automviles que sea abierta, para que diversos fabricantes
puedan desarrollar dispositivos que sean interoperables entre s. Las empresas francesas PSA y
Renault tambin se encontraban trabajando en un proyecto similar llamado VDX, y se fusionaron al
proyecto OSEK en el ao 1994, conformando un nico estndar llamado OSEK/VDX.

2.2.3.1. Arquitectura
El estndar OSEK/VDX define un conjunto de interfaces que permiten el desarrollo de
componentes de software porttiles y reutilizables. La idea del estndar es abstraer la aplicacin del
hardware utilizado en los dispositivos interconectados a travs de una red. Una aplicacin interacta
con la interfaz, lo que permite el desarrollo del estndar para diversas plataformas y la evolucin del
mismo, sin necesidad de modificar la aplicacin. En la figura 2.45 se puede observar la arquitectura
propuesta por el estndar.

Figura 2.45. Arquitectura de OSEK/VDX [LeenHeffernanDunne].

FernandoArielBeunza79156

57

Tesis de Grado en Ingeniera Informtica


Si se compara el modelo OSI con la arquitectura de OSEK/VDX, se puede observar que OSEK/VDX
implementa las capa de enlace y de red. La aplicacin interacta por medio de la interfaz de
comunicacin y la interfaz de red, con la capa de interaccin y el Administrador de Red,
respectivamente. La capa de interaccin se encuentra al tope de la pila de capas constituidas por la
capa de red y de enlace. El Administrador de Red interacta con la capa de interaccin y con la capa
de enlace. Finalmente la capa de enlace interacta con el medio fsico de conexin por medio del
hardware de comunicacin (capa fsica del modelo OSI).

2.2.3.2. Implementacin
OSEK/VDX implementa un entorno de trabajo distribuido dentro de un vehculo, basndose
en los mismos principios utilizados para implementar entornos distribuidos que operan dentro de las
redes de datos de gran tamao. De ste modo se pretende reducir costos en la creacin de software
reutilizable. Pero la flexibilidad de OSEK/VDX requiere de memorias ROM y RAM adicionales,
adems de sobrecargar a los procesadores. La clave del xito de ste modelo depende que los costos
adicionales de hardware sean absorbidos por el ahorro asociado por la implementacin de software
reutilizable.

Figura 2.46. Indepedencia de OSEK/VDX [LeenHeffernanDunne].

Tambin OSEK/VDX puede ser visto como un sistema operativo desarrollado para diversas
plataformas de procesador, soportar diversas interfaces de comunicacin y servir a mltiples
aplicaciones. Como todo sistema operativo, OSEK/VDX debe administrar las diferentes tareas que
se encuentren en ejecucin, procesar las diferentes solicitudes de interrupcin, proveer mecanismos
de comunicacin entre procesos en ejecucin y brindar tratamiento a los errores que ocurran.
El estndar por s mismo no especifica como se llevan a cabo las comunicaciones entre
dispositivos, como lo hacen otros estndares, sino que define un esquema multiplataforma que
puede complementarse con distintos estndares de comunicacin existentes como CAN y J1850.

2.2.4. LIN
Las redes LIN fueron pensadas para ser redes de bajo costo, como complemento de otras
redes presentes en un automvil. La idea surge del principio que dentro de un automvil se
disponen de una gran cantidad de dispositivos, siendo algunos de baja complejidad (como por
58

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


ejemplo, una tecla de levantavidrios); e interconectar este tipo de dispositivos por medio de una red
como CAN o J1850, los haran ms complejos y costosos. Adems stos dispositivos tienden a
agruparse en determinados sectores de un automvil (la tecla de levantavidrios se encuentra en la
puerta muy prxima del motor que ejecuta la accin de subir y bajar el vidrio). Entonces la
propuesta de LIN es crear una red de bajo costo y simple que permita interconectar dispositivos muy
prximos entre s, y que tambin permita las comunicaciones con dispositivos distantes empleando
pasarelas conectadas a una red de cobertura ms amplia como CAN o J1850 (con la tecla de
levantavidrios de una puerta controlar la ventanilla de otra puerta).

2.2.4.1. Capa fsica


La capa fsica de LIN especifica como debe ser el medio fsico de comunicacin, la interfaz
elctrica que debe implementar un dispositivo para poder conectarse, los valores de tensin
utilizados para codificar los bits de informacin, y las velocidades de transferencia permitidas.
Un bus LIN se encuentra constituido por un nico cable, conformando una red de topologa
lineal. El bus puede tener una longitud mxima de 40 metros, y puede soportar hasta 16 dispositivos
conectados. Sobre ste bus, los diferentes dispositivos conectados, pueden transmitir y recibir,
empleando una interfaz cuyo esquema bsico puede observarse en la figura 2.47, en donde la lnea
K corresponde al bus de datos que es alimentado por la tensin de la batera. El transistor es el
componente que permite al dispositivo cambiar el estado del bus en funcin de la informacin que
desee transmitir. El dispositivo recibe informacin leyendo el estado del bus en el punto que se
encuentra entre la resistencia y el transistor.

Figura 2.47. Esquema de interfaz fsica [Wense00].

Los niveles de tensin empleados para codificar los bits de datos se encuentran definidos en
relacin a la tensin de la batera. La figura 2.48 muestra el rango de tensiones utilizado para el
nivel alto y el bajo. El nivel bajo resulta ser dominante frente al alto debido a la configuracin de la
interfaz de la figura 2.47, en un transistor tiene la capacidad de forzar a todo el bus a un estado bajo
sin importar el estado que tengan las interfaces de los otros dispositivos conectados al bus.

Figura 2.48. Rango de tensiones para niveles alto y


bajo sobre la lnea de transmisin [Wense00].

FernandoArielBeunza79156

Figura 2.49. Umbrales para niveles alto y bajo


soportados por los receptores [Wense00].

59

Tesis de Grado en Ingeniera Informtica


En la figura 2.49 se puede observar los umbrales que deben soportar los receptores para poder
detectar los distintos niveles del bus. Como es de esperar los rangos comprendidos son ms amplios
que los vistos en la figura 2.48, por cuestiones de compatibilidad.
El ancho de pulso que puede tener cada smbolo utilizado para codificar un bit de datos
depende de la velocidad de transferencia que se utilice. LIN soporta una velocidad de transferencia
mxima de 20 Kbps, lo que se traduce en un ancho de pulso de 50 microsegundos, aunque en la
industria automotriz suele trabajarse con velocidades de 2,4 Kbps; 9,6 Kbps y 19,2 Kbps [Rey03].

2.2.4.2. Capa de enlace


La simpleza de LIN radica en que el mecanismo de acceso al medio fsico no consiste en
algoritmos complejos, ya que el esquema de una red consiste en un dispositivo maestro que
administra el uso del medio de comunicacin, y en dispositivos esclavos que siguen las
instrucciones del dispositivo maestro. El beneficio de la simpleza debe pagarse teniendo
concentrada las funciones vitales de la red en un slo dispositivo, que en caso de falla de ste, la red
queda paralizada.
El intercambio de datos entre los diferentes dispositivos de una red LIN se realiza por medio
de tramas conformadas por los campos detallados en la figura 2.50.

Figura 2.50. Estructura de una trama [LIN10].

Una trama se compone de un encabezado y una respuesta. El encabezado siempre es generado por el
dispositivo maestro, y consiste en un espacio inicial utilizado para marcar el inicio de una trama,
seguido de una secuencia alternada de bits de valor cero y uno para sincronizar los dispositivos
esclavos con el maestro, y finalmente un identificador protegido. ste identificador se conforma de
los campos detallados en la figura 2.51.

Figura 2.51. Estructura del campo identificador [LIN10].

El campo identificador comienza con un bit de comienzo, seguido de 6 bits correspondientes al


identificador, 2 bits de paridad que protegen el identificador anterior ante errores de transmisin, y
finalmente un bit de final de campo. El dispositivo esclavo que reconozca el identificador
transmitir la respuesta a continuacin del encabezado de la trama. Dicha respuesta puede contener
hasta 8 bytes estructurados de la forma descripta en la figura 2.52.

60

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 2.52. Estructura de un campo de dato [LIN10].

Luego de la secuencia de bytes de datos, el dispositivo esclavo emite una suma de verificacin, para
que el dispositivo maestro pueda verificar si los datos recibidos contienen errores o no. En la figura
2.53 se describe un ejemplo de secuencia de envo de encabezado y recepcin de datos.

Figura 2.53. Transmisin de una trama [Wense00].

Los identificadores se encuentran clasificados segn los datos de la trama: los


identificadores comprendidos entre 0 y 59 se emplean para el transporte de seales, los
comprendidos entre 60 y 61 se utilizan para transportar datos de diagnstico y configuracin, y los
comprendidos entre 62 y 63 se encuentran reservados para aplicaciones futuras.
Existen diferentes tipos de tramas: incondicionales, activadas por evento, de diagnstico y
reservadas. Las tramas incondicionales transportan seales y presentan identificadores
comprendidos entre 0 y 59. ste tipo de tramas permiten a los dispositivos esclavos enviar datos a
otros dispositivos. El dispositivo maestro es quien siempre inicia la trama enviando el encabezado,
y luego el dispositivo esclavo correspondiente enva los datos solicitados que son recibidos por los
dispositivos destinatarios.
Las tramas activadas por eventos son enviadas por el dispositivo maestro destinadas a uno o
varios dispositivos esclavos. Si los dispositivos esclavos tiene asociado a una trama activada por
evento una trama incondicional (est ltima es enviada luego de recibirse la primera). sto ltimo
puede dar lugar a colisiones de tramas. El mecanismo de deteccin de colisin se basa en la
existencia de bits de valor dominante y recesivo que permiten a los dispositivos detectar cuando una
transmisin est siendo interferida por otra. El dispositivo maestro es el encargado de la resolucin
de la colisin, por medio de una tabla predefinida especialmente para esta situacin, que le indica a
cada dispositivo esclavo en que momento emitir su respuesta.
Las tramas de diagnstico utilizan los identificadores 60 y 61, y son utilizadas para
funciones de diagnstico y configuracin de los dispositivos de la red.
Por ltimo las tramas reservadas emplean identificadores 62 y 63, y no tienen una funcin
especfica ya que se reservan para aplicaciones futuras.

2.2.5. D2B
ste bus fue desarrollado por la empresa Phillips en los comienzos de la dcada del 80. Su
finalidad era poder interconectar diferentes dispositivos domsticos de audio y video. La empresa
FernandoArielBeunza79156

61

Tesis de Grado en Ingeniera Informtica


Mercedes Benz adopt D2B para interconectar los dispositivos de audio y video (radio, cargador de
CD, etc.) de sus automviles.

2.2.5.1. Medio fsico


D2B fue pensado para utilizar par trenzado o fibra ptica. Como en sta parte del presente
trabajo, se analizan las redes utilizadas en automviles, solamente se hablar de la implementacin
de ste bus sobre fibra ptica, ya que es el medio fsico empleado por la empresa Mercedes Benz
para la construccin de sus automviles.
La implementacin de D2B propuesta por Mercedes Benz consiste en una red integrada por
fibra ptica y cableado elctrico. La fibra ptica es utilizada para el envo de informacin y los
dispositivos se interconectan formando una red de topologa tipo anillo. El cableado elctrico es
utilizado para el envo de la seal de activacin de los transceptores de fibra ptica de cada uno de
los dispositivos, y emplea una topologa de red tipo estrella. La figura 2.54 muestra las diferentes
topologas adoptadas por la fibra ptica y el cableado elctrico de la red.

Figura 2.54. Configuracin de D2B implementada por Mercedes Benz [D2B04].

Una red D2B puede soportar hasta 6 dispositivos conectados, siendo uno de ellos el maestro,
y el resto esclavos. La fibra ptima permite que la velocidad de transferencia alcance los 5,65 Mbps,
debido a la inmunidad al ruido electromagntico que ste medio posee. El largo mximo que puede
alcanzar el cable de fibra ptica varia segn la cantidad de acopladores: si no se emplean
acopladores el cable puede tener hasta un largo de 10 metros, si se introduce un acoplador el largo
se reduce a 7 metros, y si se introducen dos acopladores el largo no puede alcanzar los 3,6 metros
[D2B02]. Adems el cable debe tener un radio de curvatura mnimo de 25 milmetros para que no
se dae.
Los beneficios de D2B vienen dados fundamentalmente por las ventajas de que brinda la
fibra ptica (altas velocidades de transferencia e inmunidad al ruido electromagntico), pero
tambin se hacen evidentes las desventajas de sta: las distancias no son extensas (y disminuyen con
el uso de acopladores), los cables son frgiles (y su curvatura se encuentra limitada), y en caso de
rotura la reparacin es costosa.

62

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

2.2.5.2. Control de acceso al medio


Una red D2B se compone de un dispositivo maestro, y varios dispositivos esclavos (hasta 5).
Los dispositivos conforman un anillo por medio de los cables de fibra ptica, y de sta forma un
paquete transmitido por el dispositivo maestro pasa por todos los dispositivos esclavos para ser
recibido por el dispositivo maestro. El dispositivo maestro puede ser una radio o un tablero de
comandos, mientras que los dispositivos esclavos pueden ser cargadores de CD, dispositivos de
control de voz, telfonos, etc.
El dispositivo maestro es responsable de almacenar la configuracin del anillo, generar la
seal elctrica para la activacin de los transceptores de los dispositivos de la red (ya que stos se
desactivan cuando no se enva informacin para ahorrar energa), inicializar el anillo, mantener el
anillo, desactivar el anillo, detectar errores de funcionamiento del anillo y ser una pasarela entre la
red D2B y la red CAN (red utilizada por otros dispositivos del automvil).
La secuencia de inicializacin del anillo comienza cuando el dispositivo maestro emite un
pulso de 80 milisegundos por medio del cableado elctrico, para que el resto de los dispositivos
esclavos activen sus transceptores. Cuando se activan todos los transceptores, ya se encuentra
disponible el canal ptico, para que el dispositivo maestro enve un pulso por medio de ste canal.
El pulso recorre todo el anillo, siendo recibido y reenviado por todos los dispositivos esclavos, hasta
que el dispositivo maestro recibe el pulso que emiti. En ste momento, el dispositivo maestro
reconoce que se constituy el anillo, entonces enva otro pulso que recorre todo el anillo
nuevamente para indicar a cada dispositivo esclavo que el anillo est listo para la circulacin de
informacin a travs de l.
Una vez constituido el anillo, la informacin fluye a travs de el por medio de paquetes que
contiene cierta informacin de control que permite determinar el destinatario de los mismos. Todos
los paquetes fluyen por el anillo, pero slo procesa el paquete el dispositivo cuya direccin coincide
con el destinatario indicado en el paquete. Cuando no hay necesidad de transmitir informacin, el
dispositivo maestro indica la desactivacin de los transceptores de todos los dispositivos de la red.

2.2.5.3. Estructura de paquete


La estructura de paquete empleada por D2B para el transporte de informacin a travs del
anillo se encuentra conformado por un bit de comienzo, la direccin del dispositivo maestro, la
direccin del dispositivo esclavo, informacin de control y la informacin a enviar. En la figura
2.55 se puede observar la estructura del paquete.

Figura 2.55. Estructura de paquete utilizado por D2B [Paret05].

FernandoArielBeunza79156

63

Tesis de Grado en Ingeniera Informtica


En un paquete enviado por el dispositivo maestro a un dispositivo esclavo, la direccin del primero
constituye la direccin de origen y la del segunda la direccin de destino. Las direcciones son
codificadas utilizando 12 bits.

2.2.6. MOST
MOST constituye una evolucin de D2B desarrollada por las empresas BMW, DaimlerChrysler, Harman/Becker y Oasis. A diferencia de D2B, el uso de ste bus no es exclusivo de
Mercedes Benz, que tambin ha adoptado MOST en reemplazo de D2B. Las mejoras incluyen
velocidad de transferencia, cableado, cantidad de dispositivos soportados, entre otras.

2.2.6.1. Modelo de dispositivo


Un dispositivo MOST consiste en una unidad fsica que se conecta a una red MOST por
medio de una interfaz fsica. Dentro de un dispositivo pueden existir varias aplicaciones que
interactan con los servicios de red. Los servicios de red son los que tiene acceso directo a la
interfaz de red MOST. La interfaz de red es la encargada de enviar las tramas generadas por los
servicios de red independientemente del medio fsico de comunicacin utilizado. En la figura 2.56
se detallan cada uno de los componentes mencionados anteriormente.

Figura 2.56. Modelo de dispositivo MOST [MOST10].

MOST fue diseado para que sea independiente del medio fsico utilizado como canal de
comunicaciones. Puede trabajar sobre cableado elctrico (par trenzado) o fibra ptica. En este
trabajo slo se hablar de fibra ptica, ya que es el medio fsico ms conocido en la industria del
automvil.

2.2.6.2. Capa fsica


La capa fsica de MOST tiene varias cosas en comn, comparada con la de D2B. Igual que
sta ltima, los dispositivo se encuentran conectados por medio de fibra ptica y cableado elctrico.
64

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


La red de fibra ptica adopta una topologa anillo y es empleada para el transporte de datos. En
cambio, la red elctrica presenta una topologa estrella y su funcin es la de transporta la seal de
activacin de los transceptores de los dispositivos conectados a la red MOST. En la figura 2.57 se
puede observar un ejemplo de como se conforma una red MOST.

Figura 2.57. Ejemplo de configuracin anillo de MOST [MOST04].

A diferencia de D2B, MOST introduce algunas mejoras con el objetivo de mejorar las
prestaciones. La primer mejora consta en el cableado ptico, que al utilizar fibra ptica plstica,
permite aumentar la longitud mxima permitida (21 metros sin acopladores y 3,962 metros con tres
acopladores), y no tiene el inconveniente del radio de curvatura mnimo que presenta D2B. Adems
la velocidad de transferencia se eleva a 24,8 Mbps y la cantidad mxima de dispositivos soportados
por la red asciende a 64. Respecto a la parte elctrica, introduce mejoras en cuanto al sistema de
activacin de los dispositivos, en lugar de que el dispositivo maestro sea el encargado de proveer la
alimentacin de ste sistema, en MOST todos los dispositivos se encargan de ello.

2.2.6.3. Capa de red


Una red MOST se conforma de un dispositivo maestro, y varios dispositivos esclavos, como
en D2B. El dispositivo maestro es el encargado de almacenar la configuracin del anillo, generar la
seal elctrica para la activacin de los transceptores de los dispositivos de la red, inicializar el
anillo, mantener el anillo, desactivar el anillo, detectar errores de funcionamiento del anillo, ser
pasarela entre MOST y otra red (como CAN), y ser la pasarela de diagnstico para los dispositivos
esclavos. En la figura 2.57 se puede ver que el dispositivo maestro encargado de las funciones
anteriores es el Audio Gateway. Un dispositivo esclavo debe encargarse de monitorear la presencia
de la seal de activacin de los transceptores, generar la seal de activacin ante un requerimiento
de ste, mantener el anillo una vez iniciado por el dispositivo maestro, detectar errores de
funcionamiento del anillo, y responder a la informacin de diagnstico requerida por el dispositivo
maestro.
La secuencia de inicializacin del anillo es similar a la empleada por D2B, con la diferencia
de que en MOST cualquier dispositivo puede emitir la seal de activacin de los transceptores que
desencadena el proceso de inicializacin del anillo. Cuando se encuentran activados todos los
transceptores, el dispositivo maestro enva un pulso por medio de ste canal. El pulso recorre todo
el anillo, siendo recibido y reenviado por todos los dispositivos esclavos, hasta que el dispositivo
FernandoArielBeunza79156

65

Tesis de Grado en Ingeniera Informtica


maestro recibe el pulso. En ste momento, el dispositivo maestro reconoce que se encuentra
constituido el anillo, entonces enva otro pulso que recorre todo el anillo nuevamente para indicar a
cada dispositivo esclavo que el anillo est listo para la circulacin de informacin a travs de l.
En un anillo constituido, la informacin fluye a travs de l de diversas formas, dependiendo
de la naturaleza de los datos. Cuando no hay necesidad de transmitir informacin, el dispositivo
maestro indica la desactivacin de los transceptores de todos los dispositivos de la red.
Segn la naturaleza de los datos provenientes de la capa de aplicacin, la capa de red provee
una serie de mecanismos de transporte para cada tipo de datos. Dichos mecanismos pueden
observarse en la clasificacin detallada en la figura 2.58.

Figura 2.58. Mecanismos de transporte de datos [MOST10].

Los mensajes enviados por medio del canal de control son cortos y transfieren informacin de
control requerida por las aplicaciones. Los destinatarios de este tipo de mensajes pueden ser un
dispositivo (unicast), un grupo de ellos (multicast) o todos (broadcast). Cuando se enva este tipo de
mensajes, el arbitraje del medio es realizado por el controlador de interfaz de red MOST,
garantizando que el acceso al medio sea independiente de la carga de la red. ste tipo de mensajes
pueden ser retransmitidos, en caso de error, la cantidad de veces indicada por la aplicacin que los
genera.
Todo tipo de datos no que no son transmitidos por medio del canal de control, pueden ser
paquetes de datos o flujo de datos. Los paquetes de datos son empleados para el envo de rfagas de
datos. La cantidad de datos enviados por medio de paquetes es mayor a los enviados por medio del
canal de control. Los paquetes pueden estructurarse de dos formas segn el tipo de direccin
utilizada, como puede verse en las figuras 2.59 y 2.60.
Encabezado
12 bytes

Direccin Direccin
de destino de origen
2 bytes

2 bytes

CRC

Datos

4 bytes 6 a 1524 bytes

Figura 2.59. Estructura de paquete para direcciones de 16 bits [MOST10].

66

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Encabezado
12 bytes

Direccin Direccin
de destino de origen
6 bytes

6 bytes

CRC

Datos

4 bytes 0 a 1506 bytes

Figura 2.60. Estructura de paquete para direcciones de 48 bits [MOST10].

Ambas estructuras son bsicamente similares en cuanto al encabezado, cdigo detector de errores
CRC, y el campo de datos (su longitud mxima vara segn el tipo de direcciones utilizados). Las
direcciones pueden ser de 16 bits (direcciones MOST) o de 48 bits (direcciones MAC). El mtodo de
acceso al medio utilizado para el envo de paquetes de datos es por medio de la circulacin de
testigo por el anillo de la red.
Los flujos de datos pueden ser de naturaleza sincrnica o iscrona. Los flujos del primer tipo
se refieren a datos en tiempo real como audio, video o datos originados por sensores. El mtodo de
acceso al medio utilizado en este caso es multiplexado por divisin de tiempo TDM. Los flujos del
primer tipo son similares a los del primero, con la diferencia de que su muestreo no se realiza con el
reloj del sistema. El mtodo de acceso al medio empleado es el mismo que para los flujos
sincrnicos.

2.2.6.4. Capa de aplicacin


La capa de aplicacin consisten en un conjunto de definiciones sobre el formato y el
significado de los datos intercambiada entre las capas de aplicacin de los distintos dispositivos.
Los mensajes a nivel de capa de aplicacin son independientes de los aspectos fsicos de la red, de
sta manera las comunicaciones entre aplicaciones se realizan sobre canales virtuales. En la figura
2.61 se puede observar las comunicaciones virtuales asociadas a las comunicaciones reales llevadas
a cabo por los servicios de red y los controladores de interfaz de red MOST.

Figura 2.61. Comunicacin virtual entre dos dispositivos a nivel de capa de aplicacin [MOST10].

Todos los mensajes de la aplicacin son finalmente transferidos a travs del canal de control o el
canal de paquetes de datos provistos por la red MOST. Dependiendo de la cantidad de datos que se
requiere enviar, se puede emplear un mensaje de transferencia nica (telegrama), o de lo contrario
por medio de transferencia segmentada.

FernandoArielBeunza79156

67

Tesis de Grado en Ingeniera Informtica


La estructura de mensaje para una transferencia nica, o telegrama (figura 2.62) se compone
de la direccin de origen del mensaje, la direccin destinataria del mismo, un identificador de
mensaje, un identificador de telegrama, la cantidad de datos transportada y los datos transportados.

Figura 2.62. Estructura de mensaje utilizado para transferencia simple [MOST10].

El tamao de las direcciones del mensaje son 16 bits. Para la identificacin de los mensajes se
destinan 32 bits, mientras que para identificar el telegrama se emplean 4 bits. Los 12 bits destinados
a almacenar la cantidad de datos transportada. Una transferencia simple puede transporta hasta 45
bytes.
La estructura de mensaje empleada para transferencias segmentadas es similar a la empleada
para los mensajes de transferencia nica. Se diferencian en que los mensajes para transferencias
segmentadas necesitan de un contador de mensaje (ver figura 2.63).

Figura 2.63. Estructura de mensaje utilizado para transferencia segmentada [MOST10].

La estructura de encabezado no se modifica, salvo el agregado de contador de mensaje de 8 bits de


longitud que le resta un byte a la capacidad de transporte de datos. En total, la transferencia
segmentada tiene la capacidad de transportar hasta 65535 bytes, distribuidos en mltiples
segmentos.

2.2.7. FlexRay
El estndar FlexRay fue desarrollado por el consorcio del mismo nombre, integrado por un
conjunto de empresas fabricantes de automviles y de electrnica, entre los aos 2000 y 2009, para
superar en prestaciones a buses como CAN y MOST.

2.2.7.1. Capa fsica


Una de las caractersticas que poseen los dispositivos que cumplen con el estndar FlexRay,
frente a otros dispositivos que emplean otros estndares, es la capacidad de poder utilizar dos
medios fsicos de comunicacin en forma paralela. sto posibilita aumentar la confiabilidad del bus
de datos y poder utilizar diversas topologas de red para interconectar los dispositivos.
El medio fsico empleado para implementar cada canal de comunicacin es par trenzado sin
blindaje. La utilizacin de seales diferenciales para transmitir la informacin permite el ahorro de
68

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


utilizar cable blindaje. sto combinado con el hecho de que cada dispositivo puede trabajar con dos
canales en simultneo a velocidades de transferencia de hasta 10 Mbps, hace que FlexRay sea muy
competitivo frente a soluciones costosas como D2B o MOST que emplean cableado de fibra ptica.
La arquitectura de un dispositivo que cumple con el estndar FlexRay se compone
bsicamente de las siguientes partes (figura 2.64): un microcontrolador (propio de cada dispositivo),
un Controlador de Comunicaciones (que implementa FlexRay), dos transceptores (uno para cada
canal de comunicacin), y una fuente de alimentacin (que suministra energa a todas las partes
anteriores).

Figura 2.64. Arquitectura del hardware de un dispositivo FlexRay [FlexRay].

Las topologas de red que se permite implementar FlexRay son variadas gracias a la
disposicin de dos canales de comunicacin paralelos. La topologa ms simple que se puede
utilizar es la lineal, en donde los dispositivos de la red puede conectarse a uno de los canales o a los
dos, como se muestra en la figura 2.65.

Figura 2.65. Topologa lineal pasiva [FlexRay].

Dependiendo de la funcionalidad de cada dispositivo, podr requerir de uno o dos canales de


comunicacin, siendo recomendado para funciones crticas el empleo de los dos canales. La
longitud mxima que puede soportar la lnea es de 24 metros, siendo posible conectar hasta 22
dispositivos. A veces no resulta adecuada la topologa anterior, una nica lnea recorriendo todo un
automvil resultara en un cableado extenso, superando el tamao mximo permitido, por lo cual
puede resultar ms prctico la siguiente topologa tipo estrella como se puede ver en la figura 2.66.

FernandoArielBeunza79156

69

Tesis de Grado en Ingeniera Informtica

Figura 2.66. Topologa estrella pasiva [FlexRay].

En la topologa estrella, el cableado su puede ramificar, sin necesidad de depender de una sola lnea
como ocurre con la topologa lineal. Solamente se permite un punto de empalme, y las limitaciones
en cuando al tamao del cable y la cantidad de dispositivos es idntica a la topologa lineal. Para
extender el lmite de longitud del cable, FlexRay permite la utilizacin de elementos activos. En la
figura 2.67 y 2.68 se proponen dos variantes de la topologa estrella activa.

Figura 2.67. Topologa estrella activa clsica [FlexRay].

Figura 2.68. Topologa estrella activa modificada [FlexRay].

A diferencia de la topologa estrella pasiva, la estrella activa emplea en los puntos de empalme
elementos repetidores. Los repetidores se encargan de regenerar la seal y tiene la capacidad de
desconectar un tramo averiado del cableado, permitiendo el funcionamiento del resto de la red. La
longitud mxima de cable que puede existir entre un dispositivo y un repetidor, o entre dos
repetidores es de 24 metros. Sobre una misma lnea se pueden colocar hasta dos repetidores, lo que
70

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


permitira una distancia mxima entre dispositivos de 72 metros (3 tramos de 24 con dos repetidores
de por medio). A partir de las topologas anteriores, pueden implementarse combinaciones
resultando topologas hbridas, que no son recomendables ya que las limitaciones resultan de la
combinacin de las limitaciones de las topologas bsicas.

Figura 2.69. Topologa hbrida [FlexRay].

La figura 2.69 muestra una topologa parte estrella y parte lineal, empleando elementos repetidores
en los puntos de empalme de las diversas topologas bsicas utilizadas.
Una trama de capa fsica se compone bsicamente de una secuencia de bytes como se puede
observar en la figura 2.70.

Figura 2.70. Estructura de trama fsica [FlexRay].

La trama comienza con el envo de una secuencia de bits de valor cero utilizados para indicar el
inicio de una transmisin. Luego de la secuencia anterior, se enva un bit de valor uno para indicar
el comienzo de la trama. A continuacin se transmiten los bytes de la trama, con un encabezado
previo compuesto por un bit de valor uno seguido de un bit de valor cero, utilizado para sincronizar
el receptor. Una vez finalizada la transmisin de todos los bytes de la trama, se enva un bit de valor
cero seguido de un bit de valor uno para indicar el fin de la trama.

2.2.7.2. Capa lgica


La capa lgica se encuentra ubicada por encima de la capa fsica y la capa de aplicacin
residente el microcontrolador del dispositivo. Se encuentra implementada por el Controlador de
Comunicaciones mencionado con anterioridad (ver figura 2.64), y es responsable del armado y
desarmado de las tramas, controlar el acceso al medio y sincronizar el reloj interno.
FernandoArielBeunza79156

71

Tesis de Grado en Ingeniera Informtica


Para controlar el acceso al medio, FlexRay se basa en un ciclo de comunicacin recurrente
conformado por cuatro segmentos. Los ciclos se pueden configurar de diferente manera como se
puede observar en la figura 2.71.

Figura 2.71. Ciclos de comunicacin [FlexRay].

El segmento esttico se compone de ranuras de tiempo de longitud fija, cada uno asociado a un
determinado identificador de trama, y a su vez cada identificador se encuentra asociado a un nodo
determinado, de ste modo cada nodo conoce en que ranura debe transmitir. El segmento dinmico
se compone de ranuras dinmicas de longitud variables, y el uso se determina en base a la prioridad
de la trama a enviar. El segmento SW es utilizado para evaluar el estado medio. El segmento NT
corresponde a un perodo de tiempo en el cual el canal queda libre. Tanto el segmento esttico como
el segmento NT son obligatorios, en cambio el segmento dinmico y el segmento SW puede estar o
no dentro de un ciclo.
La informacin se enva por medio de tramas conformadas por los campos detallados en la
figura 2.72. Una trama puede dividirse en tres partes: un encabezado, la informacin a enviar y
cdigos de deteccin de errores. El tamao de la trama puede variar entre los 8 y 262 bytes.

Figura 2.72. Estructura de trama lgica [FlexRay].

El encabezado tiene una longitud de 5 bytes distribuidos en: 5 bits de estado, 11 bits destinados al
identificador nico de trama asociado al nodo que enva la trama, 7 bits para indicar la cantidad de
bytes de informacin enviados en la trama, 11 bits para cdigo de deteccin de errores CRC para el
encabezado y 6 bits para indicar el ciclo de comunicacin corriente. La informacin conformarse

72

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


por 0 y 254 bytes de datos. Los cdigos de deteccin de errores se componen de tres cdigos CRC
de 8 bits cada uno.
FlexRay, como otros sistemas, tambin implementa un mecanismo de ahorro de energa, en
donde los dispositivos se desactivan cuando no llevan a cabo ninguna tarea. Esto implica que antes
de enviar una trama, deben activarse los dispositivos desactivados para que puedan recibir la trama.

2.3. Redes PLC en automviles


Todos los estndares referidos a PLC tratados hasta este momento fueron diseados para
funcionar sobre redes elctricas presentes infraestructura edilicia. Algunos de stos estndares se
encuentran ms orientados a la interconexin de sensores y actuadores, mientras que otros
estndares proponen una alternativa a las tradicionales redes de datos cableadas (por ejemplo
Ethernet) e inalmbricas (WiFi).
Tambin se hizo referencia a los estndares de redes de datos empleadas en automviles, que
no se encuentran, en principio, relacionados con la tecnologa PLC, pero las soluciones que aportan
son de gran utilidad para poder adaptar la tecnologa PLC al ambiente de un automvil.
Un automvil presenta caractersticas muy diferentes a una infraestructura edilicia,
comenzando por la alimentacin, que en el caso de un automvil se trabaja con corriente continua a
diferencia de una red elctrica domiciliaria. Muchos de los estndares PLC utilizan la seal alterna
de potencia para sincronizacin, cosa que no es posible con una seal continua. Como sta
diferencia, existen otras, que muestran la necesidad de realizar un trabajo de adaptacin para
trasladar la tecnologa PLC al mundo del automvil.

2.3.1. DC-BUS
La empresa Yamar Electronics Ltd. ha desarrollado un sistema propietario para
comunicaciones PLC para automviles. El sistema llamado DC-BUS permite un ahorro en el
cableado que se traduce en una reduccin en el peso total del automvil adems de las ventajas que
brinda la utilizacin de un bus de datos para intercomunicar los diversos dispositivos electrnicos
existentes en el mismo.

2.3.1.1. mbitos de aplicacin


Las comunicaciones en un automvil por medio de un bus de datos pueden dividirse en tres
categoras, segn el mbito de aplicacin:

Bus de alta velocidad para sistemas de multimedia y entretenimiento con velocidades


entre 1 y 100 Mbps.
Bus de velocidad media dedicado a telemtica con velocidades entre 10 Kbps y 1 Mbps.
Bus de baja velocidad dedicado a mecatrnica con velocidades entre 1 Kbps y 10 Kbps.

DC-BUS propone una opcin por cada categora. Para las aplicaciones multimedia existe una
alternativa que ofrece 1,7 Mbps utilizada, por ejemplo, para transmitir audio de calidad proveniente
del cargador de CD hacia el reproductor de audio. Para aplicaciones de telemtica, la alternativa
existente tiene una velocidad de 250 Kbps que permite la transmisin de voz y datos. Por ltimo,
FernandoArielBeunza79156

73

Tesis de Grado en Ingeniera Informtica


para aplicaciones de mecatrnica, se ofrece una alternativa de 10 Kbps adecuada para
intercomunicar sensores y actuadores.

Figura 2.73. Esquema del DC-BUS desarrollado por Yamar Electronics Ltd.

2.3.1.2. Medio de comunicacin


Para cada una de las categoras mencionada con anterioridad se asignan diferentes
frecuencias de trabajo: (F0) para mecatrnica, (F1, F2) para telemtica y (F3, F4) para multimedia;
siendo utilizadas dos frecuencia para redundancia.

Figura 2.74. Canales utilizados por DC-BUS [Maryanka00].

DC-BUS fue diseado para trabajar en una red constituida con hasta 16 dispositivos. Todos
los canales se encuentran disponibles sobre una misma red de potencia. Solamente un dispositivo a
la vez, puede enviar informacin utilizando cualquiera de los canales.
Cuando varios dispositivos tiene que realizar una transmisin, se emplea un protocolo
CSMA para resolver la contienda entre los dispositivos. Existen variantes del protocolo CSMA,
sobre el tratamiento de las colisiones de mensajes. DC-BUS tiene la particularidad de no poder
transmitir y recibir en forma simultnea, lo cual impide la deteccin de colisin. La solucin
implementada consiste en realizar un arbitraje previo a la transmisin, y resolver la contienda en
base a la emisin y deteccin de una portadora.

Figura 2.75. Transmisin de un mensaje DC-BUS [AnraniRubin].

74

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


En la figura 2.75 su puede observar la existencia de un perodo de arbitraje destinado a resolver la
contienda entre varios dispositivos que deseen transmitir en forma simultnea. El perodo de
arbitraje comienza cuando no se detecta activa en el canal de comunicacin. El mecanismo de
resolucin de contienda consiste en que cada dispositivo contiene un registro de n bits cuyos valores
se determinan aleatoriamente. Dicho registro, determina en que momento el dispositivo debe emitir
la portadora (bit uno) y cuando debe escuchar el canal (bit cero), durante un tiempo equivalente al
perodo de un bit, a medida que se recorre el registro. El primer y ltimo bit del registro tienen valor
cero, indicando que debe escuchar el canal al comienzo y fin del recorrido. Luego de haber recorrido
los n bits del registro, si en ningn momento de escucha del canal se detect la presencia de
portadora, el dispositivo inicia la transmisin. En caso contrario, debe retornarse al punto inicial y
volviendo a iniciar el perodo de arbitraje.

2.3.1.3. Implementacin
Un dispositivo de comunicacin DC-BUS se encuentra constituido por los bloques
enumerados en la figura 2.76.

Figura 2.76. Arquitectura de DC-BUS [Maryanka00].

La informacin proveniente de un sensor, u otro dispositivo generador de datos, es almacenada en


una cola de transmisin. La informacin de la cola, es empaquetada en un mensaje y se le agrega un
cdigo corrector de errores, y queda a la espera de poder ser modulada y enviada cuando el canal se
encuentre disponible. Los receptores del mensaje demodulan la seal recibida, corrigen los errores
ocurridos, desarman el mensaje y almacenan en la cola de recepcin la informacin recibida, que
queda a la espera de que el dispositivo cliente destinatario pueda recibirla.

2.3.2. Trabajos sobre PLC en la industria automotriz


La Facultad de Ingeniera Elctrica de la Universidad Tcnica Checa de Praga ha realizado
una serie de trabajos sobre la implementacin tecnologa PLC en el ambiente automotriz. En uno de
stos trabajos, Power Line Communications in Automotive Industry [Trnka05], se implementa un
FernandoArielBeunza79156

75

Tesis de Grado en Ingeniera Informtica


dispositivo que permite la comunicacin por medio del cableado elctrico del automvil. Dicho
trabajo adems realiza un estudio de las caractersticas del canal de comunicacin utilizado y del
desempeo de diversas tcnicas de modulacin para la transmisin de datos.
El dispositivo mencionado anteriormente consiste en un modem prototipo implementado con
un FPGA como se describe en el trabajo Development System for Communications over DC Power
Lines [TrnkaPurkert05].
Un ltimo trabajo realizado por la misma universidad, Optimization of the Data
Transmissions over DC Power Lines [Trnka06-1] [Trnka06-2], pone nfasis en el mecanismo de
transmisin de los datos. Propone dos tcnicas de modulacin basadas en BFSK y BPSK, las cuales
son adaptadas para funcionar sobre lneas de potencia.
Los trabajos mencionados anteriormente ponen su atencin en implementar con un bajo
nivel de complejidad las capas fsica y de enlace, dejando de lado las restantes capas del modelo
OSI.

2.3.2.1. Canal de comunicaciones


Segn el estudio realizado en el trabajo Optimization of the Data Transmissions over DC
Power Lines [Trnka06-2], el canal de comunicaciones utilizado por las redes PLC introduce en la
seales de informacin distorsiones lineales y no lineales. Dentro del grupo de las distorsiones
lineales se encuentran las referidas al ruido aditivo, atenuacin de seal, distorsin de amplitud y
fase, y distorsin multitrayecto. Las distorsiones del tipo no lineal, se refieren principalmente a
limitaciones de los amplificadores, la utilizacin de transformadores con ncleo ferromagntico y
circuitos limitadores.
Una aproximacin terica del canal de comunicaciones, que tenga en cuenta solamente las
distorsiones lineales, se puede modelizar por medio de una funcin de transferencia y la suma de
ruido aditivo a la respuesta de dicha funcin, como se puede observar en la figura 2.77.

Figura 2.77. Modelo del canal de comunicaciones [Trnka06-2].

La funcin de transferencia H(f, t) representa la atenuacin de seal, distorsin de amplitud y


fase, y distorsin multitrayecto en funcin de la frecuencia f y del tiempo t. Dicha funcin es
dependiente del tiempo debido a que la respuesta en frecuencia del canal de comunicaciones
depende de la estructura de la red de potencia que vara segn se activen o desactiven dispositivos
conectados a sta (por ejemplo, el encendido o apagado de una lmpara, un motor, u otro tipo de
dispositivo que consuma energa de la red de potencia afectan la impedancia total de la misma).
Adems de la dependencia temporal de la funcin de transferencia H(f, t), la respuesta en
frecuencia del canal de comunicaciones no es invariante a la ubicacin del transmisor y el receptor
dentro de la red de potencia, por lo cual se tendrn diferentes funciones H segn la ubicacin del
transmisor y receptor.
Para corroborar la validez del modelo de canal de comunicaciones propuesto anteriormente,
se toma una red de potencia de un automvil (que segn [Trnka06-2] pertenece al Skoda Fabia), y

76

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


se definen puntos de prueba, a fin de determinar en forma aproximada la respuesta en frecuencia de
la red.

Figura 2.78. Esquema bsico de una red de potencia de un automvil y puntos de prueba [Trnka06-2].

En la figura 2.78 se detallan seis puntos de prueba que comprenden todo el automvil, a fin
de obtener la atenuacin promedio en diferentes bandas de frecuencia del canal de comunicaciones
entre cada una de las posibles combinaciones de puntos. Segn las mediciones realizadas en el
trabajo Optimization of the Data Transmissions over DC Power Lines [Trnka06-2], los valores de
atenuacin promedio, para cada una de las diferentes bandas de frecuencia, son los detallados en la
tabla 2.16.

Tabla 2.16. Atenuacin promedio (en dB) en diferentes bandas de frecuencia [Trnka06-2].

Como se puede observar en la anterior tabla, la atenuacin promedio vara aproximadamente


entre las -50 y -20 dB, resultando la banda de frecuencia comprendida entre los 0 y 5 MHz, como la
banda con mayor atenuacin, y la banda de frecuencias comprendida entre los 15 y 20 MHz, como
la banda con menor atenuacin, de lo cual se deduce que el rango de frecuencias ms ptimo para
establecer comunicaciones PLC es el comprendido entre los 15 y 20 MHz.
Otra caracterstica del canal de comunicaciones a tener en cuenta es la impedancia de la red
de potencia, ya que sto define la potencia requerida por los transmisores. Para obtener dicha
impedancia, en el trabajo Power Line Communications in Automotive Industry [Trnka05], se
FernandoArielBeunza79156

77

Tesis de Grado en Ingeniera Informtica


realizan mediciones de la impedancia de la red en los puntos de prueba 2 y 3 de la figura 2.78
correspondientes a la puerta del conductor y acompaante, respectivamente.

Figura 2.79. Impedancia de la red de potencia en funcin de la frecuencia [Trnka05].

Como se puede observar en la figura 2.79, la impedancia de la red de potencia en funcin de


la frecuencia es similar en ambos puntos de pruebas, lo que permite inferir que ste parmetro de la
red de potencia es invariante a la ubicacin (al contrario de lo que ocurre con la respuesta en
frecuencia). Adems se establece como rango apto para comunicaciones PLC el comprendido entre
las frecuencias 4 y 30 MHz, ya que el valor mnimo de la impedancia ronda los 10 ohm. Las
frecuencias debajo de los 4 MHz, no resultan convenientes ya que el valor de la impedancia cae de
los 10 ohm, lo que hace necesario que los modems requieran de transmisores de considerable
potencia.
Por ltimo, en el trabajo Power Line Communications in Automotive Industry [Trnka05], se
evala el funcionamiento de un modem prototipo. En dicha prueba se compara la seal emitida por
el transmisor y la seal recibida por el receptor, y en los resultados obtenidos se puede observar la
atenuacin producida por la red de potencia en la seal original.

Figura 2.80. Seal transmitida (arriba) y su


espectro (abajo) [Trnka05].

78

Figura 2.81. Seal recibida (arriba) y su


espectro(abajo) [Trnka05].

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Como se observa en las figuras 2.80 y 2.81, de una seal cuyo espectro se encuentra
comprendido entre las frecuencias 4 y 16 MHz, solamente llegan al receptor las frecuencias
comprendidas entre los 12 y 16 MHz, lo que obedece a los valores de atenuacin promedio en
funcin de la frecuencia estudiados con anterioridad (ver tabla 2.16).
Luego de analizar los resultados obtenidos en los trabajos realizados por la Facultad de
Ingeniera Elctrica de la Universidad Tcnica Checa de Praga, se pueden concluir que el canal de
comunicaciones presenta las siguientes caractersticas:

Debido a la impedancia de la red de alimentacin de un automvil, el rango de


frecuencias utilizable se encuentra comprendido entre los 4 y 30 MHz. Debajo de los 4
MHz, la impedancia alcanza valores menores a 10 ohm, lo cual requiere modems con
transmisores de considerable potencia. Por arriba de los 30 MHz se excede el lmite de la
banda de HF destinada para comunicaciones PLC [Trnka05].

La banda de frecuencias comprendida entre 4 y 30 MHz, destinada para comunicaciones


PLC, coincide con la banda de HF caracterizada por desvanecimiento intermitente y
selectivo de frecuencia, y trayectoria de propagacin mltiple [OppenheimWillsky97].

El rango de frecuencias con menor atenuacin se encuentra comprendido entre los 15 y


20 MHz, lo que resulta en el rango ms ptimo para implementar comunicaciones PLC.
sto no implica descartar las frecuencias prximas a dicho rango ptimo.

La pruebas realizadas al modem prototipo, han dado como resultado que de una seal
emitida comprendida en frecuencia entre los 4 y 16 MHz, slo llegan al receptor las
frecuencias comprendidas dentro del rango de los 12 y 16 MHz aproximadamente
(figuras 2.80 y 2.81). sto obedece a lo enunciado en la caracterstica anterior.

2.3.2.2. Mtodo de acoplamiento


Como se comparte una misma red cableada para el suministro alimentacin e intercambio de
informacin entre los dispositivos conectados a ella, se requiere un mecanismo en el transmisor que
permita el acoplamiento de la seal con informacin, a la red de alimentacin y un mecanismo en el
receptor que filtre, dejando pasar solamente la seal con informacin.
Bsicamente existen dos mtodos de acoplamiento, que dependen del elemento pasivo
utilizado, denominados: acoplamiento capacitivo y acoplamiento inductivo.

Figura 2.82. Acoplamiento capacitivo [Trnka06-2].

FernandoArielBeunza79156

Figura 2.83. Acoplamiento inductivo [Trnka06-2].

79

Tesis de Grado en Ingeniera Informtica


El mtodo de acoplamiento capacitivo, tambin se lo denomina acoplamiento paralelo,
debido a que la fuente de seal se conecta en paralelo a la aplicacin. ste mtodo se caracteriza por
ser una solucin de bajo costo e insensible a las variaciones de corriente, pero resulta sensible a
aplicaciones de baja impedancia. Para disminuir ste ltimo efecto se suele agregar una inductor
como se puede observar en la figura 2.82.
En cambio, el mtodo de acoplamiento inductivo, se lo denomina acoplamiento serie, debido
a que la fuente de seal se conecta en serie a la aplicacin por medio de un transformador. ste
mtodo tiene la ventaja de ser insensible a aplicaciones de baja impedancia, pero tiene el defecto de
ser sensible a las variaciones de corriente. Para contrarrestar ste efecto, se suele agregar un
capacitor en paralelo a la aplicacin (figura 2.83).
En el modem prototipo propuesto en el trabajo Optimization of the Data Transmissions over
DC Power Lines [Trnka06-2], se implementa tambin una variante del acoplamiento capacitivo
compuesto por dos capacitores en serie a la salida del transmisor, que junto a la impedancia de
salida de ste ltimo conforma un filtro pasa alto.

2.3.2.3. Tcnica de modulacin


Luego de estudiar las caractersticas propias del canal de comunicacin utilizado para redes
PLC, se debe hallar la tcnica de modulacin ms adecuada que permita la transmisin de datos de
forma confiable sobre un medio hostil como el descripto con anterioridad. Adems de encontrar una
tcnica de modulacin robusta, no se debe olvidar el factor de simplicidad de implementacin, ya
que es uno de los objetivos del presente trabajo.
La tcnica de banda base, tal vez sta tcnica pueda ser considerada como la ms simple de
todas ya que consiste en representar la informacin binaria por medio de dos estados elctricos. Sin
embargo, si se realiza un anlisis del espectro de la seal de informacin, la mayor cantidad de
energa de dicha seal se concentra en las frecuencias ubicadas por debajo de los 4 MHz, que
cuando se estudiaron las caractersticas del canal de comunicacin, se determin que dicha zona del
espectro no es la ms adecuada para transmitir informacin (por cuestiones de atenuacin,
impedancia, etc.).
sto ltimo, concluye con la necesidad de transmitir la informacin sobre una o varias
portadoras de frecuencia superior a los 4 MHz, para proteger a la informacin de las distorsiones
existentes en la zona del espectro en cuestin. Por lo cual, con sto, queda totalmente descartada la
posibilidad de utilizar la tcnica de banda base, ya que no brinda un mecanismo de transmisin de
informacin de forma confiable.
Las tcnicas de banda de paso se caracterizan por utilizar una o varias portadoras para
transportar la informacin. De sta forma, la o las portadoras trasladan la informacin a un rango de
frecuencias superior a la ocupada por la seal de informacin, delimitando la misma a una banda de
frecuencias del espectro. En funcin del ancho de la banda de frecuencias utilizada, se pueden
distinguir dos tipos de tcnicas diferentes: banda estrecha y banda ancha.
Las tcnicas de banda estrecha se basan en la utilizacin de una sola frecuencia portadora lo
cual resulta aceptable si el objetivo es el bajo costo y la velocidad de transmisin no es demasiada
alta. Dependiendo de la tcnica de modulacin, pueden ser ms o menos confiable, pero en general
son susceptible a las interferencia y a los desvanecimientos de frecuencia caractersticos del canal de
comunicaciones de la redes PLC.
La tcnica de modulacin de banda estrecha ms simple de implementar es la modulacin en
amplitud. sta tcnica consiste en disponer de una portadora cuya amplitud vara segn la
informacin a transmitir. La variante ms simple es la denominada ASK que define dos niveles de
amplitud posibles: uno destinado para transmitir un bit cero y otro para transmitir un bit uno).
80

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Debido a que sta tcnica resulta bastante ineficiente se ha desarrollado una mejora que trabaja con
ms niveles de amplitud y tambin trabaja con la fase de la portadora, logrando una mejora en la
eficiencia, que se conoce como QAM. Como se mencion en el estudio de las caractersticas del
canal de comunicaciones, una de ellas es la distorsin de amplitud y fase, que afecta a los esquemas
de modulacin basados en la amplitud, por lo cual resultan alternativas inviables para las
comunicaciones PLC.
Debido a las dificultades existentes en transmitir la informacin por medio de la amplitud de
la portadora, nace la modulacin en frecuencia que consiste en variar las frecuencia de la portadora
de amplitud constante en funcin de la informacin a transmitir. La versin ms simple se la conoce
como BFSK, en donde se destina una frecuencia para codificar un bit de valor cero y otra frecuencia
para codificar un bit de valor uno. sta tcnica resulta se inmune ante las distorsiones de amplitud y
fase enunciada con anterioridad, pero no resuelven otra caracterstica del canal de comunicaciones
que son los desvanecimientos de frecuencia, resultando inadecuada sta tcnica si dicho fenmeno
coincide con una de las frecuencias utilizadas.

Figura 2.84. Diagrama de bloques de un modem BFSK coherente [Trnka06-2].

Como alternativa a las anteriores tcnicas de modulacin, existe la modulacin en fase, en la


cual la informacin se codifica por medio de la fase de la portadora. sta tcnica resulta ser ms
confiable que las dependientes de la amplitud (la amplitud de la portadora es constante) y ms
eficiente que las dependientes de la frecuencia (se utiliza una sola frecuencia), utilizando en su
versin ms simple, conocida como BPSK, una fase de la portadora para codificar un bit de valor
cero y la fase opuesta para codificar un bit de valor uno. Si bien resulta una mejora, la complejidad
del demodulador crece ya que se requiere de un recuperador de portadora.

Figura 2.85. Diagrama de bloques de un modem BPSK coherente [Trnka06-2].

Una variante que elimina la necesidad de implementar un recuperador de portadora es la


conocida como DBPSK y requiere anteponer un codificador diferencial al modulador, que no
incrementa demasiado la complejidad de ste ltimo. El precio que se debe pagar por esta ventaja es
una menor inmunidad al ruido con respecto a la ofrecida por la tcnica original.

FernandoArielBeunza79156

81

Tesis de Grado en Ingeniera Informtica

Figura 2.86. Diagrama de bloques de un demodulador DBPSK [Trnka06-2].

Para aumentar la eficiencia de las tcnicas anteriores pueden utilizarse ms de dos fase para
codificar la informacin, aumentando la capacidad de transporte, pero disminuyendo la inmunidad
al ruido. En el caso particular de las comunicaciones PLC, no se pueden emplear muchas fases
(disminucin de la inmunidad al ruido), y ninguna de las variantes es inmune al desvanecimiento de
frecuencia que si coincide con la portadora, imposibilita la transmisin de informacin a travs del
medio.
Debido a los problemas expuestos en las anteriores tcnicas de modulacin, resulta necesario
transmitir la informacin de forma redundante, trabajando con mltiples portadoras
independientemente de la tcnica de modulacin. sto disminuye la posibilidad de destruccin de la
seal de informacin a mayor cantidad de portadoras se utilicen. La utilizacin de mltiples
portadoras implica una aumento del ancho de banda requerido, por ello, las tcnicas que se
describen a continuacin se denominan tcnicas de modulacin de banda ancha.
La primer tcnica de modulacin de banda ancha es una mejora de la modulacin BPSK
basada en la tcnica de espectro ensanchado de secuencia directa conocida como DSSS. El principio
fundamental de cualquier tcnica de ensanchamiento de espectro se basa en la idea de distribuir la
energa de la seal concentrada en una banda estrecha a lo largo de una banda ms ancha que la
anterior, con lo cual se mejora la inmunidad al ruido y resistencia a la interferencia. En el caso
particular de la tcnica DSSS, dicha distribucin se logra con la introduccin de una secuencia
pseudoaleatoria, con lo cual en lugar de transmitir un bit cero o uno directamente (como en el caso
de BPSK), se transmite una secuencia pseudoaleatoria que representa el bit de informacin. Dicha
secuencia modulan y demodulan de forma idntica a la tcnica BPSK.

Figura 2.87. Diagrama de bloques de un modem DSSS [Trnka06-2].

La mejora introducida por sta ltima tcnica de modulacin agrega a las caractersticas de
la modulacin BPSK de banda estrecha los beneficios del ensanchamiento en espectro que hace
resistente a la informacin al ruido e interferencia propios del canal de comunicaciones, sin un gran
incremento de la complejidad de implementacin. Pero la atenuacin en funcin de la frecuencia
caracterstica del canal de comunicaciones, estudiada con anterioridad, implica la necesidad de
implementar un esquema de ecualizacin para corregir las deformaciones del espectro de la seal,
para que sta pueda ser demodulada de forma correcta. La desventaja de la tcnica DSSS radica en
que requiere una alto grado de complejidad la implementacin de un ecualizador que permita el
correcto funcionamiento sobre el canal de comunicaciones PLC particular de un automvil. sto

82

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


ltimo es lo que hace descartar sta tcnica a pesar de que es viable para comunicaciones PLC en
otros entornos de aplicacin.
Otra tcnica de modulacin de banda ancha utilizada para comunicaciones PLC es la
OFDM, que consiste en trabajar con mltiples portadoras. sto minimiza los efectos indeseados
sobre la seal de informacin ocasionados por la naturaleza del canal de comunicaciones empleado.
De modo similar a la anterior tcnica, OFDM trabaja junto con alguna de la tcnicas de modulacin
mencionadas en el momento que se trataron las tcnicas de modulacin de banda estrecha; como
por ejemplo variantes de modulacin en fase (BPSK, QPSK, etc.) o QAM. El principio de
funcionamiento bsico se describe en la figura 2.88, que consiste en un modulador y demodulador
de alguna de las tcnicas de banda estrecha, que en lugar de unirse directamente se interpone un
bloque IDFT, encargada de transformar la seal generada por el modulador en un smbolo
compuesto por mltiples portadoras, y un bloque DFT, que toma el smbolo generado y lo convierte
en la seal original generada por el modulador.

Figura 2.88. Diagrama de bloques de un modem OFDM [Trnka06-2].

sta tcnica descripta simplifica la implementacin del ecualizador, ya que el espectro


generado (cuya forma se aproxima a un rectngulo) es ms simple reconstituir que el generador por
la tcnica DSSS. Sin embargo, la complejidad de implementar los bloques IDFT y DFT, hacen de
ste mtodo, que aparenta ser ms adecuado de todos los estudiados, que en realidad no lo sea.
Hasta aqu se han analizado las tcnicas de modulacin ms conocidas, y ninguna de ellas
satisface completamente las necesidades requeridas en las comunicaciones PLC en automviles. Por
sta razn, a continuacin se analizan otras tcnicas que surgen como modificaciones a las
anteriormente analizadas.

2.3.2.4. Tcnicas modificadas


En los trabajos realizados por la Facultad de Ingeniera Elctrica de la Universidad Tcnica
Checa de Praga sobre este tema, se proponen dos tcnicas de modulacin que pretenden reunir las
simpleza de las tcnicas de banda estrecha con la robustez de las tcnicas de banda ancha.
La primer tcnica de modulacin que se presenta consta de una modificacin de la tcnica
BFSK, que se la designa BFSK Adaptado. El principio de funcionamiento es simple como el de
BFSK, pero en lugar de emplear una portadora para codificar cada bit de valor cero o uno, se
emplean varias (en este caso se utilizan las portadoras pares e impares). Por lo tanto, el espectro de
la seal de informacin es similar al que se puede obtener con la tcnica OFDM, ya que se definen
dos smbolos (uno con las portadoras pares y otro con las impares) para transmitir un bit de valor
cero o uno. La diferencia de sta tcnica con respecto a OFDM es que los smbolos se encuentran
predefinidos por medio de un conjunto de muestras, y no se generan durante el funcionamiento,
ahorrando la complejidad requerida para implementar los bloques IDFT y DFT.

FernandoArielBeunza79156

83

Tesis de Grado en Ingeniera Informtica

Figura 2.89. Diagrama de bloques de un modem BFSK Adaptado [Trnka06-2].

La tcnica BFSK Adaptada logra reunir la simpleza del BFSK con las ventajas de OFDM,
pero la utilizacin del espectro no es del todo eficiente, ya que para cada uno de los smbolos
solamente se utilizan la mitad de las portadoras disponibles. El empleo de ms portadoras se traduce
en una mayor redundancia lo que se traduce en mayor confiabilidad en el proceso de transmisin de
la informacin.
Para lograr el uso de todas las portadoras disponibles, se propone una nueva tcnica basada
en DBPSK, denominada DBPSK Adaptada. Al igual que la anterior, sta tcnica se basa en la
modulacin DBPSK, pero en lugar de trabajar con una sola portadora, utiliza todas las portadoras
disponibles. Bsicamente se dispone de un smbolo sintetizado conformado por todas las portadoras
disponibles a ste se le modifica su fase segn el bit que se transmita. Por lo cual, adems de las
ventajas de BFSK Adaptado, se le suma uso de todas las portadoras (que se traduce en mayor
redundancia y confiabilidad) y la necesidad de tener generado previamente un slo smbolo.

Figura 2.90. Diagrama de bloques de un modem DBPSK Adaptado [Trnka06-2].

sta tcnica podra adaptarse a BPSK (que es mejor que DBPSK), pero como la primera
requiere de un recuperador de portadora, una tcnica BPSK Adaptada requerira de un recuperador
de todas las portadoras utilizadas lo cual incrementara el costo de implementacin.

84

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

3. Descripcin del problema


En este captulo se realiza una comparacin entre las soluciones existentes presentadas en el
captulo anterior, y se analiza el alcance de cada una de ellas, para determinar los problemas no
resueltos a fin de presentar una propuesta de solucin algunos de stos ltimos. Los antecedentes
estudiados pertenecen en su mayora a dos ambientes diferentes. Las comunicaciones PLC se
desarrollan sobre el ambiente de infraestructura edilicia, diferente a las redes de datos utilizadas en
el ambiente de los automviles. Existen antecedentes sobre la integracin de tecnologas de ambos
ambientes, que brindan un punto inicial para continuar trabajando sobre ste tema. El presente
trabajo pretende contribuir en sta materia.

3.1. Alcance de las soluciones existentes


En general, los estndares existentes, tanto sobre tecnologa PLC como redes de datos para
automviles, no implementan todas las capas propuestos por el modelo OSI, salvo algunas
excepciones. Algunos estndares se centran en implementar solamente las capas fsica y de enlace,
pudiendo o no dar libertad de eleccin del medio fsico utilizado como canal de comunicaciones;
otros en cambio, implementan algunas de las capas superiores con la posibilidad de trabajar con los
estndares de primer tipo; y finalmente existen los estndares que implementan todas las capas del
modelo OSI, permitiendo incluso emplear diversos medios fsicos como canal de comunicaciones.

3.1.1. Comunicaciones PLC


Las comunicaciones PLC se encuentran reguladas por la norma CENELEC 50065, que
establece rango de frecuencias reservado para este tipo de comunicaciones. Los estndares que no
requieren demasiado ancho de banda, utilizados para sensores y actuadores, respetan la normativa
anterior. Los estndares ms evolucionados, generalmente empleados para transmisin de datos, se
ven forzados a trabajar en otro rango de frecuencias para brindar mayor velocidad de transferencia.
Entre los estndares del primer tipo se pueden mencionar: X10, UPB y LonWorks; mientras que
entre los estndares que no respetan CENELEC 50065 se pueden destacar: CEBus y HomePlug.
Los estndares X10, y su evolucin UPB, implementan las funcionalidades correspondientes
a la capas fsica y de enlace segn el modelo OSI. Solamente permiten la utilizacin de un nico
medio fsico, que en este caso son las lneas de energa. Se caracterizan por su simpleza, para se
implementados en dispositivos de bajo costo.
El estndar CEBus es similar a X10 y UPB, con respecto a las aplicaciones que hacen uso de
ste estndar. La diferencia radica en que CEBus puede trabajar sobre diversos medios fsicos, entre
los cuales se encuentran las lneas de potencia.
LonWorks es el nico estndar PLC de los analizados en el captulo anterior que implementa
todas las capas del modelo OSI, porque se basa en el protocolo CNP que define las siete capas. Al
igual que CEBus, define en su capa fsica un conjunto de medios fsicos sobre los cuales se puede
trabajar, entre los cuales figura las lneas de electricidad. Comparado con X10, UPB y CEBus,
LonWorks es el estndar que brinda mayor funcionalidad, y tambin es el ms complejo de
implementar.
Por ltimo se encuentra la familia de especificaciones HomePlug, que originalmente se
encontraban orientadas a brindar soporte para la creacin de redes IP empleando como medio de
FernandoArielBeunza79156

85

Tesis de Grado en Ingeniera Informtica


transmisin de datos las lneas de energa. Existen tres especificaciones, siendo la primera de ellas
(HomePlug 1.0) la que fue orientada para el propsito descripto anteriormente. La segunda
especificacin (HomePlug AV) introduce un conjunto de mejoras que adems de brindar soporte
para redes IP, permite el transporte de audio y video. Finalmente, la tercer especificacin
(HomePlug Green PHY) se encuentra orientada a control de dispositivos como X10, UPB, CEBus y
LonWorks.

3.1.2. Redes de automviles


Los estndares de redes de datos para automviles descriptos en el captulo anterior
generalmente implementan las capas inferiores (fsica y de enlace) del modelo propuesto por OSI.
Las redes CAN y J1850 son las ms utilizada en la industria automotriz, aunque existen otros tipo
de redes ms evolucionadas con mayores capacidades, empleadas en vehculos de alta gama, que
requieren de la implementacin de ms capas del modelo OSI.
CAN y J1850 se tratan de dos redes que presentan un funcionamiento similar aunque las
prestaciones que ofrecen son diferentes. Siguiendo el modelo de capas propuesto por OSI, ambas
redes implementan las capas fsica y de enlace; y adems J1850 implementa la capa de aplicacin
que consisten en una interfaz para interactuar con los dispositivos. Las especificaciones de CAN son
independientes del medio fsico utilizado como canal de comunicaciones, mientras que J1850
especifica que el medio fsico debe ser cableado elctrico con diversas configuraciones segn la
variante utilizada (VPW o PWM). La topologa de red utilizada en el caso de ambas redes es tipo
bus. Tanto las redes CAN como J1850, son redes del tipo multimaestro, por lo cual requieren de un
protocolo de control de acceso al medio CSMA/CR que permite resolver las colisiones. Las redes
CAN pueden trabajar en un rango amplio de velocidades de transferencia lo que extenderse a
diversas aplicaciones dentro de un automvil (aplicaciones de propsito general y tiempo real). En
cambio J1850 se encuentra preparado solamente para aplicaciones de propsito general, ya que la
limitada velocidad de transferencia que ofrece no soporta aplicaciones de tiempo real. Ambas redes
se encuentran orientadas a control, por lo cual se prioriza la robustez y simpleza de implementacin,
sobre tener gran capacidad para transporte de datos.
Las redes LIN estn diseadas como complemento de otras redes como CAN y J1850.
Solamente implementa las capas fsicas y de enlace. El medio fsico utilizado se compone de un
nico cable. La topologa utilizada por ste tipo de redes es tipo bus, y el bajo costo se debe a la baja
complejidad de implementacin que presenta gracias a que es una red del tipo maestro/esclavo, por
lo cual tampoco se requiere de ningn protocolo de resolucin de colisiones. La idea de LIN no es
brindar grandes capacidades de transferencia de datos, sino poder interconectar diversos
dispositivos cercanos entre si a bajo costo.
El estndar OSEK/VDX fue desarrollado con el objetivo de poder bajar los costos de los
dispositivos y garantizar la interoperabilidad entre los mismos. La idea es proponer una plataforma
de desarrollo de software reutilizable para dispositivos de un automvil que se intercomunican por
medio de redes CAN o J1850. OSEK/VDX surge como un complemento de las dos redes anteriores
implementando la capa de red del modelo OSI, sobre las capas de enlace y fsica provistas por CAN
y J1850.
Las redes D2B y MOST implementan las capas fsica y de enlace, y en el caso de MOST,
tambin se implementa una capa de aplicacin por encima de la capa de enlace. El medio fsico
utilizado en ambas redes es fibra ptica para la transferencia de datos y cableado elctrico para
funciones auxiliares. Las prestaciones que brinda cada tipo de red difieren entre s, MOST supera a
D2B por emplear una mejor calidad de cableado ptico que le permite aumentar la velocidad de
transferencia, la longitud de la red y la cantidad de dispositivos conectados. La topologa utilizada
86

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


en ambas redes es anillo para el cableado ptico y estrella para el cableado elctrico, en donde existe
un dispositivo que ejerce el rol de maestro de la red. El control de acceso al medio viene dado en
ambas redes por el mtodo de paso de testigo, que consiste en un testigo que circula por medio del
anillo que indica a cada dispositivo cuando transmitir, creando un canal de comunicacin libre de
colisiones. El mtodo de paso de testigo exigen la existencia de un dispositivo supervisor de la red
que el es dispositivo maestro, por lo cual D2B y MOST son redes del tipo maestro/esclavo. Tanto
D2B como MOST se encuentran orientadas a aplicaciones multimedia donde se requiere gran
capacidad de transporte de datos a alta velocidad.
Las redes FlexRay fueron diseadas para superar los problemas que presentan las redes D2B
y MOST, y proponer una mejora a las redes tradicionales CAN y J1850. De igual forma que las redes
analizadas hasta ahora, FlexRay implementa dos capas equivalentes a la capa fsica y de enlace del
modelo OSI. El medio fsico propuesto en este caso es cable par trenzado, lo cual lo hace una
alternativa ms econmica y sin los inconvenientes presentados por la fibra ptica utilizada en D2B
y MOST: Con respecto a la topologa, FlexRay permite utilizar configuraciones tipo bus, estrella o
combinacin de las anteriores, lo que otorga una gran flexibilidad en este aspecto. Adems es una
red multimaestro como CAN y J1850, eliminando las desventajas presentes en el esquema propuesto
por D2B y MOST. El mtodo para controlar el acceso al medio consiste en ranuras de tiempo fijas
asignadas a cada dispositivo para transmitir tramas de longitud fija, y en ranuras de tiempo variable
empleadas para la transmisin de tramas de longitud variable, en donde se determina que
dispositivo hace uso de ellas en base a la prioridad de la trama. En cuanto a capacidad de transporte
y velocidad, se encuentra entre algo intermedio entre CAN y J1850, y D2B y MOST; resulta una
gran mejora comparado con las capacidades prestadas por los dos primeros, pero no logra superar a
los dos segundos.

3.1.3. PLC en automviles


Las comunicaciones PLC en el ambiente del automvil deriva del desarrollo realizado sobre
ste tipo de comunicaciones para infraestructura edilicia analizado con anterioridad. Los requisitos
de ste ambiente son diferentes, como tambin los problemas que se plantean a la hora de introducir
una tecnologa diseada originalmente para un ambiente diferente. En el ste trabajo se estudia dos
desarrollos sobre esta materia: uno es el estndar DC-BUS desarrollado por la empresa Yamar
Electronics Ltd., y el otro son una serie de trabajos realizados por la Facultad de Ingeniera
Elctrica de la Universidad Tcnica Checa de Praga. En ambos casos se implementan la capa fsica
correspondientes al modelo OSI, y en el caso de DC-BUS tambin la capa de enlace, porque centran
su esfuerzo en resolver las cuestiones involucradas a las comunicaciones sobre lneas de potencia,
un medio fsico que conforma una red topologa hbrida, que no fue diseado para tal fin, brindado
soporte para otras redes que implementen las restantes capas.
DC-BUS es un desarrollo comercial que brinda la posibilidad de interconexin de
dispositivos por medio de la lnea de alimentacin de un automvil. ste estndar de comunicacin
PLC est pensado para brindar un puente entre las lneas de alimentacin y redes CAN, por lo cual
implementa las capas fsica y de enlace con una interfaz que permite interactuar con CAN. Las redes
DC-BUS, por trabajar con redes CAN, hereda su caracterstica de ser multimaestro, y el
inconveniente de las colisiones que son resuelvas por un mecanismo de arbitraje diseado
especialmente para ste estndar. DC-BUS es capaz de trabajar en rango de velocidad de
transferencia baja, media y alta; lo que le permite trabajar con aplicaciones de control, de telemtica
y multimedia, respectivamente.
Los trabajos desarrollados por la Facultad de Ingeniera Elctrica de la Universidad
Tcnica Checa de Praga, no son un desarrollo comercial como el caso de DC-BUS. Realizan un
FernandoArielBeunza79156

87

Tesis de Grado en Ingeniera Informtica


estudio sobre las caractersticas que presentan las lneas de alimentacin de un automvil, y como
podran usarse stas para transmisin de informacin. Plantean el desarrollo de un prototipo que
implementa las capas fsicas y de enlace, pero no define una interfaz para otras redes, como por
ejemplo CAN, como lo hace DC-BUS. La capacidad de transferencia que brinda corresponde a
aplicaciones de telemtica.

3.2. Requerimientos para la propuesta del presente


trabajo
Como se menciona en el anlisis anterior, las soluciones existentes, en general, centran su
atencin en implementar solamente las capas fsica y de enlace, dejando de lado las restantes capas
del modelo OSI. Tomando como punto de partida los trabajos desarrollados por la Facultad de
Ingeniera Elctrica de la Universidad Tcnica Checa de Praga sobre comunicaciones PLC en
automviles, y las ideas propuestas por los estndares referente a PLC y redes de datos de
automviles; el objetivo del presente trabajo es proponer una implementacin de las capas no
implementadas, que son las ms relacionadas con la informtica. La idea es similar a lo propuesto
por LonWorks que define las siete capas del modelo OSI, y a OSEK/VDX combinado con CAN o
J1850 que brinda una plataforma estndar de comunicacin entre dispositivos.
Aplicacin
Presentacin

Dispositivocliente(realovirtual)

Sesin
Transporte

Ncleodelsistema

Red
Enlace
Fsica

ModemPLC

Figura 3.1. Modelo de capas del sistema.

El desarrollo del sistema debe respetar el modelo de capas sugerido por OSI y sus principales
componentes pueden verse distribuidos en la figura 3.1. A diferencia de LonWorks u OSEK/VDX,
todas las capas no se pueden implementar dentro de un nico microcontrolador, ya que se pretende
separar las funcionalidades del dispositivo cliente con las relacionadas con las comunicaciones PLC,
para no aumentar la complejidad del firmware del dispositivo cliente.
El dispositivo cliente es el dispositivo que obtiene informacin suministrada por el sistema,
hace uso de ella, emite alguna accin que puede ser fsica y/o una respuesta hacia el sistema. En este
dispositivo deben implementarse las capas de aplicacin y presentacin debido a que la primera
constituye una interfaz para la funcin especfica del dispositivo, que en caso particular de este
trabajo es una funcionalidad demostrativa del funcionamiento del sistema; y la segunda se relaciona
a la representacin de los datos que depende de la plataforma, por ejemplo se puede tener un
dispositivo que enve un nmero entero a otro y cada uno de stos tiene una forma diferente de
representarlos lo cual requiere de un proceso de adaptacin para la correcta interpretacin del dato
en cuestin.

88

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


El ncleo del sistema debe comprender las capas de sesin, transporte y red. Es
responsabilidad del sistema establecer, gestionar y finalizar las conexiones entre los dispositivos
clientes (capa sesin). Adems el sistema debe garantizar, con distintos grados de confiabilidad, que
la informacin generada por un dispositivo llegu a los dispositivos destinatarios (capa de
transporte). Por ltimo, es responsabilidad del ncleo del sistema la identificacin de cada uno de
los dispositivos presentes en el bus de datos y el encaminado de los paquetes de informacin (capa
de red).
El modem PLC es el dispositivo fsico encargado de transmitir y recibir informacin por
medio del cableado elctrico (capa fsica) y de implementar el protocolo de acceso al medio fsico
de comunicacin que permita la transmisin de datos sin errores (capa de enlace).
Tanto el ncleo del sistema como el protocolo de enlace deben residir en el microcontrolador
del modem PLC para aprovechar al mximo las funcionalidades de ste dispositivo electrnico
bajando el costo en dinero del sistema.

Figura 3.2. Esquema de red.

En la figura 3.2 puede observarse el esquema general de la red de la cual slo es


recomendable la implementacin de un dispositivo cliente virtual sobre una PC, que simule la
realizacin de una tarea demostrativa; un dispositivo cliente real que ejecute alguna accin
demostrativa real y concreta; y una PC que supervise la red para comprobar su funcionamiento
(dispositivo diagnstico); como puede verse el la figura 3.3.

Figura 3.3. Esquema de red recomendable.

FernandoArielBeunza79156

89

Tesis de Grado en Ingeniera Informtica


Como el dispositivo cliente virtual y el dispositivo de diagnstico se implementan sobre una PC, se
puede concentrar las tareas de los dispositivos anteriores en uno slo para ahorra la construccin de
uno de los modems.
Tanto para la PC que implemente el dispositivo cliente virtual como para la que supervise la
red necesitan interfaces en lenguaje C/C++ para poder construir aplicaciones que simulen un
dispositivo cliente y permitan visualizar el funcionamiento de la red respectivamente. Adems las
mencionadas interfaces van a permitir la construccin de un biblioteca de bloques Simulink que
permitan construir aplicaciones de prueba mediante modelos grficos.
Para los dispositivos clientes reales, dado que stos necesariamente deben contener un
microcontrolador para acceder al sistema, tambin necesitan una versin de la interfaz anterior para
simplificar el acceso al sistema de intercambio de informacin.

90

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

4. Solucin propuesta
La solucin que se propone en el presente trabajo se compone de siete capas conforme al
modelo planteado por OSI. sta idea se basa en la forma de implementacin de LonWorks, que
tambin implementa las siete capas, y define desde los aspectos fsicos (capa fsica) hasta la interfaz
con los dispositivos usuarios de ste (capa de aplicacin). Aqu se intenta integrar las diversas ideas
propuestas por los antecedentes estudiados e integrarlas conformando cada una de las capas.
Las siete capas no se implementan en un slo microcontrolador, ya que se pretende no
involucrar las funciones propias del dispositivo cliente con las funciones relacionadas con las
comunicaciones PLC. De ste modo se provee un sistema de comunicaciones lo ms independiente
posible de la utilidad que se le de a ste, ya que la separacin absoluta no es posible, debido a que
las dos ltimas capas (capas de presentacin y aplicacin) se encuentran muy vinculadas con la
plataforma que emplea la implementacin del dispositivo cliente. Las restantes capas se
implementan dentro del modem PLC, aunque ste se compone de dos microcontroladores: uno
destinado exclusivamente a la capa fsica, y el resto a las capas de enlace, red, transporte y sesin

4.1. Capa fsica


Debido a la imposibilidad de tener acceso a modems PLC, y a que stos ltimos son
necesarios para evaluar la propuestas del presente trabajo, se requiere la construccin de un
hardware prototipo. El grado de complejidad del hardware en cuestin no podr exceder la
disponibilidad de los componentes electrnicos disponibles en el mercado Argentino.

4.1.1. Mtodo de acoplamiento


Como se mencion con anterioridad, en el trabajo Optimization of the Data Transmissions
over DC Power Lines [Trnka06-2], se implementa una variante del acoplamiento capacitivo
compuesto por dos capacitores en serie a la salida del transmisor. Otra variante del acoplamiento
capacitivo es la utilizada en redes LIN sobre PLC [BenziFacchinettiCaprini08] (figura 4.1), que
consiste en colocar filtros de rechazo de banda a la salida de la batera y a la entrada de los
dispositivo que consumen la energa proporcionada por la batera. De esta forma se bloquea el paso
de la seal con informacin a los puntos de la red con baja impedancia, solucionando el problema
de la baja impedancia del mtodo capacitivo. El transmisor se acopla a la red por medio de un
capacitor y una resistencia conectados en serie, y el receptor emplea un inductor, un capacitor y una
resistencia. Los capacitores son necesarios para el bloqueo de la seal continua de potencia, todos
los elementos mencionados anteriormente junto con la red cableada conforman un filtro pasa banda.

FernandoArielBeunza79156

91

Tesis de Grado en Ingeniera Informtica

Figura 4.1. Esquema de acoplamiento utilizado en redes LIN sobre PLC.

Para el caso del modem propuesto en el presente trabajo, a partir de las ideas anteriores, se
propone un mtodo basado en el acoplamiento capacitivo. La idea bsica de ste mtodo es
combinar la simpleza del mtodo de acoplamiento capacitivo con el esquema de filtrado, de forma
tal que el conjunto completo constituya un filtro pasa alto que solamente permita el paso de las
frecuencias de 4 MHz en adelante. Los conjuntos capacitor resistencia (ver figura 4.1) constituyen
un circuito de bloqueo de componente continua y un limitador de corriente, para limitar el consumo
de potencia del transmisor y del receptor. Los inductores cumplen la funcin de bloqueo de la seal
de informacin evitando que dicha seal no sea afectada por la baja impedancia de la batera y
dispositivos de carga considerable.

Figura 4.2. Esquema de acoplamiento a la red PLC propuesto.

El filtro pasa alto conformado por los elementos pasivos de la figura 4.2, no se caracteriza
por su selectividad ni tampoco es su principal objetivo, slo se limita a bloquear las frecuencias que
ste debajo de la banda de HF no utilizadas para las comunicaciones PLC en automviles. Por sta
razn, el receptor necesariamente debe contener un filtro ms selectivo que se concentre en dejar
pasar solamente la banda de frecuencias de inters. sto ltimo permite utilizar solamente una
92

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


porcin del espectro destinado para las comunicaciones PLC, dejando libre el resto, para
convivencia con futuras aplicaciones basadas en ste tipo de comunicaciones sin necesidad de
modificar el esquema propuesto en la figura 4.2.

4.1.2. Tcnica de modulacin


Debido a las caractersticas del canal de comunicaciones, la tcnica de modulacin ms
adecuada para transmitir la informacin no debe basarse en la amplitud (quedando descartada ASK y
QAM). Debido al desvanecimiento intermitente y selectivo de frecuencias, no puede emplearse una
tcnica de modulacin que utilice una sola portadora (ASK y variantes de PSK). Tampoco sera
adecuado el empleo de FSK debido a que se utiliza una frecuencia para representar cada smbolo
que se desea transmitir (BFSK utiliza una frecuencia para representar el cero y otra para representar
el uno), y en caso de desvanecimiento de una de las frecuencias utilizadas se perdera el smbolo
correspondiente a dicha frecuencia. Por lo cual puede concluirse que se requiere de una tcnica de
modulacin que utiliza mltiples portadoras para transmitir un smbolo, como por ejemplo OFDM.
El empleo de OFDM requiere de gran complejidad del transmisor y el receptor que
imposibilitara la implementacin del modem PLC con los componentes disponibles en el mercado
Argentino. Buscando un equilibrio entre confiabilidad y baja complejidad, se recurre a la tcnica de
modulacin DBPSK Adaptada [Trnka06-1] [Trnka06-2]. ste mtodo se basa en la tcnica
DBPSK, pero en lugar de emplear una sola portadora, emplea un conjunto de portadoras, lo que
hace que ste mtodo junte las ventajas de DBPSK con la resistencia al desvanecimiento provista
por la utilizacin de mltiples portadoras. Adems ste mtodo, por derivar de DBPSK, no requiere
la implementacin de un recuperador de portadora, lo cual simplifica el receptor.

Figura 4.3. Diagrama de bloques del modem prototipo desarrollado.

En la figura 4.3, se puede observar los bloques bsicos que conforman el modem prototipo
desarrollado para el presente trabajo similar al modem DBPSK Adaptado descripto anteriormente.
Se conforma de un codificador diferencia integrado por el retardo de un bit y una operacin lgica
o-exclusiva en el transmisor encargada de generar los cambios de fase de las portadoras en funcin
de los datos a enviar. Las portadoras son sintetizadas por un bloque dedicado para tal fin que genera
un nico smbolo que multiplicado por la fase generada por la salida del codificador diferencial
conforman la seal con la informacin que viaja a travs del canal de comunicaciones hasta llegar al
receptor. En el receptor, la mencionada seal, es retardada un tiempo equivalente a la duracin
temporal de un smbolo. La seal recibida y la seal retardada son multiplicadas entre s para poder

FernandoArielBeunza79156

93

Tesis de Grado en Ingeniera Informtica


distinguir la fase de cada smbolo recibido que contiene la informacin. Debido a que la seal
resultante de la multiplicacin resulta tener cierta cantidad de ruido que no permite distinguir
fcilmente el valor de los bits de informacin recibidos, dicha seal es procesada por un bloque
integrador que tiene el efecto de filtro pasa bajo resultando una seal que vara de nivel segn el bit
de informacin recibido. Por ltimo, un bloque detector se encarga de comparar la seal resultante
del integrador contra un valor de referencia utilizado para determinar si el bit de informacin
recibido corresponden a un cero o un uno.

4.1.3. Modem PLC


El modem PLC propuesto se basa en el dispositivo descripto en el trabajo, Power Line
Communications in Automotive Industry [Trnka05]. Debido a la no disponibilidad de ciertos
componentes que integran el modem original, en ste trabajo se implementa una versin diferente
realizable con los componentes disponibles en el mercado Argentino. No obstante, el modem
propuesto se basa en los mismos principios de funcionamiento del modem original.

Figura 4.4. Diagrama de bloques de un modem PLC prototipo.

Los componentes bsicos del modem PLC prototipo (figura 4.4), se describen a
continuacin:

94

Filtro: consiste en un filtro que rechaza la banda de frecuencias utilizada para transmitir
la informacin. Suministra la seal de potencia utilizada para alimentacin libre de ruido.

Fuente: proporciona energa a los bloques activos del modem PLC.

Transmisor: transmite la informacin por medio de la red de alimentacin utilizando la


tcnica de modulacin DBPSK Adaptada, cuya implementacin se describe ms adelante.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Receptor: recibe informacin por medio de la red alimentacin modulada con la tcnica
DBPSK Adaptada. La implementacin del receptor se describe ms adelante.

Microcontrolador procesador de seales: contiene el software asociado procesamiento de


seales. Por sus prestaciones, resulta adecuado la utilizacin del microcontrolador AVR
ATmega8515 que permite ejecutar ciertas instrucciones en un ciclo de reloj
[ATmega8515].

Microcontrolador de procesamiento: contiene el software asociado al ncleo sistema y el


protocolo de enlace. Por sus prestaciones, resulta adecuado la utilizacin del
microcontrolador 8052 AT89S52 que permite almacenar el software anteriormente
mencionado en una memoria externa ms grande que la provista por el microcontrolador
y brinda la posibilidad de expandir la memoria RAM [AT89S52] [AT89CMemOrg].

Memoria: extiende la capacidad de almacenamiento de la memoria RAM del


microcontrolador. Para ste caso resulta suficiente que la capacidad de la mencionada
memoria sea de 32KB. Esta memoria adicional es necesaria para poder implementar una
cola de mensajes.

Interfaz RS232: brinda una interfaz con el dispositivo cliente del sistema.

Los detalles sobre la implementacin del modem PLC se encuentran en el Apndice A


(Implementacin del hardware del modem PLC), en donde se describen los componentes que
constituyen el modem PLC con ms precisin.

4.1.4. Implementacin del sistema de comunicaciones


Tanto el proceso de transmisin como de recepcin se componen de dos partes
fundamentales: la parte fsica implementada con circuitos dedicados y la parte lgica constituida por
algoritmos ejecutados por el microcontrolador procesador de seales. Esta implementacin permite
simplificar los circuitos dedicados y mejorar el procesamiento de las seales involucradas en el
proceso de comunicacin.

4.1.4.1. Implementacin fsica


Como se mencion anteriormente la tcnica de modulacin utilizada es DBPSK Adaptada
por su posibilidad de ser implementada con la tecnologa de componentes disponible y su
inmunidad ante los problemas que presenta el canal de comunicaciones utilizado para las redes
PLC.
La adopcin de este sistema de modulacin implica una velocidad de transmisin de datos
constante (por derivar DBPSK) [Tropeano03], y la necesidad de implementar un sintetizador de
portadoras. sta ltima cuestin es la ms problemtica dado que resulta dificultoso sintetizar
frecuencia del rango de HF en forma directa. La solucin adoptada fue la sntesis de frecuencias
bajas y su posterior conversin [AlleyAtwood68] a un rango de frecuencias de HF. Esta solucin
permite que un microcontrolador, que emite una instruccin por ciclo de reloj, pueda sintetizar
frecuencias que van desde los 0 hz hasta la cuarta parte de la frecuencia de reloj sin mayores
inconvenientes.
FernandoArielBeunza79156

95

Tesis de Grado en Ingeniera Informtica


El transmisor se compone de un sintetizador de portadoras, implementado por firmware del
microcontrolador (ver Implementacin lgica), encargado de generar los smbolos utilizados para
transmitir los bits de informacin, que alimentan el conversor digital analgico. La seal resultante
es amplificada y filtrada, y a partir de ella se generan dos seales desfasadas entre s por un ngulo
de 180, debido a que la conversin de frecuencias se realiza por medio de un modulador VSB-SC
(banda lateral vestigial con portadora suprimida), que requiere la seal de informacin con ngulos
de desfasaje 0 y 180. La razn de la utilizacin de ste tipo de modulador es el ahorro de energa
por no transmitir la portadora (la frecuencia de traslacin) y que el nmero de componentes en
frecuencia de la seal smbolo se duplican por tratarse de una tcnica de modulacin de doble banda
lateral (mayor cantidad de componentes en frecuencia se corresponde con una mayor redundancia y
mayor confiabilidad). La seal resultante se encuentra en el rango de frecuencias de HF, y sta
ingresa al amplificador de salida encargado de alimentar al circuito de acoplamiento encargado de
propagar la seal a lo largo de la red de potencia.
En el Apndice B (Simulacin del hardware del modem PLC) se especifica en detalle los
componentes del transmisor mencionados anteriormente, en donde el sintetizador de portadoras se
encuentra implementado por un circuito especial que simula al microcontrolador, y la seal
resultante puede verse en la parte de dicho apndice donde se muestran los resultados de la
simulacin.
El receptor se encarga de realizar los pasos en sentido inverso del transmisor. La seal que
viaja por medio de la red de potencia llega al circuito de desacoplamiento en donde se filtra la
componente contina, quedando solamente la seal con la informacin que alimenta al amplificador
de entrada. Dicho amplificador se encarga de amplificar y filtrar de forma ms selectiva la seal con
la informacin para el posterior proceso de conversin de frecuencias. El convertidor de frecuencias
(demodulador VSB-SC) se encarga de convertir las componentes en frecuencia de HF de la seal
con la informacin a componentes en frecuencia manejables por el microcontrolador. La seal
resultante de la conversin se digitaliza por medio de un ADC de un bit [Trnka06-2], debido a que
el ruido introducido por ste tipo de conversor no afecta significativamente el proceso de
demodulacin y ste resulta ms simple de implementar. Debido a que la seal se digitaliza con un
bit, se pueden formar grupos de 8 bits, para que el microcontrolador los lea en paralelo y almacene
en registros internos, permitiendo la implementacin de una lnea de retardo 80 bits (el smbolo se
compone de 80 muestras) con la utilizacin de 10 registros internos (de 8 bits cada uno). Con la
seal obtenida leda directamente y la resultante de la lnea de retardo se aplica la operacin lgica
o-exclusiva (que ms se asemeja a la multiplicacin de seales), obtenindose una nueva seal
digital que se caracteriza por tener ciclos de 80 muestras con muchos ceros (asociados a un bit de
informacin de valor uno) o con muchos unos (asociados a un bit de informacin de valor cero). El
mecanismo de cuantificar dichos ceros y unos, se realiza por medio de una fuente de corriente,
controlada por los bits resultantes de la operacin o-exclusiva, que carga un capacitor;
implementado de sta forma un integrador. La seal resultante del integrador es comparada contra
un umbral de referencia (determinado por el microcontrolador), para determinar el valor del bit de
informacin recibido.
En el Apndice B (Simulacin del hardware del modem PLC) se especifica en detalle los
componentes del receptor mencionados anteriormente. El microcontrolador se encuentra simulado
por un circuito especial que realiza el procesamiento de las muestras de forma similar a como lo
hara el correspondiente algoritmo. Las seales involucradas en el proceso de recepcin y la
informacin recuperada puede verse en la parte de dicho apndice donde se muestran los resultados
de la simulacin.

96

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 4.5. Diagrama de bloques del transmisor y receptor de un modem PLC prototipo.

En el modem PLC propuesto, se utiliza como microcontrolador procesador de seales el


AVR ATmega8515 con una frecuencia de reloj de 11,0592 MHz, lo que permite sintetizar
frecuencias del rango 0 a 2,7648 MHz. Los convertidores de frecuencia operan con un oscilador de
16 MHz lo que permite trasladar las frecuencias sintetizadas al rango comprendido entre 13,2352 y
15,86176 MHz. Dicho rango de frecuencias resulta adecuado segn el anlisis realizado
previamente sobre las caractersticas del canal de comunicaciones.

4.1.4.2. Implementacin lgica


Como se observa en la figura 4.5, ciertos componentes del transmisor y receptor no se
implementan con circuitos dedicados sino que se utiliza un microcontrolador dedicado para realizar
la sntesis de la seal y la decodificacin de la misma. La ventaja de optar por sta alternativa es la
simplificacin de los circuitos del modem PLC. Los bloques sealados en la figura mencionada
corresponden a los algoritmos de envo y recepcin respectivamente.
El algoritmo de envo consiste en recibir una trama de bits con la informacin a enviar,
aplicar codificacin diferencial a dicha trama de bits, y generar el smbolo correspondiente por cada
bit resultante del proceso de codificacin. Los smbolos utilizados para transmitir dichos bits se
encuentra conformado por 80 muestras, cuyos valores para uno de ellos se pueden ver en la tabla 4.2
(el otro smbolo corresponde a la misma seal desfasada en 180), y generan una seal compuesta
por 19 portadoras equiespaciadas en frecuencia dentro de los 0 a 2,7648 MHz (tabla 4.3) de la forma
especificada en la figura 4.6, cuyo espectro en frecuencia es el detallado en la figura 4.7. Cada una
de las portadoras mencionadas presenta una fase inicial (tabla 4.3) predeterminada para obtener la
FernandoArielBeunza79156

97

Tesis de Grado en Ingeniera Informtica


menor relacin entre pico y promedio de amplitudes (conocido como PAR) del smbolo [Trnka06-2] ,
lo que permite que las amplitudes se encuentren comprendidas dentro de un rango de valores no
muy grande, para que el conversor analgico digital del receptor pueda digitalizar la seal recibida
de forma adecuada.
Con una frecuencia de operacin del microcontrolador de 11,0592 MHz, la duracin en
tiempo del smbolo es de 7,234 microsegundos aproximadamente, lo que implica una velocidad de
transferencia de informacin cercana a los 140 Kbps (dado que cada smbolo representa a un bit).
N Seal Cod.

N Seal Cod.

N Seal Cod.

N Seal Cod.

N Seal Cod.

09

17

-4

03

33

0A

49

04

65

0B

-3

04

18

-6

01

34

0C

50

07

66

0A

-6

01

19

-4

03

35

0B

51

08

67

07

-5

02

20

-2

05

36

0B

52

-2

05

68

-3

04

-2

05

21

-2

05

37

0B

53

-2

05

69

-2

05

07

22

-3

04

38

09

54

0A

70

09

07

23

07

39

-4

03

55

0E

71

0B

-1

06

24

0A

40

-6

01

56

0B

72

09

-1

06

25

09

41

-1

06

57

-2

05

73

-3

04

10

-1

06

26

-4

03

42

0D

58

-4

03

74

-3

04

11

07

27

-7

00

43

0D

59

07

75

09

12

08

28

-2

05

44

08

60

0C

76

0E

13

09

29

0C

45

-2

05

61

0D

77

0D

14

09

30

0B

46

-3

04

62

0B

78

0D

15

09

31

07

47

-3

04

63

0B

79

0D

16

07

32

-1

06

48

-4

03

64

0B

80

0D

Tabla 4.1. Valores de las muestras del smbolo.


Portadora

Frecuencia

Portadora

Frecuencia

Portadora

Frecuencia

138,237 KHz

1105,895 KHz

15

2073,553 KHz

276,474 KHz

1244,132 KHz

16

2211,789 KHz

414,711 KHz

10

1382,368 KHz

17

2350,026 KHz

552,947 KHz

11

1520,605 KHz

18

2488,263 KHz

691,184 KHz

12

1658,842 KHz

19

2626,500 KHz

829,421 KHz

13

1797,079 KHz

967,658 KHz

14

1935,316 KHz

Tabla 4.2. Valores de frecuencia de cada portadora del smbolo.


Portadora
Fase

180

-180

-180 -180

180

-180

180

10

11

-135 -180

12

13

14

15

16

17

18

19

-180

45

135

135

180

Tabla 4.3. Valores de fase de cada portadora del smbolo.

98

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 4.6. Grfico de la seal sintetizada


correspondiente a un smbolo.

Figura 4.7. Grfico del espectro de la seal


sintetizada correspondiente a un smbolo.

El microcontrolador AVR ATmega8515 permite emitir una muestra por ciclo de reloj si stas
se encuentran previamente cargadas en registros, ya que la carga a registro de la muestra consume
un ciclo de reloj y la emisin de la muestra requiere de otro ciclo de reloj. Debido a que no se
disponen de 80 registros para almacenar todas las muestras se sintetiza la seal de tal forma que se
repitan frecuentemente los valores de las muestras, lo que permite reducir 80 muestras a un nmero
manejable de 15. Adems las muestras son emitidas cuando su valor cambia, por ejemplo, si existen
dos o ms muestras consecutivas con el mismo valor, se emite slo una vez la muestra en cuestin
ya que el valor de sta queda retenido en el puerto de salida del microcontrolador hasta que sea
modificado nuevamente. sto ltimo permite que el microcontrolador pueda realizar otras tareas
hasta tanto no sea necesario modificar el valor de la muestras. Una de stas tareas es el cambio de
fase del smbolo segn la codificacin diferencial del bit de informacin a enviar.
La codificacin diferencial consiste en generar una nueva seal a partir de los cambios de
estado que sufre la seal con la informacin, y suponiendo que la duracin de cada estado es
constante, no es necesaria la introduccin de una seal de sincronismo para poder recuperar la
informacin. En cambio si es necesario un codificador en el transmisor y un decodificador en el
receptor que son simples de implementar ya que su lgica es la siguiente:
codificador:

c(t)=not(c(t1)xors(t))

decodificador: s(t)=not(c(t)xorc(t1))
Figura 4.8. Expresiones lgicas del codificador y decodificador diferencial.

La expresin lgica correspondiente al codificador se implementa dentro del algoritmo sintetizador


de seal y el clculo se lleva a cabo en forma paralela a la emisin de las muestras del smbolo (se
aprovecha los instantes de no variacin del valor de la muestra en los que no se debe modificar el
estado del puerto de salida, y en lugar de introducir una espera, se realiza el clculo). La secuencia
de instrucciones encargadas de la sntesis de la seal pueden verse en detalle en el Apndice C
(Cdigo fuente), ms especficamente en la implementacin de la parte de la capa fsica
perteneciente al firmware procesador de seales, en la rutina dedicada al envo de trama de bits.
FernandoArielBeunza79156

99

Tesis de Grado en Ingeniera Informtica


La expresin lgica correspondiente al decodificador se implementa dentro de algoritmo de
recepcin. Por ejemplo dada una seal de informacin representada por los siguientes 4 bits 1001,
suponiendo que el estado inicial es uno, el resultado de la codificacin diferencial sera 1011, y la
fase de los smbolos respondera a sta ltima secuencia (siendo uno la fase 0 y cero la fase 180).
El decodificador diferencial se compone de una lnea de retardo (implementada con los registros
internos del microcontrolador) y un multiplicador de seal (implementado con la operacin oexclusiva provista por el microcontrolador) que multiplica la seal recibida y la misma seal retarda
el mismo tiempo de duracin de un smbolo. El resultado final es una seal que pasada por un
integrador (implementado de forma fsica) y luego por un detector de nivel devuelve la informacin
original 1001. La implementacin de lo anteriormente descripto se encuentra detallada en el
Apndice C (Cdigo fuente), ms especficamente en la implementacin de la parte de la capa fsica
perteneciente al firmware procesador de seales, en la rutina dedicada a la captura de seal.

Figura 4.9. Diagrama de flujo correspondiente al algoritmo de envo.

100

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 4.10. Diagrama de flujo correspondiente al algoritmo de recepcin.

En las figuras 4.9 y 4.10 se muestran los diagramas de flujo correspondientes a los
algoritmos de envo y recepcin, respectivamente. En dichos diagramas se hace mencin al
operaciones principales que involucran cada uno de los algoritmos. Todas las operaciones
relacionadas a la emisin de muestras y recepcin de las mismas, se realizan en tiempo real, lo que
implican que no pueden ser interrumpidas por ningn otra operacin pendiente. Las operaciones que
no requieran ser realizadas en tiempo real se realizan antes o despus del bloque de operaciones que
requieren ser ejecutadas en tiempo real.

FernandoArielBeunza79156

101

Tesis de Grado en Ingeniera Informtica

4.1.5. Estructura de tramas


La informacin se enva por medio de tramas compuestas de dos secuencias delimitadoras
(una de comienzo y otra fin), y entre dichas secuencias se encuentra la informacin. La cantidad de
informacin que puede contener una trama esta limitada por la memoria que dispone el mdulo de
procesamiento de seales que permite un mximo de 400 bytes. El receptor comienza a almacenar
la informacin recibida en su memoria luego de detectar el delimitador de inicio y almacena la
cantidad de bytes que le indica la capa inmediata superior, ya que la estructura de la trama no posee
ningn campo que contenga el tamao de la trama. El manejo del tamao de la trama, entre otras
cuestiones, se delega a la capa superior quien es la que determina el tamao de la trama esperada
por el receptor. El delimitador de fin se utiliza para espaciar las tramas. A continuacin se muestra
en la figura 4.11 la estructura de la trama descripta:
Delimitador
de inicio

Datos

Delimitador
de fin

128 bits

3200 bits

16 bits

16 bytes

400 bytes

2 bytes

Figura 4.11. Estructura de una trama.

Delimitador de inicio: secuencia de bits 128 bits utilizada para marcar el inicio de la
trama. La secuencia se compone de tres partes, una primera parte encargada de marcar la
ocupacin del canal de comunicacin (16 bits de valor uno, seguido de 1 bit de valor
cero, seguido de 23 bits de valor uno), una segunda parte utilizada por el receptor para
ajustar su umbral de deteccin (secuencia 01 repetida 32 veces), y por ltimo una
secuencia indicadora de comienzo del mensaje (secuencia de 16 bits con valor uno
seguida de la secuencia 11011011).

Datos: informacin transportada. La mxima capacidad de transporte son 400 bytes.

Delimitador de fin: secuencia de 16 bits de valor uno utilizada para marcar el fin de la
trama.

4.1.6. Funciones adicionales


Adems de las funciones principales que cumple la capa fsica, que son el envo y recepcin
de tramas, existen otras funciones auxiliares que requiere la capa inmediata superior, ms
especficamente la subcapa de control de acceso al medio.
Una de stas funciones auxiliares es la generacin de ruido, utilizado para indicar la
ocupacin de canal. El ruido se compone de una secuencia de bits pseudoaleatorios transmitidos de
igual forma que una trama. sta funcin permite a la subcapa de control de acceso al medio indicar
la ocupacin del canal de comunicaciones.
La anterior funcin se encuentra asociado con la funcin de escucha del canal de
comunicaciones. sta funcin se encarga de escuchar la actividad presente en el canal durante un
tiempo especificado, y reportar cuando se sobrepasa un determinado umbral de energa. sta
funcin es empleada por la subcapa de control de acceso al medio para determinar la ocupacin o no
del canal de comunicaciones, siendo la subcapa de control de acceso al medio quien determina el
tiempo de escucha, y el umbral que se debe sobrepasar para considerar el canal ocupado.
102

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Las anteriores funciones brindan soporte a la subcapa de control de acceso al medio para que
sta pueda implementar el algoritmo que controla el acceso al medio, y el mecanismo de
confirmacin de recepcin.
Adems de las funciones descriptas hasta el momento, existen otras orientadas a la
realizacin de pruebas de funcionamiento, y para evaluacin de los componentes del hardware
descripta en el captulo 5. Las funciones permiten la generacin de seales de prueba utilizadas
verificar el correcto funcionamiento del hardware y evaluar la respuesta en frecuencia del mismo.

4.1.7. Primitivas de manejo de la capa fsica


Como se mencion anteriormente, ciertos componentes del transmisor y receptor no se
implementan fsicamente con circuitos dedicados, sino que se utiliza un microcontrolador dedicado
exclusivamente al procesamiento de seales. Tambin se hizo mencin a que esta forma de
implementacin tiene la ventaja de simplificar los componentes fsicos del modem PLC, pero dicha
simplificacin trae como consecuencia la creacin de un firmware adicional de procesamiento de
seales para resolver las cuestiones no resueltas por los componentes fsicos. Adems es necesario
implementar firmware adicional que permita la comunicacin entre el microcontrolador dedicado al
procesamiento de seales y el microcontrolador dedicado al procesamiento de mensajes.
Debido a que se ha optado como norma para la realizacin de ste trabajo el respetar el
modelo OSI de capas independientes entre s, es necesario implementar un conjunto de primitivas
que brinden una abstraccin hacia las capas superiores del manejo de los aspectos fsicos que
involucran en proceso de comunicacin (comunicacin entre los microcontroladores mencionados
anteriormente, sntesis de seales, decodificacin de las mismas, etc.). De esta forma se deja abierta
la posibilidad de futuras actualizaciones de la capa fsica, sin que stas alteren la implementacin de
las restantes capa superiores.
A continuacin se detallan las primitivas referentes al manejo de la capa fsica (cuya
implementacin se detalla en el Apndice C, especificacin del cdigo fuente del firmware del
modem PLC) que permiten manejar al procesador de seales desde el microcontrolador dedicado al
procesamiento de mensajes, proporcionando las funcionalidades de inicializacin y liberacin de
recursos (activacin y desactivacin del transmisor y/o receptor), envo de tramas y recepcin de los
mismas, y otras funcionalidades ms especificas referentes al hardware:

void phy_init(void):
Inicializa los recursos que comprenden todo el proceso de comunicacin por medio de la
red de potencia. Inicializa el buffer de mensajes, inicializa la interrupcin de recepcin de
mensajes y pone en funcionamiento al circuito receptor.

void phy_release(void):
Libera los recursos que comprenden todo el proceso de comunicacin por medio de la red
de potencia inicializados por la primitiva anterior.

short int phy_sndframe(const void *dat, short int size):


Enva una trama dat de longitud size. Esta primitiva tiene la responsabilidad de generar, a
partir de la anterior trama, la seal con la informacin que es transmitida por la red de
potencia. Implementa el algoritmo de envo detallado en la figura 4.9. Devuelve como
resultado la cantidad de bytes enviados, que coincide con size si la operacin de envo
pudo ser realizada.

FernandoArielBeunza79156

103

Tesis de Grado en Ingeniera Informtica

104

int phy_capframe(short int size):


Inicia la captura de una trama de longitud size. Esta primitiva se encarga de poner al
mdulo de procesamiento de seales en espera de una trama. Dicho mdulo comenzar a
almacenar la trama recibida al momento que detecte el patrn de bits preestablecido por el
mdulo de procesamiento de seales. La captura finaliza cuando se lee la cantidad de
bytes especificados por el parmetro size. Mientras no se detecte la llegada del patrn de
bits preestablecido, el mdulo de procesamiento de seales se encuentra en espera, que
puede ser interrumpida por cualquier otra operacin. Esta primitiva implementa el
algoritmo detallado en la figura 4.10. En caso de haberse podido dar inicio a la captura
devuelve como resultado un valor positivo distinto a cero.

short int phy_getframe(void *dat, short int size):


Lee size bytes del contenido del buffer del mdulo de procesamiento de seales y lo
almacena en dat. En caso de haberse ejecutado la primitiva anterior, y haber llegado una
trama, el buffer contendr mencionada trama. En caso de haberse ejecutado la primitiva
de envo de trama, el buffer contendr la trama enviada. El contenido de buffer podr
leerse de forma repetida obteniendo la misma informacin hasta que no sea limpiado, por
la correspondiente primitiva, o modificado por el envo o la captura de una nueva trama.
Como resultado devuelve la cantidad de bytes ledos del buffer.

void phy_notify(void (*func)(void)):


Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
haya capturado una trama. El objetivo de sta primitiva es evitar la espera de la llegada de
una trama, realizando permanentemente consultas y consumiendo recursos del
microcontrolador.

int phy_poll(void):
Esta primitiva verifica si se ha capturado una trama. Devuelve como resultado uno si el
buffer contiene una trama capturada a la espera de ser leda mediante la primitiva
phy_getframe. Si no se ha capturado ninguna trama el resultado devuelto es cero. Con
esta primitiva se puede implementar una espera de la llegada de una trama, en
circunstancias en las cuales no sea conveniente utilizar la primitiva anterior.

int phy_rsdsignal(void):
Esta primitiva se similar a phy_sndframe, pero no es necesario especificar la trama a
enviar, ya que repite el ltimo envo realizado. sto permite implementar de forma ms
eficiente la repeticin de envos evitando la transferencia de la trama hacia el mdulo de
procesamiento de seales. Tambin puede utilizarse para reenviar una trama capturada
mediante la primitiva phy_capframe. En caso de haberse podido realizar el reenvo
devuelve como resultado un valor positivo distinto a cero.

int phy_clrbuffer(void):
Esta primitiva permite limpiar el contenido del buffer del mdulo de procesamiento de
seales. En caso de haberse podido realizar dicha operacin devuelve como resultado un
valor positivo distinto a cero.

int phy_sensechannel(unsigned char thrl, long int usecs):


Esta primitiva permite sensar el estado del canal de comunicaciones durante un tiempo de
usecs microsegundos. Mientras no se detecte ocupacin del canal de comunicaciones, el
FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


mdulo de procesamiento de seales, se encuentra a la espera (durante el tiempo
establecido) de una seal que ocupe dicho canal cuya energa alcance el nivel de umbral
establecido por thrl. En caso que se alcance dicho nivel de umbral, se interrumpe la
espera y devuelve como resultado un valor positivo distinto a cero. Una vez transcurrido
el tiempo de espera, devuelve como resultado el valor cero.

int phy_gennoisesignal(void):
Esta primitiva permite generar una seal de ruido que ocupe el canal de comunicaciones.
Dicha seal de ruido se genera a partir de una secuencia pseudoaleatoria de bits
modulados en BPSK. La generacin de la seal de ruido puede ser interrumpida en
cualquier momento por la ejecucin de cualquier otra primitiva. En caso de haberse
podido dar comienzo a dicha operacin devuelve como resultado un valor positivo
distinto a cero.

int phy_tstsignal1(void):
Esta primitiva permite generar una seal de prueba. La seal es una onda senoidal de
138,237 KHz, utilizada solamente para realizar pruebas de hardware. La generacin de
dicha seal puede ser interrumpida por la ejecucin de cualquier otra operacin. En caso
de haberse podido dar inicio a la generacin de la seal de prueba devuelve como
resultado un valor positivo distinto a cero.

int phy_tstsignal2(void):
Esta primitiva permite generar una seal de prueba. La seal es una onda senoidal de
552,947 KHz, utilizada solamente para realizar pruebas de hardware. La generacin de
dicha seal puede ser interrumpida por la ejecucin de cualquier otra operacin. En caso
de haberse podido dar inicio a la generacin de la seal de prueba devuelve como
resultado un valor positivo distinto a cero.

int phy_tstreceive(void):
Esta primitiva permite verificar la recepcin de seales por parte del receptor. La prueba
de recepcin puede ser interrumpida por la ejecucin de cualquier otra operacin. En caso
de haberse podido dar inicio a la generacin de la seal de prueba devuelve como
resultado un valor positivo distinto a cero.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la capa fsica, en siete primitivas el envo, recepcin y manipulacin de
tramas por medio de una red de potencia, en dos primitivas de manipulacin del canal de
comunicacin, y en tres primitivas de prueba. Las tramas recibidas son bytes en bruto los cuales no
presentan ningn tipo de control de error ni ninguna identificacin del dispositivo originario y
destinatario. Es responsabilidad de la capa superior (enlace) el resolver stas ltimas cuestiones.

4.2. Capa de enlace


La capa fsica brinda la posibilidad de transmitir tramas por medio de la red PLC, lo cual no
es suficiente para intercomunicar dos o ms dispositivos, ya que se requiere que la informacin
fluya por medio de un circuito de transmisin de datos libre de errores. Para lograr sto ltimo, la
capa de enlace tiene la responsabilidad de recibir la informacin fragmentada en paquetes,

FernandoArielBeunza79156

105

Tesis de Grado en Ingeniera Informtica


conformar tramas a partir de dichos paquetes, gestionar un mecanismo de direccionamiento para
dichas tramas, controlar el flujo de la informacin, garantizar que la informacin llegu a destino
libre de errores y controlar el acceso al medio fsico utilizado para transmitir las tramas.
La implementacin de la capa de enlace se subdivide en dos subcapas: control de acceso al
medio (conocida como MAC) y control de lgica de enlace (conocida como LLC).

4.2.1. Subcapa de control de acceso al medio


La subcapa de control de acceso al medio se encarga principalmente de controlar el acceso a
un nico medio fsico comn a todos los modems PLC. Otras responsabilidades de esta subcapa son
el direccionamiento de los paquetes y controlar que los mismos, cuando lleguen al receptor, no
tengan errores.

4.2.1.1. Caractersticas del medio


Todos los modems PLC utilizan como nico medio de comunicacin la red de potencia. La
consecuencia de sto ltimo es que dichos dispositivos no pueden transmitir en forma simultnea,
por lo cual necesitan de un mecanismo de coordinacin para que todos los dispositivos puedan
transmitir sus tramas de informacin en algn momento evitando que haya colisiones de tramas o,
por lo menos, si ocurren colisiones exista algn mecanismo de resolucin.
Otra caracterstica del medio es que la capa fsica slo brinda un servicio de transmisin de
tramas sin ningn tipo de control de errores, lo que significa que existe la posibilidad de recibir
tramas con informacin errnea debido a ruido en la red de potencia o interferencia (en el caso de
que haya colisiones).
Por ltimo, debe observarse, que al tratarse de un nico medio comn, todo lo que sea
transmitido a travs de l ser escuchado por todos los dispositivos conectados al medio (broadcast),
lo que implica que en los receptores es necesario implementar un mecanismo de filtrado, ya que no
todos los dispositivos estn interesados en recibir todas las tramas (mecanismo de
direccionamiento). Adems del direccionamiento de los dispositivos, es necesario implementar un
mtodo de tratamiento de errores basado en la retransmisin de tramas.

4.2.1.2. Mtodo de acceso al medio


Como se mencion anteriormente, el modem PLC requiere de un mecanismo de control de
acceso al nico medio fsico de comunicaciones compartido con otros modems. El medio fsico slo
soporta una transmisin a la vez porque slo se dispone de un slo canal y mltiples transmisiones
en simultneo corrompen el contenido de las mismas, por lo tanto la nica forma de que todos los
modems puedan realizar transmisiones sin interferirse entre s es estableciendo un protocolo de
gestin del canal de comunicaciones.
En el mbito de redes se han implementado diversos mtodos para resolver sta cuestin del
acceso al medio. Existen mtodos que garantizan tiempos de acceso determinsticos, como los que
hacen uso de un testigo que es utilizado como un permiso de utilizacin del canal de
comunicaciones. Ejemplos de stos son las redes Token Ring y Token Bus [Stallings97], en donde,
para el caso de las primeras los dispositivos se interconectan entre s formando un anillo (como
sucede en redes como D2B y MOST) por donde circula el testigo, que habilita al dispositivo que lo

106

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


posee a enviar un mensaje que circula por todo el anillo hasta volver al dispositivo que lo origin,
quien lo retira de circulacin (en circunstancias de normal funcionamiento). Las redes Token Bus
funcionan de modo similar, pero el anillo no es fsico sino que se crea un anillo lgico sobre una red
fsica tipo bus. Estos mtodos de acceso al medio mencionados y sus derivados pueden garantizar
un tiempo de acceso determinstico porque se puede calcular el tiempo mximo que un dispositivo
que entrega el testigo lo vuelve a obtener en funcin a la cantidad de dispositivos presentes en la
red. sto ltimo puede funcionar de forma eficiente con redes con pocos dispositivos, pero al
aumentar el nmero de dispositivos se eleva el tiempo que tarda el testigo en circular por toda la red
lo que puede provocar que las comunicaciones sean muy lentas. Adems el mantenimiento del
anillo requiere una lgica compleja ya que la cada de un dispositivo provoca que se rompa el anillo,
por lo que deben implementarse mtodos de recuperacin. Algo similar puede ocurrir si se pierde el
testigo, porque se perdi la conexin con el dispositivo que lo posea en ese momento.
Como los mtodos anteriores tiene como punto dbil la cantidad de dispositivos conectados
y el mantenimiento de la estructura lgica de comunicacin, han surgido con xito otros mtodos
que garantizan tiempos de acceso probabilsticos independientes de la cantidad de dispositivos de la
red, y con una lgica ms simple. El primero de ellos es el CSMA/CD [Stallings97] utilizado en las
redes Ethernet que consiste en que un dispositivo que desee transmitir un mensaje, primero debe
escuchar el canal y si se encuentra libre puede transmitir, en caso de que otro dispositivo haya hecho
algo similar ocurrir una colisin que ser detectada por ambos dispositivos; en tal caso cada uno
aplicar un tiempo de espera aleatorio y luego volvern a intentar transmitir. ste proceso puede
derivar en varios reintentos de transmisin que sumado a los tiempos de espera aleatorios hacen que
no se pueda garantizar un tiempo mximo de demora para transmitir un mensaje (carcter
probabilstico), pero ste mtodo de gestionar el medio no necesita de una lgica adicional para
mantener un anillo como ocurra en los mtodos de tiempo determinstico.
El mtodo CSMA/CD puede funcionar bien para transmisin de datos en general, pero no
resulta muy adecuado en aplicaciones de tiempo real en donde se necesita predecir con ms certeza
el tiempo que tarda en enviarse un mensaje a lo largo de la red, ms an sin existen muchos
dispositivos queriendo transmitir, lo que provoca el aumento de la colisiones. Para mejorar estos
inconvenientes han surgido modificaciones a ste mtodo que se centran en resolver las colisiones
para evitar la retransmisiones de mensajes que pueden ocasionar ms colisiones. Uno de ellos es el
utilizado en redes CAN y J1850 que trabaja con el esquema de bit dominante, en el cual cada
mensaje se compone de una cabecera con una secuencia de bits destinada al arbitraje en caso de que
se produzca una colisin. Si existen varios dispositivos transmitiendo en forma simultnea,
continuar transmitiendo el dispositivo cuya cabecera recibida coincida con la emitida, y los
restantes dispositivos detendrn la transmisin. ste mtodo logra establecer un sistema de
prioridad de transmisin lo cual permite un tratamiento diferenciado de los mensajes mejorando el
comportamiento en aplicaciones de tiempo real.
Para el caso particular del modem PLC existen diversos inconvenientes que dificultan o
impiden la implementacin de los mtodos anteriores. La implementacin de un mtodo basado en
el paso de testigos hara muy compleja la lgica de mantenimiento de un estructura lgica con forma
de anillo sobre una red de topologa tipo bus (similar a Token Bus). El mtodo CSMA/CD podra ser
una alternativa vlida, pero el modem PLC no puede escuchar el canal mientras transmite un
mensaje (problema que tambin presentan los dispositivos que trabajan con DC-BUS), porque
resulta muy costosa la implementacin con la tecnologa utilizada en el modem. Tampoco podra
implementarse un mtodo similar a CAN ya que no se puede definir un bit dominante, ya que el bit
dominante slo puede funcionar en esquemas de transmisin en banda base.
Entonces la alternativa surge de un mtodo empleado en redes inalmbricas y en redes
HomePlug que deriva del CSMA/CD, conocido como CSMA/CA [Stallings97], en donde si bien la
colisiones no se eliminan, se intentan evitar por el problema anteriormente expuesto para detectar
FernandoArielBeunza79156

107

Tesis de Grado en Ingeniera Informtica


las colisiones. Adems el mtodo CSMA/CA no requiere de escuchar el medio de forma simultnea
a la transmisin, sino que se transmite el mensaje y el destinatario del mismo es el encargado de
verificar si ste lleg sin errores, y en caso afirmativo le enva la confirmacin de recepcin al
transmisor. En caso de existir algn tipo de interferencia por colisin de mensajes o ruido en el
medio, el mensaje ser retransmitido luego de un tiempo de espera de duracin aleatoria (similar al
utilizado en CSMA/CD).
El mtodo CSMA/CA al igual que el CSMA/CD han sido diseados para redes de datos en
mbitos en donde las aplicaciones que hacen uso de ellas no son de tiempo real. En el caso
particular del presente trabajo se pretende poder determinar el tiempo de envo de un mensaje con
alguna certeza. Por esta razn, a lo largo de ste trabajo se irn introduciendo algunas mejoras que
apuntes a mejorar sta cuestin. Una de las mejoras que se introduce a este nivel, es la
implementacin de un sistema de prioridades para los mensajes. Dichas prioridades influyen en el
tiempo de espera entre las escuchas de canal (figura 4.12), haciendo que el nmero de prioridad sea
proporcional al tiempo de espera. Esto significa que un nmero bajo implica una espera corta y un
nmero alto una espera larga, haciendo que el nmero bajo signifique alta prioridad y un nmero
alto menos prioridad, debido a que el menor tiempo de espera implica ms oportunidades de ganar
el uso del canal para transmitir el mensaje.

Figura 4.12. Diagrama de flujo correspondiente al mtodo CSMA/CA.

108

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


El algoritmo de la figura 4.12 muestra las acciones involucradas en el envo de una trama.
Como se puede ver, cada vez que una trama no es recibida de forma correcta, sta debe
retransmitirse con un cierto costo de tiempo. Por las caractersticas del canal de comunicaciones
utilizado sto puede resultar frecuente, por lo cual no es recomendable enviar mucha informacin en
una trama, porque con slo un bit errado, se pierde toda la informacin contenida en la trama. Para
minimizar las prdidas de informacin, y disminuir el tiempo insumido por retransmisiones, se hace
necesario la implementacin de un esquema de fragmentacin a nivel de la subcapa de control de
acceso al medio.

4.2.1.3. Fragmentacin
La finalidad de implementar un esquema de fragmentacin a nivel de subcapa de control de
acceso al medio principalmente es la de hacer un uso ms eficiente de un medio en donde las tramas
enviadas con frecuencia son destruidas por cambios en el valor de algunos bits. Adems en este caso
particular, la fragmentacin se utiliza para extender la capacidad de envo de informacin con
respecto al lmite impuesto para la capa inferior.
Como ya se trat anteriormente, cuando se habl sobre el medio sobre el cual se est
trabajando, el medio es ruidoso lo que provoca, a pesar de la tcnicas de modulacin implementadas
a nivel de capa fsica, la ocurrencia de errores ocasionan la destruccin de la trama, lo que lleva a
reiteradas retransmisiones de la misma hasta que su recepcin sea correcta. Para el caso de tramas
de pocos bytes, la demora ocasionada por las sucesivas retransmisiones no resulta demasiada; lo que
no se puede decir en el caso de tratar de las tramas que ronden el tamao mximo, en el cual el
cambio de un slo valor de un bit puede destruir la trama completa de 3200 bits (tamao mximo
permitido por la capa inferior). Debido a que reiteradas transmisiones de una trama de tantos bits
puede insumir demasiado tiempo de espera, se hace necesaria la implementacin de un esquema de
fragmentacin para que toda la informacin que se enva, se haga en varias tramas, que en caso de
destruirse una de ellas, solamente sea necesaria la retransmisin de un parte de la informacin
original, demorando menos tiempo la recepcin completa del mensaje. El algoritmo de envo para
una trama corta corresponde al de la figura 4.12, mientras que para una trama larga se emplea una
variante del anterior en donde se enva previamente un pedido de envo de trama (con el tamao de
la trama a enviar), utilizando el algoritmo de la figura 4.12 y cuando se tiene la confirmacin de
recepcin, se comienzan a transmitir los sucesivos fragmentos sin esperas aleatorias de por medio.
Cada fragmento enviado debe esperar la confirmacin de recepcin para poder enviar el siguiente
fragmento. En el caso de no recibirse confirmacin, el tamao del fragmento se disminuye a la
mitad de tamao y se vuelve a intentar la transmisin del mismo, hasta alcanzar el tamao mnimo
permitido de mensaje, en cuyo caso se continua reenviando el mismo fragmento hasta agotar el
lmite de reenvos en cuyo caso el algoritmo termina devolviendo error de transmisin. En la figura
4.13 se muestra el diagrama de flujo correspondiente al algoritmo empleado para el envo de tramas
largas.

FernandoArielBeunza79156

109

Tesis de Grado en Ingeniera Informtica

Figura 4.13. Diagrama de flujo correspondiente al algoritmo de envo de tramas largas.

La fragmentacin excesiva tambin puede ser perjudicial, ya que resulta en una mayor
demora debido a que la cantidad de informacin de control de cada fragmento puede ser
significativa en comparacin a la informacin que se pretende enviar. El esquema propuesto
siempre comienza intentando enviar la mayor cantidad posible de informacin en cada trama para
minimizar la cantidad de tramas. Igualmente se establece que los fragmentos no pueden tener menor
longitud que la que posee una trama corta. Para la solucin propuesta en ste trabajo, se considera

110

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


que la longitud de una trama corta no puede superar el doble de la cantidad de bytes utilizados para
informacin de control de una trama (en este caso resulta 26 bytes * 2 = 52 bytes, ver figura 4.14).

4.2.1.4. Esquema de direccionamiento


Como se hizo mencin anteriormente, es necesario poder identificar a cada uno de los
modems PLC conectados a la red de potencia, para poder dar soporte a comunicaciones punto a
punto. Para ello no es suficiente con que modem PLC cuente con una direccin identificatoria
cualquiera, sino que sta debe ser nica, ya que si existieran dos dispositivos con la misma
direccin, establecer una comunicacin punto a punto sera imposible.
Para garantizar sto ltimo se opta por utilizar en los modems PLC un mecanismo de
direccionamiento similar al utilizado en las placas de red Ethernet que consiste en asignar a cada
dispositivo una direccin nica e irrepetible compuesta en este caso por 8 bytes (64 bits). Dicha
direccin es asignada por el fabricante y no puede ser modificada por el usuario, garantizando de
sta forma que la direccin sea nica.
De esta forma, la subcapa de control de acceso al medio puede brindar un servicio de filtrado
de tramas por direccin destinataria y un servicio de transmisin de informacin punto a punto. Pero
tambin puede requerirse otros tipos de transmisin como un broadcast, en donde un dispositivo
enve una trama de informacin a todos los dems sin necesidad de conocer todas las direcciones
destinatarias. Para ello se reserva la direccin FF:FF:FF:FF:FF:FF:FF:FF (64 bits con valor 1) para
broadcast, lo que significa que cualquier dispositivo que reciba un paquete con sta direccin
destinataria lo debe aceptar como si fuera la direccin propia del dispositivo.

4.2.1.5. Estructura de tramas


Las tramas, adems de contener la informacin a enviar, poseen cierta informacin adicional
de control necesaria para que el dispositivo destinatario pueda desarmarlos y recuperar la
informacin originalmente enviada. De los 400 bytes de capacidad mxima provistos por la capa
inferior, se destinan 374 bytes para datos y el resto para informacin de control.
No solamente deben existir paquetes que transporten informacin, sino que son necesarias
tramas dedicadas exclusivamente a enviar informacin de control para coordinacin entre el
transmisor y el receptor. Para el caso particular de la presente subcapa se requiere de una trama de
peticin de envo de trama para poder enviar informacin en varios fragmentos.
Por lo tanto, para sta subcapa se define una nica estructura de trama que permite
transportar informacin y peticin de recepcin, detallada a continuacin en la figura 4.14:
Delimitador

Direccin
de destino

Direccin
de origen

Tipo de
paquete

Protocolo

Fragmento

Tamao
de
fragmento

Tamao
total

Datos

Cdigo
detector
de errores

8 bits

64 bits

64 bits

8 bits

8 bits

8 bits

16 bits

16 bits

2992 bits

16 bits

1 byte

8 bytes

8 bytes

1 byte

1 byte

1 byte

2 byte

2 byte

374 bytes

2 bytes

Figura 4.14. Estructura de una trama.

Delimitador: secuencia de bits 01111110 utilizada para marcar el comienzo de la trama.


Dado que una secuencia de bytes recibida de la capa fsica puede corresponder a una
trama o a ruido, se requiere de una primera verificacin simple para evitar la
interpretacin de algo que puede no ser una trama vlida.

FernandoArielBeunza79156

111

Tesis de Grado en Ingeniera Informtica

Direccin de destino: direccin del modem PLC destinatario del paquete. Si la direccin
es FF:FF:FF:FF:FF:FF:FF:FF (64 bits con valor 1), por ser la direccin reservada para
broadcast, el paquete es para todos los modems PLC conectados a la red.

Direccin de origen: direccin del modem PLC que origin la trama. Esta direccin no
puede ser la de broadcast (FF:FF:FF:FF:FF:FF:FF:FF), por carecer de sentido.

Tipo de paquete: especifica el tipo de paquete que puede ser de control o de datos.

Protocolo: especifica el identificador asociado al paquete.

Fragmento: especifica el identificador de fragmento.

Tamao de fragmento: especifica el tamao del campo de datos, cuya capacidad mxima
es de 374 bytes.

Tamao total: especifica la cantidad total de bytes contenida en uno o mas fragmentos. La
cantidad mxima es de 1024 bytes.

Datos: informacin transportada. La mxima capacidad de transporte son 374 bytes.

Cdigo detector de errores: es un CRC de 16 bits calculado a partir de todos los bytes que
conforman la trama (excluyendo al cdigo detector de errores).

4.2.1.6. Control de errores


La subcapa de control de acceso al medio posee tres verificaciones para aceptar o descartar
las tramas recibidas.
El primer control es realiza con el patrn preestablecido al comienzo de la trama,
descartando cualquier tipo de trama originada por ruido en la red de potencia o interferencia. La
finalidad de ste control es ahorrar todo el costo de interpretacin de la trama, en caso de que la
trama fuera originada por ruido.
El segundo control se relaciona con el tamao de los datos que transporta la trama ya que es
necesario conocerlo para determinar en que posicin se encuentra el campo de cdigo detector de
errores. En caso de que el valor del tamao de los datos no sea vlido (mayor a 374 bytes), se
descarta la trama por entenderse de que por ruido o interferencia el tamao de los datos tom un
valor invlido, por lo cual la trama se encuentra corrompida.
La tercer, y ltima, verificacin es la ms importante ya que verifica la validez del contenido
de la trama. Excluyendo los 2 bytes finales del paquete (cdigo detector de errores), con el resto de
la trama se obtiene un cdigo CRC de 16 bits. ste cdigo debe coincidir con el CRC recibido, que
fue calculado de forma similar en el origen. En caso afirmativo se contina con el procesamiento de
la trama, caso contrario se descarta.
Si una trama ha logrado pasar con xito las verificaciones anteriormente descriptas, y la
direccin destinataria corresponde a algn modem PLC o a todos (direccin de broadcast), el o los
destinatarios de la trama emiten una respuesta confirmando la correcta recepcin. El sistema de
confirmacin de recepcin se basa en parte al utilizado en CAN y J1850, pero como no es posible
definir un valor de bit dominante, se recurre tambin a principio utilizado por DC-BUS para la
112

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


resolucin de colisin. Cuando uno o varios dispositivos emiten una confirmacin de recepcin,
generan una seal de ruido de ocupacin del canal seguido de un silencio para indicar al transmisor
de la trama, y al resto de los dispositivos conectados, que la trama ha sido correctamente recibida.
Durante el silencio mencionado, los dispositivos escuchan la actividad del canal, debido a que si
alguno de los destinatarios reporta un error de recepcin lo har ocupando el espacio de silencio, y
de esta forma el resto de los dispositivos, aunque hayan recibido correctamente la trama, la
rechazarn. Este mecanismo descripto, logra garantizar que una trama sea recibida de forma
correcta por todos los destinatarios o en su defecto por ninguno, lo que provocar sucesivas
retransmisiones de la misma hasta lograr la correcta recepcin. En caso de no existir ningn
destinatario, luego de la transmisin de la trama habr silencio en el canal, y el transmisor
interpretar este silencio tambin como un error de transmisin.
El mecanismo de confirmacin de recepcin descripto es utilizado tanto para tramas
pequeas, como para fragmentos de una trama ms grande y para la peticin de envo. La no
confirmacin de recepcin de una peticin de envo evita el costo de tiempo de enviar los sucesivos
fragmentos con los datos de la trama. Gracias a ste mecanismo se puede ofrecer un servicio de
multicast confiable a las capas superiores, de una forma menos compleja que si se lo hiciera a nivel
de las capas superiores.
La cantidad de transmisiones que han tenido una falla son contabilizadas por el modem PLC,
y la cuenta es reiniciada al detectarse una transmisin correcta de una trama (sea una trama pequea
individual o todos los fragmentos de una trama mas larga). sta cuenta es independiente a la
utilizada para reportar la falla de envo de trama, y es utilizada para desactivar el dispositivo en caso
de sobrepasar la cantidad mxima de fallas permitidas. Cuando se desactiva el modem PLC, no se
pueden ni enviar ni recibir tramas, dado que se interpreta que por alguna razn el dispositivo no
puede comunicarse con el resto, por lo cual se lo fuerza a abandonar al red. La subcapa de control
de acceso al medio se limita a detectar esta situacin de falla, desactivar el dispositivo y notificarlo
a las capas superiores, para que alguna de estas se encargue de gestionar una posible reconexin a la
red.

4.2.1.7. Filtrado de tramas


La subcapa de control de acceso al medio brinda una funcionalidad de filtrado de tramas por
medio de un identificador de protocolo. Est funcionalidad es un agregado que permite a la subcapa
de control de lgica de enlace implementar el multiplexado de protocolos y el control de flujo para
cada protocolo con el cual trabaje.
El esquema de filtrado trabaja con una tabla en donde se almacena el estado de cada
identificador de protocolo que puede ser bloqueado o no bloqueado. Cada vez que se recibe una
trama sin errores se consulta la mencionada tabla y se verifica que el protocolo asociado a la trama
recibida no se encuentre bloqueado. Si el protocolo no se encuentra bloqueado, la trama se procesa
como correcta enviando la correspondiente confirmacin de recepcin. En caso de que el protocolo
se encuentre bloqueado, a pesar de que la trama no presenta errores, se reporta recepcin errnea
como si la trama hubiera sido recibida con errores, con el mecanismo descripto con anterioridad.
El filtrado adems de asistir a la subcapa de control de lgica de enlace, permite adems la
no ocupacin de los recursos de la subcapa de control de acceso al medio en una trama que no ser
procesada por la subcapa superior.

FernandoArielBeunza79156

113

Tesis de Grado en Ingeniera Informtica

4.2.1.8. Primitivas de manejo de la subcapa de control de acceso al medio


A continuacin se detallan las primitivas referentes al manejo de la subcapa de control de
acceso al medio (cuya implementacin se detalla en el Apndice C) que proporcionan las
funcionalidades de inicializacin y liberacin de recursos, envo de mensajes y recepcin de los
mismo:

114

void mac_init(void):
Inicializa la capa fsica, el buffer de mensajes y la funcin de recepcin de mensajes.

void mac_release(void):
Libera los recursos inicializados por la primitiva anterior.

short int mac_send(mac_addr dest_addr, unsigned char prio, unsigned char prot, const
void *msg, short int msgsize):
Enva un paquete de informacin msg de longitud msgsize con prioridad prio asociado al
protocolo prot al dispositivo cuya direccin es dest_addr. Devuelve como resultado la
cantidad de bytes enviados, que coincide con msgsize si la operacin de envo pudo ser
realizada.

short int mac_receive(mac_addr addr, unsigned char *prot, void *msg, short int
msgsize):
Recibe msgsize bytes que se transfieren a msg, de un paquete asociado al protocolo prot
proveniente del dispositivo cuya direccin es addr. Cuando se recibe una trama desde la
capa fsica, se invoca la funcin dedicada a recepcin y procesamiento de tramas. Si
luego de interpretar dicha trama, sta corresponde a un paquete, ste se almacena en un
buffer. Esta primitiva transfiere msgsize bytes del contenido del buffer a msg y devuelve
la cantidad de bytes transferidos como resultado. Si el buffer se encuentra vaco, queda a
la espera de que llegu un paquete.

void mac_notify(void (*func)(mac_addr addr, unsigned char prot, void *msg, short int
msgsize)):
Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe una trama. Dicha funcin debe tener definidos como parmetros addr, prot, msg y
msgsize, que cumplen la misma funcin que en la primitiva de anterior. El objetivo de
sta primitiva es poder procesar la informacin que transporta la trama de forma
inmediata a la recepcin de la misma, sin bloquear el microcontrolador, como ocurre con
la anterior primitiva.

int mac_poll(void):
Esta primitiva verifica el estado del buffer. Devuelve como resultado uno si el buffer
contiene un paquete a la espera de ser recibido mediante la primitiva mac_receive. Si el
buffer se encuentra vaco el resultado devuelto es cero. De sta forma puede
implementarse una espera no bloqueante utilizando la primitiva mac_receive.

int mac_acceptprotocol(unsigned char prot):


Esta primitiva permite la recepcin de paquetes asociados al protocolo prot. Devuelve
como resultado uno si se pudo establecer el permiso, caso contrario el resultado devuelto
es cero.
FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

int mac_rejectprotocol(unsigned char prot):


Esta primitiva establece el rechazo de todos los paquetes asociados al protocolo prot.
Devuelve como resultado uno si se pudo establecer el rechazo, caso contrario el resultado
devuelto es cero.

int mac_status(void):
Esta primitiva verifica el estado del dispositivo. Devuelve como resultado uno si el
dispositivo se encuentra operativo. Si el dispositivo se encuentra inactivo debido a la
ocurrencia de fallas el resultado devuelto es cero.

int mac_getaddress(mac_addr addr):


Esta primitiva devuelve la direccin fsica asignada al dispositivo.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la subcapa de control de acceso al medio, en seis primitivas el envo y
recepcin (en modo bloqueante y no bloqueante) de paquetes, y en dos primitivas la obtencin de
informacin acerca del dispositivo. Los paquetes recibidos son los que tiene direccin destinataria la
del receptor o la direccin de broadcast. Adems se controla que los paquetes no contengan errores,
aunque dicho control no es infalible y requiere de otro control de errores proporcionado por la
subcapa superior de lgica de control de enlace.

4.2.2. Subcapa de control de lgica de enlace


La subcapa de control de lgica de enlace (subcapa LLC) se encarga de multiplexar diversos
protocolos sobre la subcapa de control de acceso al medio (subcapa MAC), controlar el flujo de
datos entre el transmisor y el receptor, y verificar que los mismos lleguen a destino sin errores.

4.2.2.1. Multiplexado de protocolos


Esta subcapa brinda la posibilidad de mantener mltiples conexiones en simultneo
haciendo uso de la subcapa de control de acceso al medio, que solamente provee un canal de
comunicaciones con filtrado de tramas por medio de un identificador de protocolo. La posibilidad
de mantener mltiples conexiones permite manejar diversos protocolos de comunicacin en
simultneo lo que permite un mejor aprovechamiento del canal de comunicaciones.
El estndar IEEE 802.2 [IEEE802.2] define tres tipos de conexiones posibles: no orientado a
la conexin sin confirmacin de recepcin, orientado a la conexin y no orientado a la conexin con
confirmacin de recepcin. El primer caso corresponde a un tipo de conexin en donde el envo de
un mensaje no implica la recepcin del mismo en el correspondiente destino, o bien el destino
recibe un mensaje que se almacena en su buffer, y que no es ledo por la capa superior de forma
inmediata, y a continuacin se recibe otro mensaje que es almacenado en el mismo buffer donde se
encontraba el primer mensaje, perdindose el primer mensaje recibido por no poseer ningn tipo de
control de flujo. El segundo caso corresponde a una comunicacin continua de datos (no mensajes
aislados) punto a punto, en donde un transmisor y un receptor establecen un canal de comunicacin
en donde los datos enviados por el transmisor y son recibidos por el receptor, si ste puede hacerlo;
caso contrario el receptor notificar al transmisor que detenga el flujo de datos momentneamente,
estableciendo un control de flujo de datos. Por ltimo, el tercer caso corresponde a un tipo
FernandoArielBeunza79156

115

Tesis de Grado en Ingeniera Informtica


intermedio entre no tener ningn tipo de garanta (primer caso) y tener un canal dedicado en donde
fluyen los datos (segundo caso). ste tipo de conexin se orienta a mensajes aislados, pero con
confirmacin de recepcin, estableciendo un control de flujo de los mensajes entre el transmisor y
receptor.
Para el caso particular del modem PLC solamente se implementa el tercer tipo de conexin
(no orientado a la conexin con confirmacin de recepcin), como por ejemplo lo hacen CAN y
J1850, debido a que los protocolos que se encuentran por encima de la subcapa de control de lgica
de enlace emplean mensajes individuales y requieren control de flujo para evitar congestin en el
microcontrolador destinatario de los mensajes.

4.2.2.2. Control de flujo de datos


Como se mencion anteriormente, la subcapa de control de lgica de enlace tiene la
responsabilidad de controlar el flujo de informacin entre el transmisor y el receptor para evitar
congestionar a ste ltimo.
Esta funcionalidad slo se implementa en comunicaciones orientadas a la conexin y
orientadas a mensajes individuales con confirmacin de recepcin. En ambos casos se emplea la
confirmacin de recepcin como indicador para que el transmisor enve ms datos hacia el receptor.
De esta forma, el receptor puede indicarle al transmisor que detenga el envo de datos no mandando
la confirmacin de recepcin durante un determinado tiempo, despus del cual se entiende que la
conexin se ha roto.
Los mtodos utilizados para el control de flujo son conocidos por las siglas ARQ
[Stallings97], de los cuales se distinguen tres tipos: Stop and Wait, Go-back-N y Selective Reject. El
primer tipo consiste en enviar un paquete y esperar a que el receptor enve una confirmacin de
recepcin, que en caso de que sta ltima no llegue, se puede suponer despus de un determinado
tiempo que el paquete se perdi y debe ser retransmitido. El segundo tipo consiste en enviar varios
paquetes en forma consecutiva y esperar la confirmacin de recepcin. Dicha confirmacin puede
notificar que llegaron todos los paquetes o que llegaron hasta un determinado nmero de secuencias,
a partir del cual el transmisor debe retransmitirlos. Por ltimo, el tercer tipo consiste en enviar
varios paquetes en forma consecutiva y en caso de que se pierdan algunos de stos, el receptor slo
pide la retransmisin de los paquetes perdidos.
Debido a que el modem PLC no dispone de demasiada memoria para almacenar una
secuencia de paquetes, resulta inadecuado implementar un ARQ basado en Go-back-N o Selective
Reject. Por simplicidad se implementa un Stop and Wait, ya que slo requiere tener un buffer que
pueda contener un slo paquete. El mecanismo utilizado para confirmar la recepcin del paquete en
destino es mediante la utilizacin de la funcin de filtrado de paquetes provisto por la subcapa de
control de acceso al medio. Cuando se dispone de espacio en el buffer para recibir un paquete, se
habilita la recepcin de paquetes asociados al protocolo de la conexin, lo que hace que cada vez
que la subcapa de control de acceso al medio confirme la recepcin cada vez que reciba de forma
correcta un paquete. Cuando el buffer se encuentra ocupado por un mensaje, automticamente se
bloquea la recepcin de un paquete asociado al protocolo de conexin. El bloqueo provoca que la
subcapa de control de acceso al medio no reciba paquetes asociados al protocolo bloqueado y
notifica al transmisor de que no se aceptan paquetes del protocolo en cuestin hasta que no se
desocupe el buffer, momento en el que automticamente se levanta el bloqueo.

116

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

4.2.2.3. Estructura de paquetes


Los paquetes, adems de contener la informacin a enviar, poseen cierta informacin
adicional de control necesaria para que el dispositivo destinatario pueda desarmarlos y recuperar la
informacin originalmente enviada. Debido a la limitacin de tamao impuesta por la subcapa
inmediata inferior, el tamao del paquete no puede superar los 8176 bits (o 1022 bytes), de los
cuales quedan disponibles para transporte de informacin 8192 bits (o 1024 bytes) y el resto
reservado para informacin de control (ver figura 4.15).
Datos

Cdigo detector
de errores

8176 bits

16 bits

1022 bytes

2 bytes

Figura 4.15. Estructura de un paquete.

Datos: informacin transportada. La mxima capacidad de transporte son 1022 bytes.

Cdigo detector de errores: es un cdigo CRC de 16 bits calculado a partir de todos los
bytes que conforman el paquete (excluyendo el cdigo detector de errores).

4.2.2.4. Control de errores


La subcapa de control de lgica de enlace agrega al control de errores realizado por la
subcapa de control de acceso al medio, un cdigo CRC de 16 bits. ste cdigo cumple la funcin de
verificar la correcta recepcin de toda la informacin de un paquete, ya que la verificacin que
realiza la subcapa inferior es a nivel de fragmentos de informacin, y no sobre la totalidad de la
misma. Brinda una proteccin adicional por si ocurre una falla en el esquema de reensamblaje de la
subcapa de control de acceso al medio.

4.2.2.5. Primitivas de manejo de la subcapa de control de lgica de enlace


A continuacin se detallan las primitivas referentes al manejo de la subcapa de control de
lgica de enlace (cuya implementacin se detalla en el Apndice C) que proporcionan las
funcionalidades de inicializacin y liberacin de recursos, envo de mensajes y recepcin de los
mismo:

void llc_init(void):
Inicializa la subcapa de control de acceso al medio, los buffers de mensajes y las
funciones de recepcin de mensajes.

void llc_release(void):
Libera los recursos inicializados por la primitiva anterior.

int llc_open(unsigned char prot):


Establece una conexin correspondiente al protocolo prot. Devuelve como resultado el
nmero de manejador de conexin requerido para enviar y recibir mensajes.

FernandoArielBeunza79156

117

Tesis de Grado en Ingeniera Informtica

int llc_close(int hd):


Libera la conexin asociada al manejador hd. En caso de xito devuelve como resultado
un valor positivo distinto a cero.

short int llc_send(int hd, llc_addr dest_addr, unsigned char prio, const void *msg, short
int msgsize):
Enva un paquete de informacin msg de longitud msgsize con prioridad prio al
dispositivo cuya direccin es dest_addr por medio de la conexin asociada al manejador
hd. Devuelve como resultado la cantidad de bytes enviados, que coincide con msgsize si
la operacin de envo pudo ser realizada.

short int llc_receive(int hd, llc_addr addr, void *msg, short int msgsize):
Recibe msgsize bytes que se transfieren a msg, de un paquete proveniente de la conexin
asociada al manejador hd. Cuando se recibe un paquete desde la subcapa de control de
acceso al medio, se invoca la funcin dedicada a recepcin y procesamiento de paquetes.
Si luego de interpretar dicho paquete, ste es vlido, se almacena en el buffer
correspondiente a la conexin. Esta primitiva transfiere msgsize bytes del contenido del
buffer a msg y devuelve la cantidad de bytes transferidos como resultado. Si el buffer se
encuentra vaco, queda a la espera de que llegue un paquete.

void llc_notify(int hd, void (*func)(llc_addr addr, void *msg, short int msgsize):
Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un paquete de la conexin asociada al manejador hd. Dicha funcin debe tener
definidos como parmetros addr, msg y msgsize, que cumplen la misma funcin que en la
primitiva anterior. El objetivo de sta primitiva es poder procesar la informacin que
transporta el paquete de forma inmediata a la recepcin de la misma, sin bloquear el
microcontrolador, como ocurre con la anterior primitiva.

int llc_poll(int hd):


Esta primitiva verifica el estado del buffer de la conexin asociada al manejador hd.
Devuelve como resultado uno si el buffer contiene un paquete a la espera de ser recibido
mediante la primitiva llc_receive. Si el buffer se encuentra vaco el resultado devuelto es
cero. De sta forma puede implementarse una espera no bloqueante utilizando la
primitiva llc_receive.

int llc_status(void):
Esta primitiva verifica el estado del dispositivo. Devuelve como resultado un valor
positivo distinto a cero si el dispositivo se encuentra operativo. Si la interfaz fsica se
encuentra inactivo debido a la ocurrencia de fallas el resultado devuelto es cero.

int llc_getaddress(llc_addr addr):


Esta primitiva devuelve la direccin fsica asignada al dispositivo.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la subcapa de control de lgica de enlace, en seis primitivas el envo y
recepcin (en modo bloqueante y no bloqueante) de paquetes, y en dos primitivas la consulta de
informacin sobre el dispositivo. Los paquetes recibidos son los que cuya direccin destinataria es
la del receptor. Adems se controla que los paquetes no contengan errores, con un control adicional
118

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


que complementa al control de errores realizado por la subcapa inferior de control de acceso al
medio).

4.2.3. Protocolo de resolucin de direcciones


El protocolo de resolucin de direcciones (conocido como ARP) es ajeno a las cuestiones
referente a la capa de enlace, pero se sita en esta capa para brindar soporte de resolucin de
direcciones lgicas utilizadas por la capa inmediata superior (capa de red).

4.2.3.1. Principio de funcionamiento


La necesidad de la existencia de ste protocolo radica en que es necesario tener la capacidad
de definir la direcciones de los dispositivos. Cuando se trat el tema de la subcapa de control de
acceso al medio, se hizo mencin a la necesidad de tener direcciones fsicas nicas e irrepetibles
para resolver cuestiones propias de sta subcapa. Pero a un nivel superior existen inconvenientes en
no poder definir las direcciones de los dispositivos.
Uno de los inconvenientes que presenta el esquema de direcciones fsicas es que no se
pueden conformar redes lgicas de dispositivos. Al no poderse modificar la direccin fsica, el
usuario no puede agrupar un conjunto de dispositivos para conformar una red lgica (sobre un
mismo medio fsico), ya que sto depende de poder definir un identificador de red que generalmente
se encuentra asociado a las direcciones asignadas a cada dispositivo.
Otro problema importante, que surge a partir del modelo de capas, es que los esquemas de
direccionamiento son propios de cada capa. No es conveniente trasladar un mismo esquema de
direccionamiento a lo largo de las capas, ya que un cambio en ste esquema provocara un cambio
en el resto de las capas, algo que trata de evitar el modelo de capas. Por ste motivo es importante
que la capa de enlace tenga a cargo el esquema de direccionamiento fsico, y la capa inmediata
superior (capa de red) tenga su propio esquema de direccionamiento. El mantener dos esquemas de
direccionamiento requiere de un mecanismo de traduccin, y en ste punto surge la necesidad de
disponer de un protocolo de resolucin de direcciones, encargado de realizar dicha traduccin.
El protocolo de resolucin de direcciones consiste bsicamente en mantener en cada
dispositivo fsico (en este caso modem PLC) una tabla con una serie de direcciones lgicas por cada
protocolo de red que haga uso de la capa de enlace. Dichas direcciones pueden ser creadas o
eliminadas por la capa de red independientemente de las direccin fsica preasignada al dispositivo
fsico. Cuando la capa de red necesita establecer una comunicacin con otro dispositivo, sta
solamente conoce la direccin lgica propia del protocolo de red; por lo cual requiere consultar al
resto de los dispositivos conectados para saber a cual de ellos se le ha asignado la direccin lgica
requerida. La consulta consiste en un mensaje de broadcast (ver figura 4.16) que llega en forma
simultnea a todos los dispositivos, y slo emitir una respuesta a dicha consulta el dispositivo que
contenga en su tabla de direcciones lgicas la direccin solicitada. Junto con el mensaje de
respuesta viaja la direccin fsica asociada a la direccin lgica suministrada, por lo cual el
dispositivo que realiz la consulta conoce la direccin fsica en el momento que recibe la respuesta,
y con sta direccin fsica puede establecer la comunicacin.
Para el caso particular del presente trabajo, se ha implementado una versin del protocolo de
resolucin de mensajes basada en el protocolo ARP para redes Ethernet [RFC826], que respeta los
principio fundamentales de funcionamiento, pero se la adapta a medida de los requerimientos y
disponibilidad de recursos del modem PLC.

FernandoArielBeunza79156

119

Tesis de Grado en Ingeniera Informtica

Figura 4.16. Funcionamiento del protocolo ARP.

4.2.3.2. Estructura de mensajes


Los mensajes que maneja ste protocolo pueden ser de consulta por una direccin fsica o de
respuesta a una consulta. En ambos casos el mensaje transporta el protocolo y la direccin lgica
asociada, mientras que la direccin fsica (para el caso del mensaje de respuesta) se encuentra dentro
de los campos de control de los paquetes de la subcapa de control de lgica de enlace, que es el
canal de comunicacin utilizado para la resolucin de direcciones. Dicha direccin fsica se obtiene
en el mismo momento en que se recibe el mensaje de respuesta, debido a que las primitivas de
recepcin de paquetes de la subcapa de control de lgica de enlace devuelven la direccin fsica del
dispositivo que dio origen al paquete y el contenido de dicho paquete, que en este caso es el
mensaje.
El protocolo de resolucin de direcciones define una nica estructura de mensaje que
permite consultar por una direccin y responder por dicha consulta:
Tipo de
Direccin
Protocolo
mensaje
lgica
8 bits

8 bits

32 bits

1 byte

1 byte

4 byte

Figura 4.17. Estructura de un mensaje.

Tipo de mensaje: si el valor es 01 (hexadecimal), el mensaje es de consulta por una


direccin fsica. En cambio, si el valor es 02 (hexadecimal), el mensaje es de respuesta a
una consulta.

Protocolo: identificador de protocolo correspondiente a la direccin lgica.

Direccin lgica: direccin de 32 bits destinada a protocolos de capa de red.

4.2.3.3. Primitivas de manejo del protocolo de resolucin de direcciones


A continuacin se detallan las primitivas referentes al manejo de la subcapa de control de
lgica de enlace (cuya implementacin se detalla en el Apndice C):

120

void arp_init(void):

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Inicializa los recursos referentes al manejo del protocolo de resolucin de direcciones
lgicas (tabla de direcciones lgicas, etc.).

void arp_release(void):
Libera los recursos inicializados por la primitiva anterior.

int arp_addaddress(unsigned char prot, logaddr addr):


Agrega una nueva direccin lgica addr correspondiente al protocolo de capa de red prot
a la tabla de direcciones lgicas. Si la direccin lgica pudo agregarse devuelve como
resultado un valor positivo distinto de cero.

int arp_deladdress(unsigned char prot, logaddr addr):


Elimina la direccin lgica addr correspondiente al protocolo de capa de red prot de la
tabla de direcciones lgicas. En caso de xito devuelve como resultado un valor positivo
distinto a cero.

int arp_getaddress(unsigned char prot, logaddr laddr, mac_addr *paddr):


Devuelve la direccin fsica paddr asociada a la direccin lgica laddr correspondiente al
protocolo de capa de red prot. Esta primitiva es la encargada de consultar al resto de los
modems PLC para averiguar cual de ellos tiene en su tabla de direcciones lgicas la
direccin solicitada. El modem PLC que contenga dicha direccin le responder al
modem que realiz la consulta con su direccin fsica. En caso de xito devuelve como
resultado un valor positivo distinto a cero.

4.2.4. Primitivas de manejo de la capa de enlace


A continuacin se detallan las primitivas referentes al manejo de la capa de enlace. Dichas
primitivas brindan una interfaz que encapsulan hacia la capa superior (capa de red) las primitivas de
control de lgica de enlace y del protocolo de resolucin de direcciones (cuyas implementaciones se
detalla en el Apndice C):

void dl_init(unsigned char iface):


Inicializa la subcapa de control de lgica de enlace y el protocolo de resolucin de
direcciones lgicas asociados a la interfaz fsica iface.

void dl_release(unsigned char iface):


Libera los recursos inicializados por la primitiva anterior asociados a la interfaz fsica
iface.

int dl_open(unsigned char iface , unsigned char prot):


Establece una conexin correspondiente a la interfaz fsica iface y al protocolo prot.
Devuelve como resultado el nmero de manejador de conexin requerido para enviar y
recibir mensajes.

int dl_close(int hd):


Libera la conexin asociada al manejador hd. En caso de xito devuelve como resultado
un valor positivo distinto a cero.

FernandoArielBeunza79156

121

Tesis de Grado en Ingeniera Informtica

122

short int dl_send(int hd, llc_addr dest_addr, unsigned char prio, const void *msg, short
int msgsize ):
Enva un paquete de informacin msg de longitud msgsize con prioridad prio al
dispositivo cuya direccin es dest_addr por medio de la conexin asociada al manejador
hd. Devuelve como resultado la cantidad de bytes enviados, que coincide con msgsize si
la operacin de envo pudo ser realizada.

short int_t dl_receive(int hd, llc_addr addr, void *msg, short int msgsize):
Recibe msgsize bytes que se transfieren a msg, de un paquete proveniente de la conexin
asociada al manejador hd. Si el buffer se encuentra vaco, queda a la espera de que llegu
un paquete.

void dl_notify(int hd, void (*func)(llc_addr addr, void *msg, short int msgsize):
Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un paquete de la conexin asociada al manejador hd. Dicha funcin debe tener
definidos como parmetros addr, msg y msgsize, que cumplen la misma funcin que en la
primitiva de anterior. El objetivo de sta primitiva es poder procesar la informacin que
transporta el paquete de forma inmediata a la recepcin de la misma, sin bloquear el
microcontrolador, como ocurre con la anterior primitiva.

int dl_poll(int hd):


Esta primitiva verifica el estado del buffer de la conexin asociada al manejador hd.
Devuelve como resultado uno si el buffer contiene un paquete a la espera de ser recibido
mediante la primitiva dl_receive. Si el buffer se encuentra vaco el resultado devuelto es
cero. De sta forma puede implementarse una espera no bloqueante utilizando la
primitiva dl_receive.

int dl_getaddress(unsigned char iface, dl_addr addr):


Devuelve la direccin fsica addr asociada a la interfaz fsica iface. En caso de xito
devuelve como resultado un valor positivo distinto a cero.

int dl_addlogaddress(unsigned char iface, unsigned char prot, logaddr addr):


Agrega una nueva direccin lgica addr correspondiente al protocolo de capa de red prot
a la tabla de direcciones lgicas asociada a la interfaz fsica iface. Si la direccin lgica
pudo agregarse devuelve como resultado un valor positivo distinto de cero.

int dl_dellogaddress(unsigned char iface, unsigned char prot, logaddr addr):


Elimina la direccin lgica addr correspondiente al protocolo de capa de red prot de la
tabla de direcciones lgicas asociada a la interfaz fsica iface. En caso de xito devuelve
como resultado un valor positivo distinto a cero.

int dl_getphyaddress(unsigned char iface, unsigned char prot, logaddr laddr, llc_addr
paddr):
Devuelve la direccin fsica paddr de la interfaz fsica iface asociada a la direccin lgica
laddr correspondiente al protocolo de capa de red prot. En caso de xito devuelve como
resultado un valor positivo distinto a cero.

int dl_status(unsigned char iface):

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Esta primitiva verifica el estado de la interfaz fsica iface. Devuelve como resultado un
valor positivo distinto a cero si el dispositivo se encuentra operativo. Si la interfaz fsica
se encuentra inactivo debido a la ocurrencia de fallas el resultado devuelto es cero.

short int dl_getpayloadsize(unsigned char iface):


Esta primitiva devuelve la cantidad mxima de bytes que puede contener un paquete.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la cada de enlace, en seis primitivas el envo y recepcin (en modo
bloqueante y no bloqueante) de paquetes, en cuatro primitivas el manejo de direcciones lgicas y
fsicas, y en dos primitivas adicionales la consulta de informacin sobre las interfaces fsicas.

4.3. Capa de red


La capa de enlace es responsable del transporte de la informacin a travs de un medio fsico
comn, libre de errores y con control de flujo entre el transmisor y el receptor. Pero es necesario
tener la capacidad de poder crear redes lgicas a partir de redes fsicas, y que todos los nodos
integrantes de una red lgica se puedan comunicar entre s independientemente de la red fsica a la
que se encuentren conectados.

4.3.1. Modelo de comunicaciones


Existen dos formas de comunicacin posible: las comunicaciones orientadas a la conexin y
las no orientados a la conexin.
La primer forma de comunicacin consiste en que tanto el transmisor como el receptor se
sincronicen en un determinado instante, por medio de un protocolo de intercambio de mensajes,
para establecer un canal de comunicaciones donde la informacin fluya libremente de un extremo a
otro y dicho flujo finalice cuando alguno o los dos extremos cierren el canal. Este mecanismos es
semejante a la comunicaciones por medio de la red telefnica donde una persona llama a otra y la
comunicacin se establece cuando sta ltima atiende, intercambian informacin durante un tiempo,
y la comunicacin finaliza cuando la persona que origin la comunicacin cuelga su telfono. La
ventaja de ste modelo es que se puede implementar un canal de comunicaciones confiable (donde
no se pierda informacin) de forma relativamente simple entre dos dispositivos.
En la segunda forma de comunicacin el transmisor y el receptor actan de forma
asincrnica, ya que el primero enva un mensaje y despus de un tiempo lo recibe el receptor. En
ste caso no se establece un canal de comunicacin como en la forma anterior y la informacin no
fluye libremente sino que se reduce a un mensaje individual. Un ejemplo tpico de esta forma de
comunicacin es el correo en el cual una persona escribe su mensaje en una carta, sta va al correo y
el correo se encarga de llevarla hasta la persona destinataria. Como se puede observar no se
establece una comunicacin punto a punto como con un comunicacin orientada a la conexin y no
resulta confiable porque al no estar sincronizados el transmisor y el receptor, ste ltimo no puede
confirmarle la llegada del mensaje al transmisor. Pero a pesar de stos inconvenientes, es una forma
de comunicacin ms simple de implementar que la primera y no est limitada a solamente dos
dispositivos pudiendo implementar mensajes de difusin.
Las redes se orientan por alguno de los dos modelos de comunicaciones anteriores, por
ejemplo la red telefnica es orientada a la conexin y el correo es no orientado a la conexin. En el
FernandoArielBeunza79156

123

Tesis de Grado en Ingeniera Informtica


caso particular del presente trabajo se busca simpleza y capacidad de difusin, lo que orienta la
eleccin hacia el modelo no orientado a la conexin. Emplear ste modelo de comunicacin implica
que debe buscarse un mecanismo adicional para garantizar la confiabilidad. Por ejemplo, las redes
IP [Stallings97], son redes que hacen su mejor esfuerzo para que los mensajes lleguen a destino,
pero no brindan garanta de sto ltimo, delegando la confiabilidad al protocolo de transporte TCP
[Stallings97]. Un esquema similar presenta LonWorks, en donde la confiabilidad tambin se
traslada a la capa de transporte. En las redes utilizadas en automviles, las comunicaciones tambin
son no orientadas a la conexin, pero a diferencia del modelo IP, no delegan el problema de la
confiabilidad a capas superiores, ya que no implementan todas las capas del modelo OSI, tendiendo
a resolver ste problema a nivel de capa de enlace. Las redes CAN y J1850 implementan un sistema
de confirmacin de recepcin para mensajes de difusin (multicast y broadcast). Las redes D2B y
MOST se basan en una topologa anillo que permite confirmar la recepcin de los mensajes.
En el caso particular del presente trabajo, se sigue el modelo de capas como lo hace el
modelo IP y LonWorks, pero tambin se busca la simpleza y capacidad de difusin de una
comunicacin no orientada a la conexin, con el agregado de confiabilidad, siguiendo tambin las
ideas de las redes de automviles. Como ya se mencion con anterioridad, la capa de enlace
propuesta permite garantizar que mensajes de difusin tengan confirmacin de recepcin (igual que
CAN y J1850), no trasladando el problema a las capas superiores, para simplificar la
implementacin de stas ltimas.

4.3.2. Esquema de direccionamiento


Debido a que el objetivo de la capa de red es poder crear redes lgicas sobre una o varias
redes fsicas, y que dichas redes lgicas sean independientes de las caractersticas de la red fsica,
uno de los puntos para lograr dicha independencia es implementar un esquema de direccionamiento
independiente al provisto por la red fsica (capa de enlace).
Cualquier esquema de direccionamiento debe aprovechar las funcionalidades del protocolo
de resolucin de direcciones (ARP), provisto por la capa de enlace, que permite trabajar con un
esquema de direcciones de 32 bits de longitud. sto resulta suficiente para poder individualizar a
cada nodo de la red lgica, pudiendo cada nodo tener una o varias direcciones lgicas. Se reserva la
direccin cero para indicar que el destinatario del mensaje son todos los nodos de la red (direccin
de broadcast).
Adems del esquema de direccionamiento lgico, se provee otro esquema basado en el
identificador de mensaje similar al sistema empleado por las redes CAN y J1850 (modo de
direccionamiento funcional). ste esquema consiste en tener una tabla de filtrado de mensajes en
cada nodo, en donde se almacena una lista de los identificadores de mensajes que el nodo tiene
inters en recibir, ignorando los mensajes que contengan un identificador no presente en su lista de
identificadores.
De este modo se tienen dos sistemas de direccionamiento, similar al esquema propuesto por
J1850 (modo de direccionamiento fsico y modo de direccionamiento funcional); uno para
identificar un nodo en particular y otro para identificar una funcionalidad en particular que puede
llevarse a cabo por uno o varios nodos. Se pueden utilizar cualquiera de los sistemas en forma
separada o en forma conjunta. Si se trabaja utilizando solamente la direccin de broadcast y el
direccionamiento por identificador de mensaje se tiene un sistema de direccionamiento similar al
propuesto por CAN y J1850 (modo de direccionamiento funcional). ste modo de trabajo
mencionado permite implementar un esquema de grupos de difusin que ms adelante se
desarrollar en profundidad.

124

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 4.18. Ejemplo de direccionamiento por identificador de mensaje.

En la figura 4.18 se puede observar un ejemplo del funcionamiento del esquema de


direccionamiento por identificador de mensaje y utilizando como identificador de nodo el
identificador destinado para mensajes de broadcast. Existen tres dispositivos, uno es el tablero que
enva rdenes a las luces delanteras y traseras de encenderse o apagarse por medio de un mensaje
cuyo identificador es 01, y cada una de stas puede reportar algo al tablero por medio de un mensaje
cuyo identificador es 02 (para las luces delanteras) o 03 (para las luces traseras). El tablero no
conoce como se encuentran conectados fsicamente los otros dispositivos, slo sabe que enviando
un mensaje con identificador 01 se encendern o apagarn las luces y que las luces podrn reportar
al tablero alguna falla, por ejemplo, enviando mensajes con identificadores 02 y 03. El tablero no
necesita saber como se conforman las redes fsicas, slo enva y recibe mensajes; dejando a la capa
de red el trabajo de encaminar cada mensaje para que llegue a su destinatario. Si por algn motivo el
tablero quisiera enviar un mensaje especfico para las luces delanteras, y no las traseras, podra
realizarse utilizando el identificador de nodo asignado a las luces delanteras, o bien si no se desea
trabajar con identificadores de nodo reservar un identificador de mensaje destinado solamente a las
luces delanteras.
Como se puede observar en el ejemplo anterior, el esquema de direccionamiento es lo
suficientemente flexible para poder implementar en capas superiores un sistema de mensajera por
medio de canales de difusin, asociando a cada identificador de mensaje a un grupo de difusin
especfico.

4.3.3. Estructura de mensajes


Los mensajes, adems de contener porciones del mensaje a enviar, poseen cierta informacin
adicional de control necesaria para que el dispositivo destinatario pueda desarmarlos y recuperar la
informacin originalmente enviada. La informacin de control ocupa 5 bytes dejando el resto
reservado para el campo de datos, cuyo tamao mximo depende de la interfaces fsicas a las cuales
se encuentre conectado el nodo. Si slo se encuentra conectado a una sola interfaz, sta interfaz
determinar la cantidad de informacin que se puede enviar. En caso de ser varias las interfaces,
ser la de menor capacidad la que determinar la cantidad de informacin que se puede enviar.

FernandoArielBeunza79156

125

Tesis de Grado en Ingeniera Informtica

Versin

Identificador
Protocolo Tamao
de mensaje

Datos

8 bits

8 bits

8 bits

16 bits

(capacidad mxima de
capa de enlace - 40) bits

1 byte

1 byte

1 byte

2 bytes

(capacidad mxima de
capa de enlace - 5) bytes

Figura 4.19. Estructura de un mensaje.

Versin: identificador de versin del protocolo de red.

Identificador de mensaje: identificador de mensaje asociado al contenido del campo de


datos.

Protocolo: identificador de protocolo asociado al contenido del campo de datos.

Tamao total: especifica el tamao del mensaje. El mximo tamao depende de la


capacidad mxima que provea la capa de enlace.

Datos: informacin transportada.

4.3.4. Primitivas de manejo de la capa de red


A continuacin se detallan las primitivas referentes al manejo de la capa de red (cuya
implementacin se detalla en el Apndice C) que proporcionan las funcionalidades de inicializacin
y liberacin de recursos, envo de mensajes y recepcin de los mismos y manejo de la tabla de
encaminado de mensajes:

126

void net_init(void):
Inicializa la capa de red, las interfaces fsicas, el buffer de mensajes y la funcin de
recepcin de mensajes.

void net_release(void):
Libera los recursos inicializados por la primitiva anterior.

short int net_send(net_nodeid nodeid, net_msgid msgid, unsigned char prio, unsigned
char prot, const void *msg, short int msgsize):
Enva un mensaje msg de longitud msgsize, cuyo identificador es msgid, con prioridad de
envo prio, por medio de la red al nodo cuyo identificador es nodeid. Adems el mensaje
enviado corresponde a un protocolo de capa superior que puede ser especificado por
medio del parmetro prot. Si el identificador de nodo nodeid tiene valor cero, el mensaje
es enviado a todos los nodos de todas las redes a las que se tiene acceso. Devuelve como
resultado la cantidad de bytes enviados, que coincide con msgsize si la operacin de envo
pudo ser realizada.

short int net_receive(net_msgid *msgid, unsigned char *prot, void *msg, short int
msgsize):

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Recibe msgsize bytes que se transfieren a msg, de un mensaje recibido a travs de la red
cuyo identificador es msgid. Cuando se recibe un mensaje por medio de la capa de enlace,
se invoca la funcin dedicada a recepcin y procesamiento de paquetes. Si luego de
interpretar un paquete recibido, ste resulta vlido, se almacena el mensaje recibido en el
buffer de la capa de red. El mensaje recibido tiene asociado un protocolo de la capa
superior devuelto a travs de prot. Esta primitiva transfiere msgsize bytes del contenido
del buffer a msg y devuelve la cantidad de bytes transferidos como resultado. Si el buffer
se encuentra vaco, queda a la espera de que algn mensaje.

void net_notify(void (*func)(net_msgid msgid, unsigned char prot, void *msg, short int
msgsize)):
Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un mensaje a travs de la red. Dicha funcin debe tener definidos como parmetros
prot, msg y msgsize, que cumplen la misma funcin que en la primitiva de anterior. El
objetivo de sta primitiva es poder procesar la informacin que transporta el mensaje de
forma inmediata a la recepcin del mismo, sin bloquear el microcontrolador, como ocurre
con la anterior primitiva.

int net_poll(void):
Esta primitiva verifica el estado del buffer. Devuelve como resultado uno si el buffer
contiene un mensaje a la espera de ser recibido mediante la primitiva net_receive. Si el
buffer se encuentra vaco el resultado devuelto es cero. De sta forma puede
implementarse una espera no bloqueante utilizando la primitiva net_receive.

int net_addaddr(net_nodeid nodeid):


Esta primitiva permite agregar un nuevo identificador de nodo nodeid. Si el identificador
de nodo pudo agregarse devuelve como resultado un valor positivo distinto de cero, caso
contrario devuelve cero.

int net_deladdr(net_nodeid nodeid):


Esta primitiva permite eliminar un identificador de nodo nodeid ya existente. Devuelve
como resultado un valor distinto de cero si la operacin pudo ejecutarse con xito, caso
contrario devuelve valor cero si la eliminacin no pudo ser concretada.

int net_addmsgid(net_msgid msgid):


Esta primitiva permite agregar un nuevo identificador de mensaje msgid en la tabla de
filtrado de mensajes. Si el identificador de mensaje pudo ser agregado a la tabla de
filtrado devuelve como resultado un valor positivo distinto de cero, caso contrario
devuelve cero.

int net_delmsgid(net_msgid msgid):


Esta primitiva permite eliminar un identificador de mensaje msgid ya existente en la tabla
de filtrado de mensajes. Devuelve como resultado un valor distinto de cero si la operacin
pudo ejecutarse con xito, caso contrario devuelve valor cero si la eliminacin no pudo
ser concretada.

int net_status(void):
Esta primitiva verifica si el nodo posee alguna interfaz fsica activa por la cual pueda
comunicarse con otros nodos. Devuelve como resultado un valor positivo distinto a cero

FernandoArielBeunza79156

127

Tesis de Grado en Ingeniera Informtica


si el nodo se encuentra operativo. Si no hay ninguna interfaz fsica activa el resultado
devuelto es cero.

short int net_getpayloadsize(void):


Esta primitiva devuelve la cantidad mxima de bytes que puede contener un mensaje para
poder ser enviado por cualquiera de las interfaces fsicas a las cuales se encuentra
conectado el nodo.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la capa de red, en cuatro primitivas en el envo y recepcin (en modo
bloqueante y no bloqueante) de mensajes, y finalmente, mediante seis primitivas especiales, se
permite la configuracin del nodo y obtener informacin sobre el mismo.

4.4. Capa de transporte


La capa de transporte es responsable de que la informacin transportada por medio de la
capa de red llegue de forma confiable a todos los destinos en un mismo orden. En caso de que lo
anterior no se logre, sta capa debe detectarlo para notificarle a la capa de sesin (capa superior)
para que pueda arbitrar los medios para resolver esta situacin.

4.4.1. Comunicacin por grupos de difusin


Existen diversas formas de establecer una comunicacin entre varios dispositivos presentes
en una red, y una de las ms simples de ver es por medio de un protocolo punto a punto. sto
consiste en tener identificados a todos los dispositivos unvocamente y asociarles a cada uno de
stos una o varias funcionalidades en particular, entonces cuando un dispositivo requiera de la
funcionalidad que provee otro, el primero le enva un mensaje al segundo solicitando el
requerimiento. Un ejemplo de ste caso podra ser el sistema de iluminacin exterior de un
automvil en donde el dispositivo que genera el requerimiento es el mando de encendido de los
faros exteriores y el dispositivo que lleva a cabo la accin son los faros, entonces cuando el usuario
acciona el encendido de las luces, el dispositivo genera un mensaje hacia cada faro exterior para que
se activen. Los inconvenientes presentes en un protocolo punto a punto es que el desarrollador del
dispositivo que acciona la iluminacin debe conocer la direccin de cada faro exterior para enviar a
cada uno de ellos la orden de encendido o apagado. sto no brinda posibilidad de agregar nuevo
dispositivos, porque si el desarrollador del dispositivo que acciona la iluminacin no prevee el
agregado de nuevos dispositivos de iluminacin, y stos ltimo, por ms que se encuentren
instalados, al no recibir el mensaje de encendido no realizarn accin alguna. sto podra superarse
si se trabajar con un esquema de mensajes de difusin como los utilizados por CAN y J1850.

128

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 4.20. Ejemplo de comunicacin punto a punto.

La propuesta de este trabajo es tomar las ideas de CAN y J1850, e implementar un esquema
de difusin. Dicho esquema responde al modelo de comunicaciones orientado a grupos. En este
modelo los dispositivos conforman grupos de difusin, volviendo al ejemplo anterior, se podra
definir un grupo referente al sistema de iluminacin exterior y los participantes o miembros seran el
mando de accionamiento y los faros exteriores. El mensaje con la orden de encendido o apagado de
los faros es nico con garanta de que la orden le llegue a todos los destinatarios o caso contrario a
ninguno. Esto ltimo es lo que se conoce como difusin confiable (o reliable multicast). LonWorks
tambin implementa un esquema de difusin con confirmacin, pero a diferencia de CAN y J1850,
la confirmacin de recepcin est dada por el primer destinatario que confirme la recepcin, lo cual
no permite garantizar que todos los dispositivos recibieron el mensaje. El modelo de comunicacin
orientado a grupos involucra varios temas adems de la difusin confiable, como la gestin de los
miembros de grupo y ordenamiento de los mensajes.

Figura 4.21. Ejemplo de comunicacin por difusin.

Evidentemente una comunicacin orientada a grupos resulta mucho ms compleja que la


punto a punto, por lo cual todas las problemticas planteadas no se pueden resolver en una sola
capa. Por este motivo desde las primeras capas se viene introduciendo mejoras a fin de poder
implementar el modelo de comunicacin mencionado de forma eficiente. La mejoras comienzan en
la capa de enlace cuando se implementa un mecanismo de confirmacin de recepcin para mensajes
de broadcast, luego en la capa de red donde se plantea un esquema de direccionamiento que permite
la introduccin de un esquema de grupos de difusin a partir de la capa de transporte.
La capa de transporte, adems de introducir por primera vez el concepto de grupos de
difusin, se encarga de garantizar la llegada de todos los mensajes que se difundan por un grupo,
como as tambin el orden de llegada. En caso de que por una falla, se pierdan las anteriores
condiciones, la capa de transporte desactiva el dispositivo y notifica de la situacin a la capa de
sesin, encargada de gestionar una posible reconexin del dispositivo.
Los grupos de difusin se conforman de un dispositivo propietario del grupo encargado de
difundir mensajes por medio del grupo y de un o varios dispositivos miembros del grupo,
destinatarios de los mensajes. Este esquema de comunicacin se implementa utilizando la difusin
de mensajes provista por la capa de red sumada al esquema de filtrado de mensajes, tambin
provisto por la capa de red.

FernandoArielBeunza79156

129

Tesis de Grado en Ingeniera Informtica

4.4.2. Esquema de identificacin


La capa de transporte debe proveer un esquema de identificacin que sea independiente del
esquema de direccionamiento que utiliza la capa inferior (capa de red) para poder ser portable a
otras implementaciones de redes.
El esquema de identificacin no se basa en identificar a cada uno de los dispositivos, sino
que a identificar los canales de comunicacin utilizados para difundir los mensajes. Cada canal de
comunicacin se denomina grupo de difusin, y se encuentra conformado por un dispositivo
propietario y mltiples dispositivos miembros del grupo. El propietario de un grupo de difusin es
el nico dispositivo que puede enviar mensajes, que el resto de los miembros recibe y procesa.
Cada grupo de difusin puede verse como una estructura maestro/esclavo, el sentido de las
comunicaciones es solamente desde el maestro o propietario hacia los esclavos o miembros. La
diferencia con la estructura tradicional maestro/esclavo, es que pueden existir mltiples grupos de
difusin, sobre una misma red fsica, lo cual permitira comunicaciones bidireccionales. Por
ejemplo, se tiene un dispositivo, que puede ser el tablero de instrumentos que tiene la funcin de
reportar el estado del vehculo, y junto a l diversos mandos como, por ejemplo, el encendido de
luces. Puede existir un grupo de difusin asociado a las luces en donde el tablero es el propietario y
las luces miembros de ese grupo, y el tablero enva mensajes de encendido y apagado hacia las
luces. Adems, cada luz puede tener asociado un grupo de difusin en donde es propietario, y el
tablero es miembro de cada uno de los grupos de difusin de cada luz, para conocer el estado de las
mismas, por medio de mensajes que enva cada una de las luces hacia el tablero. As como este
ejemplo, se pueden pensar otros mucho ms complejos donde intervengan ms dispositivos.
La cantidad de grupos de difusin que pueden existir se limitan a 255, cada grupo debe
poseer un propietario del mismo, y no existe lmites de dispositivos que pueden ser miembro del
grupo. Cada dispositivo puede ser propietario de uno o varios grupos de difusin, o bien no ser
propietario de ninguno; sto viene dado a la informacin que desee compartir el dispositivo con el
resto de los dispositivos de la red. El lmite de dispositivos est dado por lmites fsicos de las redes,
no por el esquema de identificacin propuesto.

4.4.3. Mensajes
La capa de transporte presenta dos tipos de mensajes: en secuencia y fuera de secuencia. Los
primeros se tratan de mensajes enviados con baja prioridad, que obligatoriamente deben ser
recibidos por todos los dispositivos miembros de un grupo de difusin, cumpliendo de esta forma
con las condiciones exigidas por un esquema de comunicacin de difusin confiable. Este tipo de
mensaje sacrifica velocidad por confiabilidad de recepcin, y pueden ser utilizados, por ejemplo,
para enviar informacin de configuracin de dispositivos. El otro tipo de mensajes son los que se
enva fuera de secuencia, en donde la capa de transporte hace su mejor esfuerzo para cumplir las
exigencias de una comunicacin por difusin confiable, pero no brinda garanta. Este tipo de
mensaje se enva con alta prioridad a diferencia de los del primer tipo, y su aplicacin est destinada
para enviar rdenes a dispositivos, en donde es ms importante recibir el mensaje en el tiempo
correspondiente, o en su defecto no recibirlo; que recibirlo fuera de tiempo.
Ambos tipos de mensaje emplean una nica estructura de mensaje como la descripta en la
figura 4.22.

130

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Versin Secuencia

Datos

8 bits

8 bits

(capacidad mxima de capa de red - 16) bits

1 byte

1 byte

(capacidad mxima de capa de red - 2) bytes

Figura 4.22. Estructura de un mensaje.

Versin: identificador de versin del protocolo de transporte.

Secuencia: especifica el nmero de secuencia del mensaje. El nmero de secuencia -1


indica que el mensaje se encuentra fuera de secuencia.

Datos: informacin transportada por el mensaje. La mxima capacidad de transporte


depende la capacidad que brinda la capa de red.

4.4.4. Primitivas de manejo de la capa de transporte


A continuacin se detallan las primitivas referentes al manejo de la capa de transporte (cuya
implementacin se detalla en el Apndice C) que proporcionan las funcionalidades de inicializacin
y liberacin de recursos, envo de mensajes y recepcin de los mismos:

void tp_init(void):
Inicializa la capa de transporte, los buffers de mensajes y la funcin de recepcin de
mensajes. Tambin establece el identificador de dispositivo dev.

void tp_release(void):
Libera los recursos inicializados por la primitiva anterior.

short int tp_send(tp_grpid grpid, unsigned char nosec, const void *msg, short int
msgsize):
Enva un mensaje msg de longitud msgsize por el grupo de difusin grpid. Por medio de
la activacin del indicador nosec, el mensaje puede excluirse de la secuencia de mensajes
enviados, lo que significa que ante una eventual resincronizacin del modem PLC, el
mensaje no ser recuperado. Devuelve como resultado la cantidad de bytes enviados, que
coincide con msgsize si la operacin de envo pudo ser realizada.

short int tp_receive(tp_grpid *grpid, void *msg, short int msgsize):


Recibe msgsize bytes que se transfieren a msg, de un mensaje recibido a travs del grupo
de difusin grpid. Cuando se recibe un mensaje de la capa de red, se invoca la funcin
dedicada a recepcin y procesamiento de mensajes. Si luego de interpretar el mensaje,
ste resulta vlido, se almacena en el buffer de la capa de transporte. Esta primitiva
transfiere msgsize bytes del contenido del buffer a msg y devuelve la cantidad de bytes
transferidos como resultado. Si el buffer se encuentra vaco, queda a la espera de que
llegue un mensaje.

void tp_notify(void (*func)(tp_grpid grpid, void *msg, short int msgsize)):


Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un mensaje. Dicha funcin debe tener definidos como parmetros grpid, msg y

FernandoArielBeunza79156

131

Tesis de Grado en Ingeniera Informtica


msgsize, que cumplen la misma funcin que en la primitiva de anterior. El objetivo de
sta primitiva es poder procesar la informacin que transporta el mensaje de forma
inmediata a la recepcin del mismo, sin bloquear el microcontrolador, como ocurre con la
anterior primitiva.

int tp_poll(void):
Esta primitiva verifica el estado del buffer de la capa de transporte. Devuelve como
resultado uno si el buffer contiene un mensaje a la espera de ser recibido mediante la
primitiva tp_receive. Si el buffer se encuentra vaco el resultado devuelto es cero. De sta
forma puede implementarse una espera no bloqueante utilizando la primitiva tp_receive.

int tp_setownergrp(tp_grpid grpid):


Establece que el modem PLC es propietario de un grupo de difusin grpid lo que le
permite enviar mensajes por medio del grupo que posee. Devuelve como resultado un
valor positivo distinto de cero si se pudo establecer la propiedad del grupo de difusin,
caso contrario devuelve como resultado cero.

int tp_setmembergrp(tp_grpid grpid):


Establece que el modem PLC es miembro de un grupo de difusin grpid lo que le permite
recibir mensajes por medio del grupo del cual es miembro. Devuelve como resultado un
valor positivo distinto de cero en caso de xito, caso contrario devuelve como resultado
cero.

int tp_leavegrp(tp_grpid grpid):


Desvincula el modem PLC del grupo de difusin grpid, independientemente de que sea
propietario o miembro. En caso de xito devuelve como resultado un valor positivo
distinto a cero.

int tp_status(void):
Esta primitiva verifica si la conexin se encuentra activa o no. Devuelve como resultado
un valor positivo distinto a cero si el nodo se encuentra operativo. Si no hay ninguna
interfaz fsica activa el resultado devuelto es cero.

short int tp_getpayloadsize(void):


Esta primitiva devuelve la cantidad mxima de bytes que puede contener un mensaje.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la capa de transporte, en cuatro primitivas la apertura, cierre y deteccin
de cambios de estado de la conexin, y en cinco primitivas el envo y recepcin (en modo
bloqueante y no bloqueante) de mensajes.

4.5. Capa de sesin


La capa de sesin es responsable de proveer los mecanismos de establecimiento y
finalizacin de sesiones entre diferentes aplicaciones usuarias. Adems debe controlar el dilogo
entre el dispositivo transmisor y receptor, y sincronizar la informacin recibida por todos los
dispositivos. La capa de transporte provee a la capa de sesin un medio confiable de transmisin de

132

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


la informacin durante la existencia de una conexin entre transmisor y receptor, que puede
perderse por diversas situaciones. La capa de sesin es la encargada de brindar a las capas
superiores un servicio de conexin entre dispositivos que gestione de forma automtica las
reconexiones, en caso de que la capa de transporte notifique una prdida de conexin, y que la
informacin enviada por un dispositivo hacia varios destinatarios sea la misma (si un dispositivo
enva varios mensajes, los destinatarios deben recibirlos todos y en el mismo orden).

4.5.1. Establecimiento de sesiones


Bajo el esquema de grupo de difusin de la capa de transporte existe la garanta de que todos
los miembros de un grupo reciben los mismos mensajes en el mismo orden, y cuando un miembro
falla en la recepcin se considera que ha abandonado el grupo, conformndose un nuevo grupo con
otros miembros (los mismos que el anterior grupo menos el que ha fallado). Lo mismo ocurre
cuando ingresa un nuevo miembro al grupo, se conforma un grupo compuesto por los miembros
anteriores ms el nuevo miembro. En la capa de transporte no existe el concepto de sesin, sino que
la comunicaciones entre dispositivos se dan por medio de grupos aislados de se conforman y
disuelven en el transcurso a lo largo del tiempo.
La capa de sesin introduce el concepto de sesin que se compone de una sucesin de
grupos que integra un dispositivo. Cuando un dispositivo establece una sesin pasa a formar parte
de un grupo determinado que finaliza su vida cuando cambia su composicin de miembros.
Ocurrido sto ltimo, se forma un nuevo grupo al cual pertenecer automticamente el dispositivo,
y sto ltimo seguir ocurriendo hasta que el dispositivo finalice la sesin. La finalizacin de la
sesin implica la conformacin de un nuevo grupo sin el dispositivo que ha cerrado su sesin. Cada
uno de stos grupos se denominan vistas [VerssimoRodrigues01], y en la capa de sesin, los
grupos de difusin se conforman a partir de una sucesin de vistas.

Figura 4.23. Ejemplo de vistas [VerssimoRodrigues01].

Un dispositivo que ha iniciado una sesin puede fallar y encontrarse incomunicado en un


determinado instante, lo que provoca la finalizacin de una vista y la creacin de otra sin el
dispositivo en cuestin hasta que vuelva a reintegrarse conformndose nuevamente otra vista
idntica a la inicial. sta situacin no se notificar a las capas superiores siempre y cuando la
secuencia de los mensajes se mantenga (no se pierdan mensajes en secuencia). Los mensajes fuera
de secuencia no son tenidos en cuenta, porque el inters en ellos slo se da en un instante
determinado. En caso de haber prdidas de mensajes en secuencia, la sesin finaliza de forma
forzada, debiendo la capa superior gestionar una nueva sesin como si el dispositivo ingresara por
primera vez.

FernandoArielBeunza79156

133

Tesis de Grado en Ingeniera Informtica

4.5.2. Control del dilogo


La capa de sesin slo permite el flujo de informacin en un slo sentido: el publicador
enva un mensaje hacia los suscriptores adheridos al grupo de difusin cuyo propietario es el
publicador. ste tipo de comunicacin se denomina half duplex, y si es requiere de un flujo de
informacin en ambos sentidos (full duplex), debe existir otro grupo de difusin que funcione en
sentido inverso: el suscriptor debe pertenecer a un grupo de difusin en donde sea publicador, en el
cual el publicador original sea suscriptor de ste ltimo grupo. De ste modo un dispositivo puede
enviar una orden por medio de un mensaje, y el dispositivo destinatario de la orden puede responder
a la misma; o el dispositivo destinatario para no estar esperando alguna instruccin, puede
solicitarle al dispositivo origen que le de instrucciones para llevar a cabo alguna accin.

Figura 4.24. Ejemplo de dilogo entre dispositivos.

En la figura 4.24 se puede observar un ejemplo de las comunicaciones establecidas entre


distintos dispositivos: mando de faros, control de faros, tablero de instrumentos y faros. Cuando se
acciona el mando de faros se origina un mensaje por parte de ste dispositivo hacia el control de
faros. El control de faros en respuesta al mensaje anterior enva un mensaje hacia los faros y el
tablero de instrumentos. Como consecuencia de sto los faros se encienden y cada una de stos
genera un mensaje de respuesta hacia el tablero de instrumentos indicando el estado de los faros (si
se encendieron correctamente o alguno presenta algn desperfecto). El tablero de instrumentos
recibe el mensaje proveniente del control de faros y de cada uno de los faros por separado, y genera
como respuesta el encendido de un indicador del tablero de instrumentos y en caso de haber alguna
falla genera una advertencia. ste ejemplo muestra la existencia de un grupo de difusin (1) cuyo
publicador es el mando de faros y el suscriptor es el control de faros; ste ltimo a su vez es
publicador de dos grupos de difusin (2 y 3) cuyos suscriptores son los faros y el tablero de
instrumentos; y cada faro es publicador de un grupo de difusin (4, 5, 6 y 7) que posee un nico
suscriptor que es el tablero de instrumentos.

4.5.3. Grupos de difusin


El grupo de difusin es medio por el cual un dispositivo intercambia informacin con otros
mediante el pasaje de mensajes. Cada grupo se encuentra asociado a un grupo de difusin de la capa
de transporte, en donde existen dispositivos que se suscriben y que publican mensajes. En el caso
134

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


particular del grupo de difusin se restringe a un dispositivo la capacidad de publicar (designado
dispositivo publicador) y el resto son simples suscriptores destinatarios de los mensajes generados
por el dispositivo anteriormente mencionado. Este concepto se asemeja a la idea de una red de
cableado dedicado en donde un dispositivo genera una seal de salida que es tomada como entrada
por otros dispositivos, en donde se puede establecer una analoga entre el primer dispositivo y el
publicador, y el resto de los dispositivos y los suscriptores, siendo el conductor de la seal anlogo
al grupo de difusin, y las seales encuentran su equivalente en los mensajes. Esta analoga permite
trasladar un diseo de red implementado con cableado dedicado a la implementacin propuesta por
la red PLC, en donde el cableado dedicado se implementa en forma virtual por medio de los grupos
de difusin.
Un grupo de difusin se individualiza del resto por medio del identificador nico. Cada uno
de los dispositivos presentes en la red se asocian a dichos grupos en el momento en que se registran
como publicadores o suscriptores en el inicio de la sesin, siendo este proceso anlogo a las
conexiones fsicas de una red de cableado dedicado. El identificador de grupo es un nmero cuyo
valor se encuentra comprendido entre 1 y 255.
Cada dispositivo de la red puede ser publicador en varios grupos de difusin y a su vez
suscriptores en otros grupos, permitiendo el flujo bidireccional de la informacin, conformando
redes como por ejemplo la detallada en la figura 4.24. Dichas redes brindan la capacidad de ser
expandidas agregando dispositivos con nuevas funcionalidades, por ejemplo se puede agregar un
interruptor crepuscular simplemente agregando dos canales de difusin (figura 4.25): un canal en
donde el mando de faros sea el publicador, y ordene la activacin o desactivacin del interruptor
crepuscular que es el suscriptor, y otro canal en donde el interruptor crepuscular sea el publicador
que ordene al control de faros (suscriptor) encender o apagar los faros y notificar al tablero de
instrumentos de sta accin. La nica condicin que se exige para que sto sea posible es que el
control de faros se registre al grupo de difusin en donde el interruptor crepuscular es publicador,
independientemente de que se encuentre presente o no ste ltimo dispositivo, ya que pueden existir
canales de difusin sin publicadores (aunque carezcan de sentido). sto permite disear un nico
sistema con funcionalidades que se pueden agregar o quitar sin necesidad de realizar ningn cambio
fsico sobre los dispositivos ms all de la conexin fsica de los mismos a la red.

Figura 4.25. Ejemplo de expansin de funcionalidades.

En la figura 4.25 se puede observar el agregado del interruptor crepuscular y el grupo de


difusin utilizado para activarlo y desactivarlo (8), y el grupo de difusin que utiliza el interruptor
crepuscular para ordenar al control de faros el encendido o apagado de los faros, y la notificacin al
tablero de instrumentos (8).
FernandoArielBeunza79156

135

Tesis de Grado en Ingeniera Informtica

4.5.4. Estructura de los mensajes


Los mensajes, adems de contener informacin, poseen cierta informacin adicional de
control necesaria para que los dispositivos destinatarios puedan desarmarlos y recuperar la
informacin originalmente enviada. A continuacin se detalla en la figura 4.26 la estructura de un
mensaje:
Versin

Datos

8 bits

(capacidad mxima de
capa de transporte - 8) bits

1 byte

(capacidad mxima de
capa de transporte - 1) bytes

Figura 4.26. Estructura de un mensaje.

Versin: identificador de versin del protocolo de transporte.

Datos: informacin transportada por el mensaje. La mxima capacidad de transporte


depende la capacidad que brinda la capa de transporte.

4.5.5. Primitivas de manejo de la capa de sesin


A continuacin se detallan las primitivas referentes al manejo de la capa de sesin (cuya
implementacin se detalla en el Apndice C) que proporcionan las funcionalidades de inicializacin
y liberacin de recursos, envo de mensajes y recepcin de los mismos:

136

void sp_init(void):
Inicializa la capa de sesin, los buffers de mensajes y la funcin de recepcin de
mensajes.

void sp_release(void):
Libera los recursos inicializados por la primitiva anterior.

int sp_publish(sp_grpid grpid):


Establece que el dispositivo es el publicador del grupo de difusin grpid. Si esta
operacin se realiz correctamente y devuelve como resultado el valor uno, sino devuelve
cero.

int sp_subscribe(sp_grpid grpid):


Establece que el dispositivo es suscriptor del grupo de difusin grpid. Si esta operacin se
realiz correctamente y devuelve como resultado el valor uno, sino devuelve cero.

int sp_leave(sp_grpid grpid):


Desvincula el dispositivo del grupo de difusin grpid. Si esta operacin se realiz
correctamente y devuelve como resultado el valor uno, sino devuelve cero.

short int sp_send(sp_grpid grpid, unsigned char nosec, const void *msg, short int
msgsize):
FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Enva un mensaje msg de longitud msgsize del tipo type por medio del grupo de difusin
grpid. El mensaje puede excluirse de la secuencia de mensajes enviados por medio de la
activacin del indicador nosec, que en caso de una resincronizacin el mensaje no ser
recuperado. Devuelve como resultado la cantidad de bytes enviados, que coincide con
msgsize si la operacin de envo pudo ser realizada.

short int sp_receive(sp_grpid *grpid, void *msg, short int msgsize):


Recibe msgsize bytes que se transfieren a msg recibido a travs del grupo de difusin
grpid. Cuando se recibe un mensaje de la capa de transporte, se invoca la funcin
dedicada a recepcin y procesamiento de mensajes. Si luego de interpretar el mensaje,
ste resulta vlido, se almacena en el buffer de mensajes. Esta primitiva transfiere
msgsize bytes del contenido del buffer a msg y devuelve la cantidad de bytes transferidos
como resultado. Si el buffer se encuentra vaco, queda a la espera de que llegue un
mensaje.

void sp_notify(void (*func)(sp_grpid grpid, void *msg, short int msgsize)):


Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un mensaje por medio del grupo de difusin grpid. Dicha funcin debe tener
definidos como parmetros grpid, msg y msgsize, que cumplen la misma funcin que en
la primitiva de anterior. El objetivo de sta primitiva es poder procesar la informacin que
transporta el mensaje de forma inmediata a la recepcin del mismo, sin bloquear el
microcontrolador, como ocurre con la anterior primitiva.

int sp_poll(void):
Esta primitiva verifica el estado del buffer de mensajes. Devuelve como resultado uno si
el buffer contiene un mensaje a la espera de ser recibido mediante la primitiva sp_receive.
Si el buffer se encuentra vaco el resultado devuelto es cero. De sta forma puede
implementarse una espera no bloqueante utilizando la primitiva sp_receive.

int sp_status(void):
Esta primitiva verifica si la conexin se encuentra activa o no. Una conexin queda
inactiva cuando la capa de sesin no pudo resincronizar el dispositivo. Devuelve como
resultado un valor positivo distinto a cero si el nodo se encuentra operativo. Si no hay
ninguna interfaz fsica activa el resultado devuelto es cero.

short int sp_getpayloadsize(void):


Esta primitiva devuelve la cantidad mxima de bytes que puede contener un mensaje.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la capa de sesin, en tres primitivas el registro y desvinculacin de un
dispositivo a un determinado grupo de difusin, en cuatro primitivas el envo y recepcin (en modo
bloqueante y no bloqueante) de mensajes, y en dos primitivas el manejo de informacin acerca del
dispositivo.

FernandoArielBeunza79156

137

Tesis de Grado en Ingeniera Informtica

4.6. Capa de presentacin


La capa de presentacin es responsable de proveer los mecanismos para el transporte de
datos estructurados entre diferentes aplicaciones usuarias. sto implica realizar las conversiones
correspondientes segn la plataforma sobre la cual se montan las aplicaciones usuarias, para que
stas ltimas procesen de forma correcta los datos recibidos (por ejemplo, la representacin de un
entero utilizada en la plataforma Intel es diferente la utilizada en la plataforma Motorola). La capa
de sesin solamente brinda la capacidad de transporte de datos sin ninguna estructura de forma
confiable, siendo responsabilidad de la capa de presentacin la implementacin de un protocolo de
representacin de cada tipo de datos independiente de las plataformas utilizadas en las aplicaciones
usuarias, e implementar en stas ltimas los correspondientes mecanismos de conversin entre la
representacin utilizada por el protocolo y la representacin propia de cada plataforma.

4.6.1. Implementacin de datos estructurados


Todas las capas tratadas hasta ahora trabajan con datos sin ningn tipo de estructura de
organizacin, simplemente son cadenas de bytes cuya responsabilidad de interpretarlos de la forma
correcta recae sobre la aplicacin usuaria que se encuentra por encima de la capa de sesin. Adems
existe una dependencia proveniente de la plataforma, como ocurre con los valores enteros, que no
toda las plataformas implementan este tipo de datos de la misma forma, por lo cual una aplicacin
que corre sobre una plataforma Intel, cuando recibe un valor entero originado por otra aplicacin
que corre sobre una plataforma Motorola, debe realizarse una conversin previa, ya que ambas
plataformas representan los valores enteros de diferentes modos. La no realizacin de dicha
conversin provocara un resultado errneo. Lo deseable en stos casos es de disponer de una capa
de abstraccin que realice todas las conversiones necesarias cuando son necesarias y que la
aplicacin usuaria se liber de sta tarea. La capa de presentacin se crea para brindar la abstraccin
anteriormente mencionada.
La introduccin de la capa de presentacin trae como consecuencia la necesidad de
implementar un protocolo propio de representacin de un conjunto de tipos de datos que sea
independiente de la plataforma donde corre especficamente la mencionada capa, por ejemplo, la
capa de presentacin puede establecer que la forma de representar un valor entero sea compatible a
la utilizada por la plataforma Motorola, en tal caso, la implementacin de la capa de presentacin
sobre una plataforma compatible con Motorola, no modifica los valores enteros enviados o
recibidos; en cambio si la capa de presentacin se encuentra implementada sobre una plataforma
Intel siempre que se enve o reciba un valor entero debe realizarse la conversin correspondiente.
Como se puede observar en el ejemplo anterior, la capa de presentacin es dependiente de la
plataforma sobre la cual es implementada, por lo cual se requiere tantas versiones de dicha capa
como plataformas se quiera cubrir. sto hace que la capa de presentacin no se encuentre
implementada dentro de modem PLC, como ocurre con las capas inferiores a sta.
Adems del tpico ejemplo de los valores enteros y sus distintas variantes (16 bits, 32 bits,
etc.), existen otras estructuras de datos como valores de punto flotante y caracteres. stos tipos de
datos son atmicos o simples, pero tambin existe la necesidad de combinarlos para conformar
estructuras de datos ms complejas. Un ejemplo son los arreglos que pueden conformarse por varios
valores enteros o de punto flotante; en el caso de los caracteres, un arreglo de ste tipo de dato
conforma una cadena de caracteres. Adems de conformar una estructura compuesta por varios
datos de un nico tipo, pueden existir estructuras conformadas por datos de distintos tipos e incluso
arreglos de datos. Los diferentes tipos de datos y sus posibles combinaciones en estructuras
138

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


complejas deberan ir de la mano junto con el lenguaje de programacin cliente de la capa de
presentacin para tener cubierta todas las posibilidades y poder armar mensajes con diferentes
estructuras de datos.
El estndar LonWorks es uno de los estndares existentes que resuelve el problema de la
representacin de los datos implementando una capa de presentacin. La idea que propone es de
disponer de un conjunto de tipos atmicos que se puedan combinar para formar tipos compuestos
como arreglos y estructuras. En el presente trabajo se toma la misma idea de LonWorks, y se
implementa una capa de presentacin con tipos de datos atmicos similares que pueden componer
tipos compuestos.
La capa de presentacin implementada en ste trabajo presenta hacia las capas superiores un
conjunto de tipos de datos para ser usados independiente de la plataforma sobre la cual se est
trabajando. sto implica que un tipo de datos brindado por la capa de presentacin debe ser posible
su representacin en todas las plataformas. La idea de la presente capa es presentar un conjunto
reducido de tipos de datos que permita por medio de combinaciones de los mismos poder
representar un conjunto bsico de estructuras de datos.
Los tipos de datos pueden ser atmicos (simples) o compuestos (integrados por tipos de
datos atmicos o a su vez compuestos). Dentro de los tipos de datos atmicos, la capa de
presentacin define los siguientes:

Caracter: representa un caracter.

Enteros de 8 bits: representa un valor entero cuyo rango de valores posibles se encuentra
comprendido entre -128 y 127 (en caso de ser enteros con signo) o entre 0 y 255 (en caso
de tratarse de enteros sin signo).

Enteros de 16 bits: representa un valor entero cuyo rango de valores posibles se encuentra
comprendido entre -32768 y 32767 (en caso de ser enteros con signo) o entre 0 y 65535
(en caso de tratarse de enteros sin signo).

Enteros de 32 bits: representa un valor entero cuyo rango de valores posibles se encuentra
comprendido entre -2147483648 y 2147483647 (en caso de ser enteros con signo) o entre
0 y 4294697296 (en caso de tratarse de enteros sin signo).

Punto flotante: representa un valor decimal cuyo rango de valores se encuentra


comprendido aproximadamente entre 10-38 y 1038.

Los tipos de datos compuestos pueden ser arreglos, o estructuras que contengan tipos de
datos atmicos o arreglos. Con cada uno los tipos de datos atmicos se pueden conformar arreglos
de datos, para constituir, por ejemplo, una lista de valores enteros o de punto flotante. Con un
arreglo del tipo caracter se puede construir una cadena de caracteres de suma para el envo mensajes
con texto. A su vez se puede crear una estructura de datos compuesta por arreglos de tipos de datos
atmicos. Una estructura adems de poder contener arreglos puede contener tipos de datos atmicos
individuales.
La implementacin de la capa de presentacin define el concepto de mensaje como un
conjunto de campos de datos. A cada uno de stos campos se le puede especificar un tipo asociado
al tipo de dato que se desea almacenar en el mismo. Adems se puede establecer la cantidad de
datos almacenados, permitiendo la conformacin de arreglos de un determinado tipo de dato. De
esta forma, un mensaje conforma una estructura de datos.

FernandoArielBeunza79156

139

Tesis de Grado en Ingeniera Informtica


La capa de presentacin implementa una forma propia de representar cada uno de los tipos
de datos anteriores que es independiente de la representacin utilizada por la plataforma. sto
ltimo afecta a los tipos de datos atmicos, cuya representacin se describe a continuacin:

Caracter: se representa por medio de un byte.

Enteros de 8 bits: se representa por medio de un byte.

Enteros de 16 bits: se representa por medio de dos bytes con la disposicin big endian.

Enteros de 32 bits: se representa por medio de cuatro bytes con la disposicin big endian.

Punto flotante: se representa por medio de cuatro bytes conforme a lo especificado en el


estndar 754 de IEEE [IEEE754] para representacin de nmeros decimales con simple
precisin.

4.6.2. Esquema multiplataforma


Como se hizo mencin con anterioridad, la capa de presentacin debe ser multiplataforma,
es decir que debe existir una implementacin por cada plataforma que se desee integrar al red PLC.
Con las capas inferiores no es necesario sto ltimo, debido a que se encuentran implementadas
dentro del modem PLC que responde a una nica plataforma, que en ste caso particular
corresponde a los microcontroladores de la familia 8052. Por las razones expuestas con
anterioridad, la capa de presentacin no puede implementarse dentro del modem PLC debido a que
sta capa es dependiente de la plataforma, ya que las operaciones de conversin de datos deben
realizarse conforme a la plataforma sobre la cual se monta sta capa.
En el presente trabajo se utilizan tres plataformas: AT89X5X, Windows y Linux. La primer
plataforma es necesaria para implementar dispositivos clientes reales con una funcin particular,
que en ste caso se opta por utilizar microcontroladores de la familia 8051. La segunda y tercer
plataforma se relacionan con los dispositivos clientes virtuales que se pueden simular con una PC y
con el monitoreo de la red PLC. En referencia al hardware, para la segunda y tercer plataforma, es el
mismo; la diferencia radica en el sistema operativo utilizado, que para este trabajo se utiliza
Windows y Linux para mostrar la independencia de la red PLC respecto al sistema operativo que se
utilice en la PC.
La capa de presentacin junto con las capa inmediata superior (capa de aplicacin) y la
interfaz de comunicacin con el modem PLC, se implementan dentro de una biblioteca esttica, para
el caso de la plataforma AT89X5X, y de un driver y una biblioteca dinmica para el caso de
Windows y Linux. La idea con esto es permitir un acceso simple a la red PLC por parte de las
aplicaciones clientes utilizando un conjunto de rutinas idntico para todas las plataformas, aunque
en realidad difieran en su implementacin interna.
Tanto las plataforma AT89X5X, como Windows y Linux, todas son compatibles con
arquitectura Intel, por lo cual a primera vista resulte innecesaria la existencia de una capa de
presentacin, pero la idea del presente trabajo es dejar abierta la posibilidad de la incorporacin de
nuevas plataformas ms all de las utilizadas para la evaluacin de la solucin propuesta, por ste
motivo no se puede obviar la existencia de la capa de presentacin.

140

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

4.6.3. Estructura de los mensajes


Los mensajes se conforman de una sucesin de campos de datos, y cantidad y tamao de
stos se encuentra limitada a la capacidad mxima de transporte que brinda la capa inmediata
inferior (capa de sesin). Cada campo de datos representa a un tipo de dato diferente, permitiendo
que un mensaje pueda formar una estructura de datos compleja. Adems por cada tipo de dato
pueden tenerse uno o varios datos, lo que permite conformar arreglos de datos. A continuacin se
detalla en la figura 4.27 la estructura de un campo de datos:
Tipo de Cantidad
campo de datos

Datos

8 bits

8 bits

(tamao tipo de dato * cantidad de datos) bits

1 byte

1 byte

(tamao tipo de dato * cantidad de datos) bytes

Figura 4.27. Estructura de un campo de datos.

Tipo de campo: especifica el tipo de datos almacenado en el rea de datos.

Cantidad de datos: especifica la cantidad de datos almacenados en el rea de datos. Tiene


un mximo terico de 256, pero el mximo real depende del tamao del tipo de dato y de
la capacidad de transporte del mensaje.

Datos: rea donde se almacenan el o los datos. La capacidad sta limitada por la
capacidad mxima de transporte del mensaje.

4.6.4. Primitivas de manejo de la capa de presentacin


A continuacin se detallan las primitivas referentes al manejo de la capa de presentacin
(cuya implementacin se detalla en el Apndice C) que proporcionan las funcionalidades de
inicializacin y liberacin de recursos, envo de mensajes y recepcin de los mismos:

modplcpp_hd *modplcpp_init(int sid):


Inicializa la capa de presentacin, la conexin con el modem PLC a travs de la interfaz
de comunicacin serie sid. La interfaz de comunicacin serie se especifica por medio de
un nmero identificatorio que en caso de la plataforma AT89X5X el nico valor posible es
1 (por existir solamente una interfaz), en caso de la plataforma Windows dicho nmero
corresponde al puerto COM (el valor 1 equivale a COM1, el valor 2 equivale a COM2,
etc.), y en caso de la plataforma Linux el nmero de puerto corresponde a la interfaz /dev/
ttyS (el valor 1 equivale a /dev/ttyS0, el valor 2 equivale a /dev/ttyS1, etc.). Si la
operacin se realiz correctamente devuelve el manejador de conexin, sino devuelve un
manejador nulo.

int modplcpp_release(modplcpp_hd *hd):


Libera los recursos de la capa de presentacin asociados al manejador de conexin hd. Si
esta operacin se realiz correctamente y devuelve como resultado el valor uno, sino
devuelve cero.

int modplcpp_publish(modplcpp_hd *hd, modplcpp_grpid grpid):

FernandoArielBeunza79156

141

Tesis de Grado en Ingeniera Informtica


Establece que el dispositivo es el publicador del grupo de difusin grpid, por medio de la
conexin hd. Si esta operacin se realiz correctamente y devuelve como resultado el
valor uno, sino devuelve cero.

142

int modplcpp_subscribe(modplcpp_hd *hd, modplcpp_grpid grpid):


Establece que el dispositivo es suscriptor del grupo de difusin grpid por medio de la
conexin hd. Si esta operacin se realiz correctamente y devuelve como resultado el
valor uno, sino devuelve cero.

int modplcpp_leave(modplcpp_hd *hd, modplcpp_grpid grpid):


Desvincula el dispositivo del grupo de difusin grpid por medio de la conexin hd. Si
esta operacin se realiz correctamente y devuelve como resultado el valor uno, sino
devuelve cero.

int modplcpp_newmsg(modplcpp_hd *hd, modplcpp_msg *msg, modplcpp_grpid grpid,


modplcpp_mtype mtype):
Crea un nuevo mensaje msg, del tipo mtype que ser enviado por el grupo de difusin
grpid por medio de la conexin hd. Si esta operacin se realiz correctamente, devuelve
como resultado el valor uno y la estructura del mensaje inicializada lista para ser
completada con diferentes campos, sino devuelve cero.

int modplcpp_copymsg(modplcpp_msg *dest, modplcpp_msg *src):


Crea una copia en dest del mensaje src. Si esta operacin se realiz correctamente,
devuelve como resultado el valor uno, sino devuelve cero.

int modplcpp_putfield(modplcpp_msg *msg, modplcpp_ftype type, unsigned char count,


const void *dat):
Agrega un nuevo campo al mensaje msg. Dicho campo se compone de una cantidad count
de datos dat del tipo ftype. Si esta operacin se realiz correctamente, devuelve como
resultado el valor uno y la estructura del mensaje con el nuevo campo incorporado, sino
devuelve cero.

int modplcpp_sendmsg(modplcpp_msg *msg):


Enva un mensaje msg. Si esta operacin se realiz correctamente, devuelve como
resultado el valor uno, sino devuelve cero.

int modplcpp_receivemsg(modplcpp_hd *hd, modplcpp_msg *msg):


Recibe un mensaje msg por medio de la conexin hd. Si no existe ningn mensaje
pendiente de ser recibido, queda a la espera de la llegada de uno. Si esta operacin se
realiz correctamente, devuelve como resultado el valor uno, sino devuelve cero.

int modplcpp_getfield(modplcpp_msg *msg, modplcpp_ftype *type, unsigned char


*count, void *dat):
Extrae del mensaje msg un campo compuesto por una cantidad count de datos dat del tipo
ftype. Si esta operacin se realiz correctamente, devuelve como resultado el valor uno y
la estructura del mensaje sin el campo extrado, sino devuelve cero.

modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *msg):

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Extrae del mensaje msg el identificador de grupo de difusin por el cual fue recibido. Si
esta operacin se realiz correctamente, devuelve como resultado el valor uno, sino
devuelve cero.

int modplcpp_destroymsg(modplcpp_msg *msg):


Destruye el mensaje msg liberando todos los recursos utilizados por ste. Si esta
operacin se realiz correctamente, devuelve como resultado el valor uno, sino devuelve
cero.

int modplcpp_notify(modplcpp_hd *hd, void (*func)(modplcpp_hd *hd, modplcpp_msg


*msg, void *param), void *param):
Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un mensaje. Dicha funcin debe tener definidos como parmetros hd, msg y
param, que cumplen la misma funcin que en la primitiva modplcpp_receivemsg. El
objetivo de sta primitiva es poder un mensaje de forma inmediata a la recepcin de la
mismo, sin bloquear el microcontrolador. El parmetro param es opcional y puede ser
utilizado para enviar parmetros adicionales al momento de invocar a la funcin func.

int modplcpp_poll(modplcpp_hd *hd):


Esta primitiva verifica si hay algn mensaje a la espera de ser recibido por medio de la
conexin hd. Devuelve como resultado uno si existe un mensaje a la espera de ser
recibido mediante la primitiva modplcpp_receivemsg. Caso contrario, el resultado
devuelto es cero. De sta forma puede implementarse una espera no bloqueante utilizando
la primitiva modplcpp_receivemsg.

int modplcpp_status(modplcpp_hd *hd):


Esta primitiva verifica si la conexin con modem PLC asociada al manejador hd se
encuentra activa o no. Devuelve como resultado un valor positivo distinto a cero si el
nodo se encuentra activo, caso contrario devuelve como resultado cero.

El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de


los recursos utilizados por la capa de presentacin, en tres primitivas la suscripcin y
desvinculacin de un dispositivo a un determinado grupo de difusin, en diez primitivas el armado y
desarmado de mensajes, y en una primitiva la verificacin del estado de la conexin.

4.7. Capa de aplicacin


La capa de aplicacin es responsable de proveer un servicio de intercambio de mensajes
entre distintos dispositivos que pueden pertenecer a distintas plataformas, y que adems pueden ser
reales o virtuales (dispositivos simulados por computadora). Dichos mensajes son utilizados para
enviar rdenes solicitando la realizacin de acciones concretas por parte de los dispositivos
destinatarios, o bien para modificar la configuracin de stos ltimos. Los mensajes tambin pueden
ser utilizados para reportar estados o fallas de dispositivos.

FernandoArielBeunza79156

143

Tesis de Grado en Ingeniera Informtica

4.7.1. Servicio de mensajera


Los distintos dispositivos conectados a una red PLC comn es intercomunican por medio de
un bus de mensajes a diferencia de las redes dedicadas que lo realizan por medio de seales que
viajan por conductores dedicados. El concepto es simple, en una red dedicada se enva una seal
para activar o desactivar algo, por ejemplo el encendido o apagado de un faro; en cambio en un bus
de mensajes se transmite una orden de encendido o apagado que es ejecutada por el destinatario
quien realiza la accin correspondiente. sto ltimo se puede observan en redes como CAN y J1850,
aunque en las redes anteriores los mensajes se encuentran muy relacionados con el medio fsico. En
cambio en las redes como LonWorks y MOST, el servicio de mensajera es ms independiente de los
aspectos fsicos debido a que se implementa a nivel de capa de aplicacin. La idea de ste trabajo es
seguir la propuestas de las dos ltimas redes mencionadas, debido a que en el presente trabajo se
implementan las siete capas propuestas por el modelo OSI.
La capa de presentacin permite el envo de mensajes estructurados en donde se pueden
definir distintos tipos de datos independientes de la plataforma de trabajo. Con este servicio provisto
se puede componer una orden conformada por un identificador propio del mismo y una serie de
parmetros opcionales que pueden ser necesarios si la orden a transmitir requiere de una accin
compleja, por ejemplo, si se requiere regular la intensidad lumnica de un dispositivo de
iluminacin no bastar con una orden de encendido o apagado sino que debe pasarse como
parmetro el valor asociado a la intensidad.
Los mensajes que dan una orden son generados por los dispositivos clientes que solicitan la
realizacin de una determinada accin y son recibidos por el o los dispositivos encargados de
llevarla a cabo debido al esquema de difusin implementado por la pila de protocolos. La va es
unidireccional ya que no brinda la posibilidad de respuesta en forma directa debido a que respuestas
de mltiples destinatarios requiere una implementacin compleja. Igualmente se puede implementar
un mecanismo de respuesta a la accin solicitada mediante otro mensaje en donde el destinatario
original sea el generador de este mensaje de respuesta y el dispositivo que requiri la accin
originariamente sea el destinatario. A su vez este mensaje de respuesta puede ser captado por otros
dispositivos no involucrados con la orden original. Dicho mensaje de respuesta puede hacer uso de
los parmetros para informar el estado de la accin ejecutada, por ejemplo si el dispositivo de
iluminacin detecta que el foco se encuentra quemado puede reportar mediante un cdigo que la
orden de regular la intensidad no se puede ejecutar por una falla del dispositivo en el iluminacin.
Los mensajes adems de estar asociados a una orden o a una respuesta de sta, puede
solicitar cambios en la configuracin de un dispositivo, por ejemplo el control de posicin de faros
delanteros puede enviar un mensaje a los faros delanteros indicando modificar la posicin de los
mismos ante un cambio realizado por el usuario por medio del control anterior. sto ltimo puede
verse tambin como una orden, pero tiene diferencia con respecto, por ejemplo, el encendido o
apagado de los faros. La diferencia radica en que cambiar una configuracin es un cambio
persistente que no prioriza el tiempo necesario para realizarlo, por lo cual el sistema de
comunicacin pone nfasis en asegurar que el mensaje llegue que en el tiempo que demor en
realizar sto ltimo. El encendido o apagado de un faro requiere que la accin sea ejecutada lo ms
rpido posible, resignando la persistencia a favor del tiempo real. En base a lo anterior, la
implementacin propuesta establece dos tipos de mensajes: uno correspondiente para el primer caso
estudiado y otro para el segundo. La manera de indicar el tipo de mensaje que se desea utilizar es
por medio del identificador de mensaje en donde se establece que los identificadores menores al
valor hexadecimal 8000 pertenecen al primer tipo, y los mayores al segundo tipo.
Los parmetros de los mensaje trabajan con diferentes tipos de datos heredados de la capa
inmediata inferior (capa de presentacin) lo que mantiene la independencia de plataforma y permite
trabajar con tipos de datos ms complejos que el byte, por ejemplo la intensidad del foco de
144

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


iluminacin puede regularse en un rango comprendido entre 0 y 65535, lo cual requiere de un
nmero entero de 16 bits; y por la independencia de plataforma el dispositivo que origin la orden
podra ser un microcontrolador de la familia Motorola y el microcontrolador del dispositivo
destinatario de la familia Intel sin ningn inconveniente. Tambin los parmetros pueden ser
arreglos de tipos, en caso de tener que enviar varios parmetros del mismo tipo; y un mensaje puede
presentar varios parmetros de diferentes tipos, del mismo modo que lo hacen los mensajes de la
capa de presentacin. Los tipos de datos permitidos para los parmetros de los mensajes son
idnticos a los provistos por la capa de presentacin (ver representacin de estructuras de datos).

4.7.2. Esquema multiplataforma


La capa de aplicacin se puede ver como la interfaz final de la pila de protocolos encargados
del servicio de mensajera por medio de la red PLC. Dicha interfaz es nica para todas las
plataformas, lo cual no significa que si lo sea su implementacin. De la misma manera que en la
capa de presentacin, la capa de aplicacin implementa tres plataformas: AT89X5X, Windows y
Linux.
Las diferencias entre las distintas implementaciones se encuentran relacionadas con la forma
de implementar las bibliotecas en cada una de las plataformas. Para el caso de la plataforma
AT89X5X, la biblioteca es esttica y no requiere mayor complejidad que presentar la declaracin de
cada una de las rutinas y la biblioteca con la implementacin de las mismas. Mencionadas rutinas se
unen junto con las propias de la aplicacin cliente durante el proceso de compilacin para
conformar un firmware que residir en un microcontrolador de la familia AT89X5X.
Diferente es el caso de las plataformas Windows y Linux, ya que stos entornos son ms
complejos que un microcontrolador. En ambos casos las bibliotecas no son estticas, sino
dinmicas, lo que significa que las rutinas de la biblioteca y las rutinas propias de la aplicacin
usuaria residen en forma separada y no se unen en el proceso de compilacin como ocurra con el
anterior caso. A su ves estas dos ltimas plataformas tiene implementaciones diferentes de
bibliotecas dinmicas: en Windows es necesario adicionar cdigo dedicado a la carga de las rutinas
de la biblioteca, mientras que en Linux la operatoria es similar a la empleada cuando la biblioteca es
esttica (afecta al proceso de compilacin, pero no el cdigo fuente). Las bibliotecas dinmicas no
se comunican directamente con el modem PLC, sino que lo hacen por medio de un driver, que
adems permite que varias aplicaciones puedan trabajar con un mismo modem compartiendo la
conexin.
La vista final en todos los casos es la misma, porque cada plataforma contiene el cdigo
necesario para que la aplicacin usuaria se desentienda completamente del manejo de bibliotecas
salvo del mtodo de invocacin de las mismas.
De la misma manera como ocurre con la capa de presentacin, la presente capa a pesar de
implementar solamente tres plataformas, es dejar abierta la posibilidad de la incorporacin de
nuevas plataformas ms all de las utilizadas para la evaluacin de la solucin propuesta.

4.7.3. Primitivas de manejo de la capa de aplicacin


A continuacin se detallan las primitivas referentes al manejo de la capa de aplicacin (cuya
implementacin se detalla en el Apndice C) que proporcionan las funcionalidades de inicializacin
y liberacin de recursos, envo de mensajes y recepcin de los mismos:

FernandoArielBeunza79156

145

Tesis de Grado en Ingeniera Informtica

146

modplcap_hd *modplcap_init(int sid):


Inicializa la capa de aplicacin, la conexin con el modem PLC a travs de la interfaz de
comunicacin serie sid. La interfaz de comunicacin serie se especifica por medio de un
nmero identificatorio que en caso de la plataforma AT89X5X el nico valor posible es 1
(por existir solamente una interfaz), en caso de la plataforma Windows dicho nmero
corresponde al puerto COM (el valor 1 equivale a COM1, el valor 2 equivale a COM2,
etc.), y en caso de la plataforma Linux el nmero de puerto corresponde a la interfaz /dev/
ttyS (el valor 1 equivale a /dev/ttyS0, el valor 2 equivale a /dev/ttyS1, etc.). Si la
operacin se realiz correctamente devuelve el manejador de conexin, sino devuelve un
manejador nulo.

int modplcap_release(modplcap_hd *hd):


Libera los recursos de la capa de aplicacin asociados al manejador de conexin hd. Si
esta operacin se realiz correctamente y devuelve como resultado el valor uno, sino
devuelve cero.

int modplcap_publish(modplcap_hd *hd, modplcap_grpid grpid):


Establece que el dispositivo es el publicador del grupo de difusin grpid, por medio de la
conexin hd. Si esta operacin se realiz correctamente y devuelve como resultado el
valor uno, sino devuelve cero.

int modplcap_subscribe(modplcap_hd *hd, modplcap_grpid grpid):


Establece que el dispositivo es suscriptor del grupo de difusin grpid por medio de la
conexin hd. Si esta operacin se realiz correctamente y devuelve como resultado el
valor uno, sino devuelve cero.

int modplcap_leave(modplcap_hd *hd, modplcap_grpid grpid):


Desvincula el dispositivo del grupo de difusin grpid por medio de la conexin hd. Si
esta operacin se realiz correctamente y devuelve como resultado el valor uno, sino
devuelve cero.

int modplcap_newmsg(modplcap_hd *hd, modplcap_msg *msg, modplcap_grpid grpid,


modplcap_msgid msgid):
Crea un nuevo mensaje msg cuyo identificador es msgid que ser enviado por el grupo de
difusin grpid por medio de la conexin hd. Si esta operacin se realiz correctamente,
devuelve como resultado el valor uno y la estructura del mensaje inicializada lista para ser
completada con diferentes campos, sino devuelve cero.

int modplcap_copymsg(modplcap_msg *dest, modplcap_msg *src):


Crea una copia en dest del mensaje src. Si esta operacin se realiz correctamente,
devuelve como resultado el valor uno, sino devuelve cero.

int modplcap_putfield(modplcap_msg *msg, modplcap_ftype type, unsigned char count,


const void *dat):
Agrega un nuevo campo al mensaje msg. Dicho campo se compone de una cantidad count
de datos dat del tipo ftype. Si esta operacin se realiz correctamente, devuelve como
resultado el valor uno y la estructura del mensaje con el nuevo campo incorporado, sino
devuelve cero.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

int modplcap_sendmsg(modplcap_msg *msg):


Enva un mensaje msg. Si esta operacin se realiz correctamente, devuelve como
resultado el valor uno, sino devuelve cero.

int modplcap_receivemsg(modplcap_hd *hd, modplcap_msg *msg):


Recibe un mensaje msg por medio de la conexin hd. Si no existe ningn mensaje
pendiente de ser recibido, queda a la espera de la llegada de uno. Si esta operacin se
realiz correctamente, devuelve como resultado el valor uno, sino devuelve cero.

int modplcap_getfield(modplcap_msg *msg, modplcap_ftype *type, unsigned char


*count, void *dat):
Extrae del mensaje msg un campo compuesto por una cantidad count de datos dat del tipo
ftype. Si esta operacin se realiz correctamente, devuelve como resultado el valor uno y
la estructura del mensaje sin el campo extrado, sino devuelve cero.

modplcap_grpid modplcap_getgrpid(modplcap_msg *msg):


Extrae del mensaje msg el identificador de grupo de difusin por el cual fue recibido. Si
esta operacin se realiz correctamente, devuelve como resultado el valor uno, sino
devuelve cero.

modplcap_msgid modplcap_getmsgid(modplcap_msg *msg):


Extrae del mensaje msg el identificador del mismo. Si esta operacin se realiz
correctamente, devuelve como resultado el valor uno, sino devuelve cero.

int modplcap_destroymsg(modplcap_msg *msg):


Destruye el mensaje msg liberando todos los recursos utilizados por ste. Si esta
operacin se realiz correctamente, devuelve como resultado el valor uno, sino devuelve
cero.

int modplcap_notify(modplcap_hd *hd, void (*func)(modplcap_hd *hd, modplcap_msg


*msg, void *param), void *param):
Esta primitiva brinda la posibilidad de definir una funcin func que se ejecute cuando se
recibe un mensaje. Dicha funcin debe tener definidos como parmetros hd, msg y
param, que cumplen la misma funcin que en la primitiva modplcap_receivemsg. El
objetivo de sta primitiva es poder un mensaje de forma inmediata a la recepcin de la
mismo, sin bloquear el microcontrolador. El parmetro param es opcional y puede ser
utilizado para enviar parmetros adicionales al momento de invocar a la funcin func.

int modplcap_poll(modplcap_hd *hd):


Esta primitiva verifica si hay algn mensaje a la espera de ser recibido por medio de la
conexin hd. Devuelve como resultado uno si existe un mensaje a la espera de ser
recibido mediante la primitiva modplcap_receivemsg. Caso contrario, el resultado
devuelto es cero. De sta forma puede implementarse una espera no bloqueante utilizando
la primitiva modplcap_receivemsg.

int modplcap_status(modplcap_hd *hd):


Esta primitiva verifica si la conexin con modem PLC asociada al manejador hd se
encuentra activa o no. Devuelve como resultado un valor positivo distinto a cero si el
nodo se encuentra activo, caso contrario devuelve como resultado cero.

FernandoArielBeunza79156

147

Tesis de Grado en Ingeniera Informtica


El conjunto de primitivas descripto abstrae en dos primitivas la inicializacin y liberacin de
los recursos utilizados por la capa de presentacin, en tres primitivas la suscripcin y
desvinculacin de un dispositivo a un determinado grupo de difusin, en once primitivas el armado
y desarmado de mensajes, y en una primitiva la verificacin del estado de la conexin.

4.7.4. Interfaz C++


Las primitivas mencionadas anteriormente resultan tiles para el desarrollo de aplicaciones
en lenguaje C necesiten hacer uso del servicio de comunicaciones provisto por el sistema
desarrollado. Un aspecto positivo en el diseo del sistema propuesto en ste trabajo es la
flexibilidad para el agregado de extensiones que implementen interfaces para distintos entornos.
Para demostrar sto ltimo, en el presente trabajo se propone una interfaz para lenguaje C++, que
permite a aplicaciones desarrolladas en ste ltimo lenguaje, utilizar los servicios de comunicacin
provistos por el sistema desarrollado.
La interfaz C++ se compone de dos clases (cuya implementacin se detalla en el Apndice
D): una que maneja la conexin con el modem PLC, y la otra dedicada a los mensajes enviados y
recibidos por medio de la anterior. A continuacin se detallan los mtodos que componen a la
primer clase mencionada referente al manejo de la conexin con el modem PLC:

148

modplcapcpp::modplcapcpp(int sid):
Inicializa la capa de aplicacin, la conexin con el modem PLC a travs de la interfaz de
comunicacin serie sid. La interfaz de comunicacin serie se especifica por medio de un
nmero identificatorio que en caso de la plataforma Windows dicho nmero corresponde
al puerto COM (el valor 1 equivale a COM1, el valor 2 equivale a COM2, etc.), y en caso
de la plataforma Linux el nmero de puerto corresponde a la interfaz /dev/ttyS (el valor 1
equivale a /dev/ttyS0, el valor 2 equivale a /dev/ttyS1, etc.). Si la operacin se realiz
correctamente devuelve un nuevo objeto conexin.

modplcapcpp::~ modplcapcpp():
Libera los recursos de la capa de aplicacin asociados al objeto conexin.

int modplcapcpp::publish(modplcap_grpid grpid):


Establece que el dispositivo es el publicador del grupo de difusin grpid. Si esta
operacin se realiz correctamente y devuelve como resultado el valor uno, sino devuelve
cero.

int modplcapcpp::subscribe(modplcap_grpid grpid):


Establece que el dispositivo es suscriptor del grupo de difusin grpid. Si esta operacin se
realiz correctamente y devuelve como resultado el valor uno, sino devuelve cero.

int modplcapcpp::leave(modplcap_grpid grpid):


Desvincula el dispositivo del grupo de difusin grpid. Si esta operacin se realiz
correctamente y devuelve como resultado el valor uno, sino devuelve cero.

int modplcapcpp::poll(void):

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Esta primitiva verifica si hay algn mensaje a la espera de ser recibido. Devuelve como
resultado uno si existe un mensaje a la espera de ser recibido. Caso contrario, el resultado
devuelto es cero.

int modplcapcpp::status(void):
Esta primitiva verifica si la conexin con modem PLC se encuentra activa o no. Devuelve
como resultado un valor positivo distinto a cero si el nodo se encuentra activo, caso
contrario devuelve como resultado cero.

De la misma forma que se detallaron los mtodos de la anterior clase, a continuacin se describen
los mtodos que conforman a la clase que maneja los mensajes:

modplcapcpp_msg::modplcapcpp_msg(modplcapcpp *hd, modplcapcpp_grpid grpid,


modplcapcpp_msgid msgid):
Crea un nuevo mensaje cuyo identificador es msgid que ser enviado por el grupo de
difusin grpid por medio de la conexin hd. Si esta operacin se realiz correctamente, el
objeto mensaje se encuentra listo para ser completado con diferentes campos.

modplcapcpp_msg::modplcapcpp_msg(modplcapcpp_msg *msg):
Crea una copia del mensaje msg. Si esta operacin se realiz correctamente, un nuevo
objeto mensaje que es una copia del mensaje msg.

modplcapcpp_msg::modplcapcpp_msg(modplcapcpp *hd):
Recibe un mensaje por medio de la conexin hd. Si no existe ningn mensaje pendiente
de ser recibido, queda a la espera de la llegada de uno. Si esta operacin se realiz
correctamente, devuelve como resultado un objeto mensaje con la informacin recibida.

modplcapcpp_msg::~modplcapcpp_msg():
Destruye el mensaje liberando todos los recursos utilizados por ste.

int modplcapcpp_msg::putfield(modplcapcpp_ftype type, unsigned char count, const void


*dat):
Agrega un nuevo campo al mensaje. Dicho campo se compone de una cantidad count de
datos dat del tipo ftype. Si esta operacin se realiz correctamente, devuelve como
resultado el valor uno y la estructura del mensaje con el nuevo campo incorporado, sino
devuelve cero.

int modplcapcpp_msg::sendmsg(void):
Enva un mensaje. Si esta operacin se realiz correctamente, devuelve como resultado el
valor uno, sino devuelve cero.

int modplcapcpp_msg::getfield(modplcapcpp_ftype *type, unsigned char *count, void


*dat):
Extrae del mensaje un campo compuesto por una cantidad count de datos dat del tipo
ftype. Si esta operacin se realiz correctamente, devuelve como resultado el valor uno y
la estructura del mensaje sin el campo extrado, sino devuelve cero.

modplcapcpp_grpid modplcapcpp_msg::getgrpid(void):

FernandoArielBeunza79156

149

Tesis de Grado en Ingeniera Informtica


Extrae del mensaje, el identificador de grupo de difusin por el cual fue recibido. Si esta
operacin se realiz correctamente, devuelve como resultado el valor uno, sino devuelve
cero.

modplcapcpp_msgid modplcapcpp_msg::getmsgid(void):
Extrae del mensaje, el identificador del mismo. Si esta operacin se realiz
correctamente, devuelve como resultado el valor uno, sino devuelve cero.

4.7.5. Biblioteca de bloques Simulink


Las primitivas mencionadas anteriormente resultan cmodas a quienes se encuentran
familiarizados con entornos de programacin, permitiendo desarrollar fcilmente aplicaciones
clientes por medio de la especificacin de algoritmos en lenguaje C/C++. Adems el tener
disponibles varias plataformas, entre las cuales figura Windows y Linux, permite al desarrollador de
aplicaciones clientes poder confeccionar algoritmos y probarlos con una computadora personal, sin
la necesidad de construir primero el hardware asociado a la aplicacin cliente. Pero estas ventajas
solamente son aprovechadas por quienes tiene conocimientos de programacin, excluyendo a
quienes tienen conocimientos sobre el desarrollo de aplicaciones clientes que no tengan dichos
conocimientos de programacin. Para stos ltimos se les ofrece la posibilidad de interactuar con el
modem PLC por medio de una interfaz grfica ms amigable que un conjunto de primitivas, dicha
interfaz se encuentra diseada para la aplicacin Simulink suministrada dentro del conjunto de
aplicaciones que provee MATLAB.
El entorno Simulink brinda una forma fcil y rpida de modelar sistemas de control y
evaluar su desempeo sin la necesidad de tener conocimientos de programacin. Simulink provee un
variado conjunto de bibliotecas de bloques funcionales. La interfaz desarrollada en el presente
trabajo pretende agregar a todas las funcionalidades provistas por Simulink la posibilidad de
manipular el modem PLC de tal forma que se pueda modelar una aplicacin cliente con las
funcionalidades nativas de Simulink y adems dicha aplicacin pueda hacer uso de la red PLC.
La interfaz Simulink es de gran utilidad para el desarrollo de una primera versin de una
aplicacin cliente, en la cual el inters se centra en desarrollar un modelo que cumpla con las
funcionalidades requeridas, para luego pasar a la construccin ms eficiente de ste por medio de un
algoritmo especificado mediante un lenguaje de programacin, y finalmente el desarrollo del
hardware prototipo con el firmware que implementa el algoritmo anteriormente mencionado.
Los detalles de la biblioteca de bloques funcionales Simulink referentes al manejo del
modem PLC se describen en el Apndice E.

150

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

5. Evaluacin de la solucin propuesta


La evaluacin de la solucin propuesta por el presente trabajo consiste en comparar el
sistema construido en base a los requerimientos planteados en el captulo 3, con los antecedentes
existentes sobre tecnologa PLC y redes de datos para automviles. De sta forma se puede
determinar el grado de xito logrado con la propuesta presentada, y determinar las diferencias y
similitudes que presenta sta ltima en relacin a las alternativas existentes.

5.1. Comparacin con redes PLC para automviles


Aqu se procede a evaluar la solucin propuesta frente a los antecedentes sobre redes PLC
para automviles utilizados como base para el desarrollo del prototipo propuesto por ste trabajo.
Primero se evala el funcionamiento de las distintas partes del hardware que constituye al
modem PLC; mdulo analgico y mdulo de procesamiento de seales. La evaluacin tambin
incluye las caractersticas del canal de comunicacin utilizado.
Una vez determinado el desempeo del hardware del modem PLC, se compara ste ltimo
con las soluciones propuestas por los antecedentes que tratan el tema de las redes PLC en el
ambiente de automviles.

5.1.1. Evaluacin del mdulo analgico


La primer parte que se evala del hardware constitutivo del modem PLC, es el mdulo
analgico, parte ms ligada al canal de comunicacin. La evaluacin consta de simulaciones
realizadas al mencionado mdulo (cuya implementacin se detallan en el Apndice B), y de
mediciones sobre la implementacin real (detallada en el Apndice A). Las diferencias entre
implementaciones se debe a que es necesarios cambiar algunos componentes, ya que existen
diferencias de comportamiento entre los componentes simulados y los reales.
A continuacin se describen una serie de situaciones a las cuales se somete el mdulo
analgico simulado:

Situacin 1: Seal transmitida por medio de la lnea de potencia. La seal es la resultante


de la modulacin de una seal de prueba compuesta por cinco componentes de frecuencia
de 500 KHz, 1 MHz, 1,5 MHz, 2 MHz y 2,5 MHz; que cubren el rango de frecuencias
permitido para la seal de entrada al transmisor.

Situacin 2: Espectro de la seal transmitida por medio de la lnea de potencia. Muestra el


espectro de la seal transmitida a travs de la lnea de potencia. Dicho espectro muestra
las cinco componentes de la seal de prueba replicados por emplearse modulacin VSBSC.

Situacin 3: Seal enviada y seal recibida. Muestra la seal de entrada al transmisor y la


seal recibida a la salida del receptor. Ambas seales corresponden a la seal de prueba
mencionada con anterioridad.

FernandoArielBeunza79156

151

Tesis de Grado en Ingeniera Informtica

Situacin 4: Espectro de la seal enviada y seal recibida. Muestra el espectro de la seal


de entrada al transmisor y la seal recibida a la salida del receptor. Se puede observar las
cinco componentes de frecuencia de la seal de prueba y la atenuacin de cada una de
ellas a la salida del receptor.

Situacin 5: Seal transmitida por medio de la lnea de potencia. En este caso se utiliza la
seal smbolo utilizada para transmitir informacin.

Situacin 6: Espectro de la seal transmitida por medio de la lnea de potencia. Muestra el


espectro de la seal anterior transmitida a travs de la lnea de potencia.

Situacin 7: Seal enviada y seal recibida. Muestra la seal smbolo de entrada al


transmisor y la seal smbolo recibida a la salida del receptor.

Situacin 8: Espectro de la seal enviada y seal recibida. Muestra el espectro de la seal


smbolo de entrada al transmisor y la seal smbolo recibida a la salida del receptor.

El comportamiento del mdulo analgico frente a las situaciones planteadas con anterioridad se
puede observar en los grficos que se encuentran a continuacin (en el mismo orden en el que se
enumeraron cada una de las situaciones).

152

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

153

Tesis de Grado en Ingeniera Informtica

154

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

155

Tesis de Grado en Ingeniera Informtica

156

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

157

Tesis de Grado en Ingeniera Informtica

158

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

159

Tesis de Grado en Ingeniera Informtica

160

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Los grficos anteriores muestran la respuesta en frecuencia que presenta el mdulo
analgico. Se puede destacar como regin crtica la comprendida en la proximidad a los 16 MHz,
donde el filtro presenta su mayor selectividad para poder eliminar la mayor parte de la banda
superior, como corresponde a un esquema de modulacin VSB. Para evaluar el comportamiento del
mdulo analgico implementado en la realidad, se eligen dos seales de frecuencia 138,237 KHz y
552,947 KHz, con el objeto de poder ver la respuesta en frecuencia de la regin crtica mencionada
con anterioridad. Las pruebas se realizaron con dos modems (uno designado con la letra A y el otro
con la letra B), la seal de prueba corresponde a la entrada del transmisor de uno de los modems y la
seal de respuesta corresponde a la salida del receptor del otro modem, de sta forma en la prueba
se incluyen todos los factores que pueden influenciar en la respuesta en frecuencia (ancho de banda
del transmisor y receptor, canal de comunicacin, etc.). Las seales de prueba se generaron con el
mdulo de procesamiento de seales, que implementa la funcionalidad de generar seales de
prueba.
En las figura 5.1 se puede observar la seal a la entrada del transmisor del mdulo analgico
correspondiente al modem PLC designado con la letra A (transmisor), y en la figura 5.2 se puede ver
la seal de respuesta a la salida del receptor del mdulo analgico correspondiente al modem PLC
designado con la letra B (receptor).

Figura 5.1. Portadora de 138,237 KHz transmitida


por A.

Figura 5.2. Portadora de 138,237KHz recibida por


B.

Comparando las figuras anteriores, se puede observar el filtrado a alta frecuencia, ya que como se
puede ver la seal de prueba presenta imperfecciones correspondientes a componentes de alta
frecuencia, que no se observan en la seal de respuesta. Tambin se puede observar un atenuacin
en la seal de respuesta en comparacin a la seal de prueba. Ambas seales deberan ser seales
senoidales perfectas, pero en el caso de la seal de prueba no es as debido al mtodo que se utiliza
para generarla produce ruido de alta frecuencia, y en el caso de la seal de respuesta se debe al
sistema de modulacin VSB que agrega distorsin a baja frecuencia.
Similar prueba realizada con la seal de prueba de 138,237 KHz se realiza con la seal de
552,947 KHz, cuyos resultados se reflejan en las figuras 5.3 y 5.4.

FernandoArielBeunza79156

161

Tesis de Grado en Ingeniera Informtica

Figura 5.3. Portadora de 552,947 KHz transmitida


por A.

Figura 5.4. Portadora de 552,947 KHz recibida por


B.

A diferencia de la prueba anterior, aqu se puede observa menor distorsin, y que prcticamente no
existe atenuacin, ya que la frecuencia de la seal de prueba utilizada se encuentra fuera de la regin
crtica.
A continuacin se realizan las mismas pruebas anteriores, pero intercambiando las
funcionalidades de los modems (el que anteriormente transmita ahora recibe, y el que reciba ahora
transmite). Los resultados de la prueba con una seal de 138,237 KHz se pueden observar en las
figuras 5.5 y 5.6:

Figura 5.5. Portadora de 138,237 KHz transmitida


por B.

Figura 5.6. Portadora de 138,237KHz recibida por


A.

El resultado obtenido es similar al de la prueba anterior, lo que indica que ambos transmisores y
receptores, se comportan de similar forma. Tambin se repite la prueba con la seal de 552,947
KHz, cuyo resultado se puede ver en las figuras 5.7 y 5.8.

162

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Figura 5.7. Portadora de 552,947 KHz transmitida


por B.

Figura 5.8. Portadora de 552,947 KHz recibida por


A.

En este caso tambin el resultado es similar a la prueba anterior, por lo cual se puede concluir que
ambos mdulos analgicos presentan respuesta en frecuencia similar, a pesar de las diferencias que
puede contener cada uno de ellos debido a que los componentes no son idnticos.
A partir de sta ltima conclusin, se puede elegir uno de los modems y observar la seal
que genera ste cuando transmite informacin (en este caso se utiliza una secuencia pseudoaleatoria
de bits como trama de prueba). En las figuras 5.9 y 5.10 se pueden observar la seal generada por el
modem a la entrada del mdulo analgico y la seal recibida a la salida del mismo mdulo,
respectivamente.

Figura 5.9. Seal transmitida y su espectro.

Figura 5.10. Seal recibida y su espectro.

En la figura 5.9 se puede distinguir claramente el espectro conformado por todas las portadoras
constituyentes del smbolo utilizado para transmitir la informacin cuyo ancho de banda es de
2,7648 MHz. En cambio, en la figura 5.10, producto del ruido y la atenuacin de la lnea de
potencia, no se distingue tan claramente la seal recibida, como en el caso de la figura anterior. sto
ltimo tambin se puede observar en las siguientes figuras, donde se muestra el espectro de la seal
observado en la lnea de potencia.
FernandoArielBeunza79156

163

Tesis de Grado en Ingeniera Informtica

Figura 5.11. Seal presente en la entrada de


alimentacin del modem PLC.

Figura 5.12. Seal presente en la lnea de potencia.

En la figura 5.11 se puede apreciar la misma seal de la figura 5.9 desplazada en frecuencia por el
modulador del mdulo analgico. Lo observado corresponde a la seal presente a la entrada de
alimentacin del modem PLC. La figura 5.12 corresponde a la misma seal, pero presente a una
distancia de 1,5 metros del modem. Como era de esperar, sta ltima seal se observa ms atenuada
que la primera y con una presencia de mayor nivel de ruido; pero en ambas figuras se puede
distinguir que el espectro de la seal corresponde al de una modulacin VSB-SC, donde la banda
vestigio se encuentra por encima de los 16 MHz, con un ancho de banda levemente mayor a 2,5
MHz.
Comparando las mediciones con las simulaciones, se puede observar que el comportamiento
de la implementacin real del mdulo analgico era el esperado, sin tener en cuenta el ruido y la
atenuacin que no se encontraron presentes en las simulaciones.

5.1.2. Evaluacin del mdulo de procesamiento de seales


La segunda parte que se evala del hardware constitutivo del modem PLC, es el mdulo de
procesamiento de seales; parte encargada de la modulacin y demodulacin, y del armado y
desarmado de tramas de bits. La evaluacin consta de simulaciones realizadas al mencionado
mdulo (cuya implementacin se detallan en el Apndice B), y de mediciones realizadas sobre la
implementacin real (detallada en el Apndice A). Las diferencias entre implementaciones se debe
al mismo motivo planteado cuando se trat el tema del mdulo analgico.
A continuacin se describen las situaciones a las cuales se somete el mdulo de
procesamiento de seales:

164

Situacin 1: Trama de bits transmitida y recibida. La trama de bits consta de un patrn de


bits que muestra la correcta deteccin del valor de cada bit. En dicho patrn se muestra
cambios frecuentes en el valor del bit (al comienzo de la trama) y cambios aislados (al
final de la trama). Tambin se puede observar la trama de bits obtenida a la salida del
integrador a partir de la seal obtenida del amplificador de salida.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Situacin 2: Espectro de la seal obtenida del amplificador de salida. Muestra el espectro


de la seal generada a partir de la trama de bits suministrada. Dicho espectro muestra el
rango de frecuencias ocupado por las portadoras que conforman el smbolo utilizado para
transmitir los bits de la trama.

FernandoArielBeunza79156

165

Tesis de Grado en Ingeniera Informtica

166

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

167

Tesis de Grado en Ingeniera Informtica


En los grficos anteriores se pueden observar una trama de bits asociada una la seal de
informacin generada por el mdulo de procesamiento de seales, en donde claramente se pueden
diferenciar los valores de los bits de la trama. A continuacin se muestran dos tramas de bits
generadas y recibidas por los mdulos de procesamiento de seales implementados en la realidad.
La prueba se realiza en ambos sentidos, el modem A transmitiendo y el modem B recibiendo, y
viceversa.

Figura 5.13. Trama de bits transmitida por A


recibida por B.

Figura 5.14. Trama de bits transmitida por B


recibida por A.

En las figuras 5.13 y 5.14, se pueden distinguir tambin los valores de los bits que conforman la
trama.
Los niveles de tensin bajos corresponden a bits de valor uno y los niveles de tensin altos
corresponden a bits de valor cero. Se puede observan en ambas figuras que la trama comienza en un
nivel alto correspondiente a la presencia de seal de informacin, seguido a un espacio
correspondiente a una serie de bits de valor uno, luego se ve un nuevo pico utilizado para marcar el
comienzo de una trama, seguido de un espacio previo a una secuencia de bits cero y uno, utilizada
para ajuste del umbral de deteccin, seguido de un espacio, un delimitador y finalmente la
informacin que corresponde a un byte de valor 01. Por ltimo un espacio y un pico que indica la
ausencia de seal de informacin.
En ambas figuras se puede observar que ambos mdulos de procesamiento de seales se
comportan de forma similar transmitiendo y recibiendo tramas de bits, a pesar de que los
componentes que constituyen cada uno de los mdulos no son idnticos (como ocurre con el
mdulo analgico).

5.1.3. Evaluacin del canal de comunicacin


Ya habiendo evaluado el comportamiento de los mdulos analgicos y los mdulos de
procesamiento de seales, y conociendo su comportamiento, se procede a evaluar el canal de
comunicacin utilizado, que en este caso en la red de potencia conformado bsicamente de un par
de cables comunes que se utilizan para alimentar los modems PLC, y por los cuales tambin se
transporta informacin.
La red de potencia utilizada para la realizacin de las pruebas consta de una fuente de
alimentacin que provee tensin constante de 12V, conectada a un filtro constituido por un inductor
168

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


de 2.2uH, un tramo de cable doble (positivo y negativo), uno de los modems PLC, otro tramo de
cable, y el otro modem PLC. Las pruebas consisten de observar el comportamiento de los modems
variando la ubicacin y el largo del tramo de cable que los separa. El comportamiento de los
modems se evala generando una serie de tramas de contenido y tamao aleatorio, envindolas por
uno de los modems y recibiendo la misma trama por el otro modem, y comparando la trama enviada
con la recibida; para observar la cantidad de bits que se pierden, que se reciben con error, as como
tambin las tramas que se pierden y que se reciben pero deben ser descartadas porque presentan
algn bit errado.
A continuacin se presenta la primer configuracin de red, que se puede observar en la
figura 5.15, en donde el largo del tramo de cable que une el filtro con el Modem PLC designado con
la letra A, denominado D1, es de 1,5 metros, y el tramo de cable que une el Modem PLC A con el
Modem PLC B, denominado D2, vara su longitud.

Figura 5.15. Esquema de prueba (Modem PLC A ms cerca del filtro).

Con la configuracin de la figura anterior, se realizan envos de tramas en ambos sentidos,


del modem A al B y viceversa, con diferentes longitudes de cable, y tipo de cable comn como el
utilizado para alimentacin. Los resultados pueden observarse en la tabla 5.1.

FernandoArielBeunza79156

169

Tesis de Grado en Ingeniera Informtica

D2 = 1,5 metros

D2 = 10 metros

D2 = 20 metros

D2 = 30 metros

AB

BA

AB

BA

AB

BA

AB

BA

Bits
enviados

417456

386024

402016

419864

399144

426624

388544

395672

Bits
perdidos

35440

40352

40592

47448

102840

135536

94048

53480

% Bits
perdidos

8,490%

10,453%

10,097%

11,301%

25,765%

31,769%

24,205%

13,519%

Bits
errneos

2639

3163

2048

1520

5010

5719

4655

3097

% Bits
errneos

0,632%

0,819%

0,509%

0,362%

1,255%

1,341%

1,198%

0,783%

Tramas
enviados

250

250

250

250

250

250

250

250

Tramas
perdidas

23

25

27

29

66

80

66

37

9,200%

10,000%

10,800%

11,600%

26,400%

32,000%

26,400%

14,800%

122

40

65

59

62

61

121

91

48,000%

16,000%

26,000%

23,600%

24,800%

24,400%

48,400%

36,400%

% Tramas
perdidas
Tramas
errneas
% Tramas
errneas

Tabla 5.1. Tasa de prdida y error segn el largo del cable utilizado para la configuracin propuesta en la
figura 5.15.

Se puede concluir que el comportamiento de los modems va empeorando a medida que se aumenta
la longitud del cable registrando un pico cuando se trabaja con una de longitud de 20 metros. Desde
el punto de vista del sentido de la transmisin de las tramas, existen diferencias atribuibles a que los
modems no son idnticos y dichas diferencias aumentan a medida que aumenta la longitud del
cable. En la tabla 5.2, se muestra el comportamiento promedio para cada una de las longitudes de
prueba:
D2 = 1,5 metros D2 = 10 metros D2 = 20 metros D2 = 30 metros
% Bits perdidos

9,472%

10,699%

28,767%

18,862%

% Bits errneos

0,726%

0,436%

1,298%

0,991%

% Tramas perdidas

9,600%

11,200%

29,200%

20,600%

% Tramas errneas

32,000%

24,800%

24,600%

42,400%

Tabla 5.2. Tasa promedio de prdida y error segn el largo del cable utilizado para la configuracin
para la configuracin propuesta en la figura 5.15.

El comportamiento promedio marca de igual modo que la tabla 5.1 que el desempeo de los
modems empeora con el aumento de la longitud del cable registrando un pico en 20 metros.
A continuacin se evala el comportamiento segn el tipo de cable, fijando una longitud D2
en 5 metros. Para la prueba se utiliza cable comn y cable coaxil, ste ltimo mucho ms inmune a
ruido que el primero, para ver cuanta influencia tiene el ruido en el empeoramiento anteriormente
visto.
170

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Cable comn

Cable coaxil

AB

BA

AB

BA

Bits
enviados

418552

402536

393904

397848

Bits
perdidos

77744

79136

38488

48664

% Bits
perdidos

18,575%

19,659%

9,771%

12,232%

Bits
errneos

3356

1051

4239

1549

% Bits
errneos

0,802%

0,261%

1,076%

0,389%

Tramas
enviados

250

250

250

250

Tramas
perdidas

44

49

22

32

17,600%

19,600%

8,800%

12,800%

68

53

72

61

27,200%

21,200%

28,800%

24,400%

% Tramas
perdidas
Tramas
errneas
% Tramas
errneas

Tabla 5.3. Tasa de prdida y error segn el tipo de cable utilizado para la configuracin propuesta en la
figura 5.15.

En la tabla anterior se puede observar que el ruido inducido en la lnea es un factor importante ya
que el desempeo de los modems mejora notablemente cuando el tramo de cable utilizado es coaxil.
Tambin se pueden ver diferencias segn el sentido de la transmisin, que no son demasiadas
debido a que la longitud no es muy grande, y sto responde a la expuesto anteriormente a que los
modems no son idnticos. De similar forma que se realiz en las anteriores pruebas, se obtiene el
comportamiento promedio, como se puede observar en la tabla 5.4:
Cable comn Cable coaxil
% Bits perdidos

19,117%

11,002%

% Bits errneos

0,532%

0,733%

% Tramas perdidas

18,600%

10,800%

% Tramas errneas

24,200%

26,600%

Tabla 5.4. Tasa promedio de prdida y error segn el tipo de cable utilizado para la configuracin
propuesta en la figura 5.15.

Aqu tambin de forma mucho ms clara puede observarse la mejora que existe al utilizar cable
coaxil, destacando como factor importante el ruido inducido en la lnea de potencia.
A continuacin se presenta una segunda configuracin de red, que se puede observar en la
figura 5.16, similar a la utilizada anteriormente, pero cambiando la disposicin de los modems.

FernandoArielBeunza79156

171

Tesis de Grado en Ingeniera Informtica

Figura 5.16. Esquema de prueba (Modem PLC B ms cerca del filtro).

Con sta configuracin, se realizaron envos de tramas en ambos sentidos, variando la longitud de
cable, y utilizando tipo de cable comn. Los resultados pueden observarse en la tabla 5.5 que se
detalla a continuacin:
D2 = 1,5 metros

D2 = 10 metros

D2 = 20 metros

D2 = 30 metros

AB

BA

AB

BA

AB

BA

AB

BA

Bits
enviados

401344

405976

383784

416048

367512

407312

397952

397096

Bits
perdidos

45408

32160

59848

50712

115408

118640

51960

101360

% Bits
perdidos

11,314%

7,922%

15,594%

12,189%

31,403%

29,128%

13,057%

25,525%

Bits
errneos

5183

4422

2083

2609

4057

6509

3151

3627

% Bits
errneos

1,291%

1,089%

0,543%

0,627%

1,104%

1,598%

0,792%

0,913%

Tramas
enviados

250

250

250

250

250

250

250

250

Tramas
perdidas

25

22

38

29

85

77

29

75

10,000%

8,800%

15,200%

11,600%

34,000%

30,000%

11,600%

30,000%

108

34

68

57

73

46

99

120

43,200%

13,600%

27,200%

22,800%

29,200%

18,400%

39,600%

48,000%

% Tramas
perdidas
Tramas
errneas
% Tramas
errneas

Tabla 5.5. Tasa de prdida y error segn el largo del cable utilizado para la configuracin propuesta en la
figura 5.16.

172

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


De la tabla anterior, se puede ver un similar comportamiento al observado con la configuracin
anterior, en donde el comportamiento de los modems va empeorando a medida que se aumenta la
longitud del cable, con un pico en 20 metros. Desde el punto de vista del sentido de la transmisin
de las tramas, existen diferencias atribuibles a que los modems no son idnticos, y dichas
diferencias aumentan a medida que se extiende la longitud del cable. En la tabla 5.6, se muestra el
comportamiento promedio para cada una de las longitudes de prueba.
D2 = 1,5 metros D2 = 10 metros D2 = 20 metros D2 = 30 metros
% Bits perdidos

9,618%

13,892%

30,266%

19,291%

% Bits errneos

1,190%

0,585%

1,351%

0,853%

% Tramas perdidas

9,400%

13,400%

32,000%

20,800%

% Tramas errneas

28,400%

25,000%

23,800%

43,800%

Tabla 5.6. Tasa promedio de prdida y error segn el largo del cable utilizado para la configuracin
propuesta en la figura 5.16.

El comportamiento promedio marca de igual modo que en la tabla 5.5 que el desempeo de los
modems empeora con el aumento de la longitud del cable registrando un pico en 20 metros.
A continuacin se evala el comportamiento segn el tipo de cable, fijando una longitud D2
en 5 metros. Para la prueba se utiliza cable comn y cable coaxil, para analizar la influencia del
ruido inducido en la lnea de potencia.
Cable comn

Cable coaxil

AB

BA

AB

BA

Bits
enviados

370368

407448

402912

397384

Bits
perdidos

53856

69592

43848

37704

% Bits
perdidos

14,541%

17,080%

10,883%

9,488%

Bits
errneos

1326

1405

4241

1546

% Bits
errneos

0,358%

0,345%

1,503%

0,389%

Tramas
enviados

250

250

250

250

Tramas
perdidas

40

42

30

24

16,000%

16,800%

12,000%

9,600%

65

56

71

76

26,000%

22,400%

28,400%

30,400%

% Tramas
perdidas
Tramas
errneas
% Tramas
errneas

Tabla 5.7. Tasa de prdida y error segn el tipo de cable utilizado para la configuracin propuesta en la
figura 5.16.

FernandoArielBeunza79156

173

Tesis de Grado en Ingeniera Informtica


En la tabla 5.7 se puede observar que el ruido inducido en la lnea es un factor importante ya que el
desempeo de los modems mejora notablemente cuando el tramo de cable utilizado es coaxil.
Tambin se pueden ver diferencias segn el sentido de la transmisin, que no son demasiadas
debido a la corta longitud del cable utilizado. De similar forma que se realiz en las anteriores
pruebas, se obtiene el comportamiento promedio, como se puede observar en la tabla 5.8.
Cable comn Cable coaxil
% Bits perdidos

15,811%

10,186%

% Bits errneos

0,352%

0,721%

% Tramas perdidas

16,400%

10,800%

% Tramas errneas

24,200%

29,400%

Tabla 5.8. Tasa promedio de prdida y error segn el tipo de cable utilizado para la configuracin
propuesta en la figura 5.16.

35,000%

1,600%

30,000%

1,400%

25,000%

1,200%

20,000%

Bits errneos

Bits perdidos

Aqu, de forma mucho ms clara, puede observarse la mejora que existe al utilizar cable coaxil,
destacando tambin como factor importante el ruido inducido en la lnea de potencia.
Luego de realizadas todas las pruebas para las dos configuraciones propuestas, se pueden
comparar los resultados obtenidos y determinar el comportamiento general de los modems
evaluados. Para determinar el comportamiento se tiene en cuenta el porcentaje de bits perdidos (por
prdida de tramas), de bits errneos, de tramas perdidas y de tramas errneas (que deben ser
descartas por presentar algn bit errado). En las figuras 5.17 y 5.18, se muestran las tasas promedio
de perdida de bits y de bits errneos en funcin de la longitud de cable utilizado.

15,000%
10,000%
5,000%

1,000%
0,800%
0,600%
0,400%
0,200%

0,000%

0,000%
0

10

15

Metros
AB

BA

20

25

30

35

10

15

20

25

30

35

Metros
AB

BA

Figura 5.17. Tasa promedio de bits perdidos segn Figura 5.18. Tasa promedio de bits errneos segn
longitud del cable y disposicin de los modems
longitud del cable y disposicin de los modems PLC.
PLC.

Se puede observar en la figura 5.17 que la tasa de prdida de bits se incrementa con la longitud de
cable con la particularidad de haber un pico en 20 metros. En la figura 5.18 se puede ver un tambin
un pico en 1,5 metros, debido a que el ruido inducido no provoca demasiada prdida de tramas
(como se observa en la figura 5.17), pero si altera el valor de los bits recibidos, lo que se traduce en
el aumento de la tasa de bits errneos. Luego la curva del grfico de la figura 5.18 coincide con la
tendencia mostrada en el grfico de la figura 5.17.

174

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


A continuacin se realiza el mismo anlisis, pero esta vez se toman en cuenta el porcentaje
de tramas perdidas y errneas. A diferencia de los bits, en el caso de las tramas slo basta un bit
errneo para descartar una trama completa (lo que hace la capa de enlace). Entonces los grficos de
las figuras 5.19 y 5.20, reflejan que tan buenos son los modems transmitiendo informacin, sin tener
en cuenta ningn mtodo que puede mejorar el desempeo de los mismos (como por ejemplo la
fragmentacin de la informacin enviada, etc.).

35,000%

50,000%
45,000%
40,000%

25,000%

Tramas errneas

Tramas perdidas

30,000%

20,000%
15,000%
10,000%
5,000%

35,000%
30,000%
25,000%
20,000%
15,000%
10,000%
5,000%

0,000%

0,000%
0

10

15

20

25

30

35

Metros
AB

BA

Figura 5.19. Tasa promedio de tramas perdidas


segn longitud del cable y disposicin de los
modems PLC.

10

15

20

25

30

35

Metros
AB

BA

Figura 5.20. Tasa promedio de tramas errneas


segn longitud del cable y disposicin de los
modems PLC.

El grfico de la figura 5.19 es similar al de la figura 5.17 que trata sobre la tasa de bits perdidos.
sto se debe a que cuando se pierde una trama, se pierden todos los bits de ella, por lo cual es de
esperar un comportamiento similar reflejado en los grficos. En cambio, en el grfico de la figura
5.20, se puede observar que la tasa de prdida de tramas se mantiene por debajo del 35% hasta los
20 metros de longitud del cable y luego aumenta. ste comportamiento se debe a varios motivos:
primero, con longitudes bajas (menos de 10 metros), el comportamiento es relativamente bueno;
segundo, superando los 10 metros hasta los 20 metros, es donde hay mucha prdida de tramas por lo
cual no se puede determinar si presentaban algn error (la trama perdida no se cuenta como
errnea); y tercero, con ms de 20 metros es de esperar la prdida de tramas por la longitud por
ruido inducido en la lnea de potencia que corrompe los bits de la tramas. Si se sumaran las tasas de
tramas prdidas con las errneas, que corresponde al ambiente sobre el cual trabaja la capa de
enlace (esta capa no tiene en cuenta si la trama se perdi o es errnea, en ambos casos pide
retransmisin de la misma), en el mejor escenario, la tasa de prdida es superior al 30%.
Una vez comparados los resultados obtenidos en funcin de la longitud del cable, se puede
realizar el mismo anlisis comparativo modificando el tipo de cable utilizado. En este caso, se
toman los mismos parmetros utilizados en la comparacin anterior (porcentaje de bits perdidos, de
bits errneos, de tramas perdidas y tramas errneas). En las figuras 5.21 y 5.22, se muestran las
tasas promedio de perdida de bits y de bits errneos en funcin del tipo de cable utilizado.

FernandoArielBeunza79156

175

Tesis de Grado en Ingeniera Informtica

0,800%

25,000%

0,700%
0,600%

Bits errneos

Bits perdidos

20,000%
15,000%
10,000%
5,000%

0,500%
0,400%
0,300%
0,200%
0,100%
0,000%

0,000%
cable comn

cable comn

cable coaxil

AB

cable coaxil

Tipo de cable

Tipo de cable

AB

BA

Figura 5.21. Tasa promedio de bits perdidos segn


tipo de cable y disposicin de los modems PLC.

BA

Figura 5.22. Tasa promedio de bits errneos segn


tipo de cable y disposicin de los modems PLC.

Observando los grficos anteriores se puede concluir que las diferencias entre los resultados
obtenidos en las dos configuraciones de prueba utilizadas son mayores cuando se utiliza cable
comn, dado que las pruebas son ms propensas a ser influidas por el ruido inducido en el cable
utilizado. En el caso particular de la tasa de bits perdidos, se puede decir que el cable coaxil
disminuye la prdida de bits; pero si se observa la tasa de bits errados, la cantidad de bits errneos
es mayor comparada a la obtenida con cable comn. sto se debe a que los bits perdidos no son
considerados como errneos, y que al haber menos prdida aumenta la probabilidad de error. Se
puede concluir que el ruido inducido sobre la lnea de potencia afecta ms al proceso de deteccin
de la trama, que a la informacin contenida en ella.
A continuacin se realiza un anlisis similar al anterior, pero trabajando con tramas y no con
bits. Los resultados analizados se puede observar en las figuras 5.23 y 5.24.

20,000%

35,000%
30,000%

16,000%

Tramas errneas

Tramas perdidas

18,000%
14,000%
12,000%
10,000%
8,000%
6,000%
4,000%

20,000%
15,000%
10,000%
5,000%

2,000%
0,000%

0,000%
cable comn

cable coaxil

Tipo de cable
AB

BA

Figura 5.23. Tasa promedio de tramas perdidas


segn tipo de cable y disposicin de los modems
PLC.

176

25,000%

cable comn

cable coaxil

Tipo de cable
AB

BA

Figura 5.24. Tasa promedio de tramas errneas


segn tipo de cable y disposicin de los modems
PLC.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Lo observado en los anteriores grficos reafirma la conclusin enunciada anteriormente. Aqu se ve
con ms claridad que el ruido inducido en el cableado afecta ms a la deteccin de tramas que a la
deteccin de la informacin contenida en ellas. En la figura 5.23 se puede ver la mejora que
presenta el cable coaxil frente al cable comn, pero no se aprecia mejora en la figura 5.24, en donde
el descarte de tramas por presentar bits errneos no mejora con la calidad del cable.
Para finalizar con el anlisis comparativo se puede obtener el comportamiento promedio
entre las dos configuraciones de prueba utilizadas y tener una idea general de desempeo de los
modems. En la tabla 5.9 se muestran los porcentajes promedio de bits perdidos y errneos, y de
tramas perdidas y errneas.
1,5 metros 10 metros 20 metros 30 metros
% Bits perdidos

9,545%

12,295%

29,516%

19,077%

% Bits errneos

0,958%

0,510%

1,325%

0,922%

% Tramas perdidas

9,500%

12,300%

30,600%

20,700%

% Tramas errneas

30,200%

24,900%

24,200%

43,100%

Tabla 5.9. Tasa promedio de prdida y error segn el largo del cable.

35,000%

1,400%

30,000%

1,200%

25,000%

1,000%

Bits errneos

Bits perdidos

En general se puede decir que ms all de donde se ubiquen los modems el comportamiento
empeora a medida que la longitud del cable entre ellos aumenta, existiendo un pico en el caso de los
20 metros. Los mismos valores pueden verse de otra forma por medio de las figuras 5.25, 5.26, 5.27
y 5.28.

20,000%
15,000%

0,800%
0,600%

10,000%

0,400%

5,000%

0,200%

0,000%

0,000%
0

10

15

20

25

30

35

Metros

Figura 5.25. Tasa promedio de bits perdidos segn


longitud del cable.

FernandoArielBeunza79156

10

15

20

25

30

35

Metros

Figura 5.26. Tasa promedio de bits errneos segn


longitud del cable.

177

Tesis de Grado en Ingeniera Informtica

35,000%

50,000%
45,000%

Tramas erroneas

Tramas perdidas

30,000%
25,000%
20,000%
15,000%

40,000%
35,000%
30,000%
25,000%
20,000%
15,000%

10,000%

10,000%
5,000%

5,000%
0,000%

0,000%
0

10

15

20

25

30

35

10

15

20

25

30

35

Metros

Metros

Figura 5.27. Tasa promedio de tramas perdidas


segn longitud del cable.

Figura 5.28. Tasa promedio de tramas errneas


segn longitud del cable.

Como en los anlisis comparativos anteriores su pudo observar que las tasas promedio eran
similares independientemente de la configuracin de prueba utilizada, los grficos que se pueden
observar aqu reflejan la misma idea, en donde el desempeo desmejora con el aumento de la
longitud de cable, con un pico de peor desempeo en 20 metros, y se tienen en cuenta las tramas
perdidas y las errneas, se observa que la prdida de tramas por alguno de los dos motivos es
superior al 40%.
Cable comn Cable coaxil
% Bits perdidos

17,464%

10,594%

% Bits errneos

0,442%

0,727%

% Tramas perdidas

17,500%

10,800%

% Tramas errneas

24,200%

28,000%

Tabla 5.10. Tasa promedio de prdida y error segn el tipo de cable.


Con referencia al tipo de cable utilizado, la tasa de perdidas mejora con la calidad del cable,
pero empeora la tasa de error debido a que al ser recibidos ms bits aumenta las probabilidades de
ocurrencia de error.

5.1.4. Comparacin con DC-BUS


El diseo de DC-BUS provee una serie de funcionalidades de comunicaciones que
corresponden a las capas fsica y de enlace del modelo OSI. DC-BUS est orientado a ofrecer un
puente entre redes CAN y el medio fsico de comunicacin provisto por las lneas de potencia. De
sta forma dispositivos existentes compatibles con CAN pueden comunicarse por medio de la lnea
de alimentacin de un automvil por medio de DC-BUS. En cambio, la solucin propuesta en ste
trabajo va ms all de implementar una interfaz fsica, sino que aborda toda la problemtica de las
comunicaciones, implementando las siete capas del modelo OSI.

178

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Tanto en DC-BUS como en la solucin propuesta, el medio fsico utilizado como canal de
comunicacin son las lneas de potencia. Las diferencias se encuentran tcnicas de codificacin de
los bits de datos. DC-BUS codifica los bits empleando dos portadoras, para brindar robustez en las
comunicaciones, sin demasiadas complejidad de implementacin. La solucin propuesta emplea
otra tcnica que permite, de forma no mucho ms costosa, utilizar 19 portadoras moduladas en
DBPSK, lo que otorga mayor robustez que la ofrecida por DC-BUS. La desventaja que presenta ste
ltimo mtodo frente al propuesto por DC-BUS es que ocupa mayor ancho de banda, que no permite
ofrecer diversos tipos de comunicaciones como los ofrece DC-BUS.
La topologa de red empleada por DC-BUS y la solucin propuesta, son idnticas ya que
ambas alternativas trabajan sobre la red de alimentacin presente en un automvil.
El mtodo de control de acceso al medio utilizado por DC-BUS se encuentra preparado para
ser compatible con CAN. Se trata de un protocolo de la familia CSMA, que permite la resolucin de
colisiones por medio de un mecanismo especialmente diseado para funcionar con las
caractersticas de DC-BUS (no tiene la capacidad de deteccin de colisiones). La solucin propuesta
en el presente trabajo, trabaja con una versin del protocolo CSMA/CA mejorado, que se basa en
evitar las colisiones, ya que tambin existe el problema de no poder detectar colisiones. ste
problema se encuentra en las dos alternativas debido a que ambos diseos no son capaces de
transmitir y escuchar en forma simultnea, por razones de complejidad de implementacin.
DC-BUS tiene la capacidad de brindar tres tipos de comunicaciones orientadas a tres tipos de
aplicaciones. Brinda soporte para comunicaciones de baja velocidad utilizadas por aplicaciones de
mecatrnica y uso general, comunicaciones de velocidad media requeridas por aplicaciones de
telemtica, y comunicaciones de alta velocidad destinadas a aplicaciones de multimedia. sto se
debe a lo explicado anteriormente sobre el modo de emplear el medio fsico, la simpleza en la forma
de codificar la informacin y el ancho de banda utilizado, permiten implementar varios canales de
comunicacin para diferentes tipos de comunicaciones. En cambio la solucin propuesta, por
cuestiones de complejidad y ancho de banda utilizado, solamente puede brindar soporte a un solo
tipo de comunicaciones que puede ser utilizado por aplicaciones generales o telemtica (velocidad
de transferencia media a baja).

5.1.5. Comparacin con los trabajos sobre PLC en la industria


automotriz
Los trabajos realizados por la Facultad de Ingeniera Elctrica de la Universidad Tcnica
Checa de Praga no implementan un sistema de comunicacin comercial, sino que centran su
esfuerzo en realizar un estudio sobre las lneas de potencia como un medio para transporte de datos,
y propone un prototipo. sto si se tuviera que comparar frente al modelo de capas de OSI, se podra
decir que los trabajos anteriores alcanzan solamente a la capa fsica. La propuesta del presente
trabajo es ms evolucionada ya que toma como punto de partida el desarrollo de los anteriores
trabajos y desarrolla las siete capas del modelo OSI, creando un prototipo ms funcional.
En cuanto a lo referente al medio fsico, la topologa de red utilizada y capacidades, ambas
propuestas son similares, ya que el presente trabajo ha sido inspirado por los trabajos anteriores.
Existen algunas diferencias como el rango de frecuencias utilizado; la propuesta de la Facultad de
Ingeniera Elctrica utiliza el rango comprendido entre 4 y 16 MHz, mientras que la solucin de
ste trabajo trabaja en el rango comprendido aproximadamente entre 12 y 16 MHz. Otra diferencia
se relaciona con la implementacin de los prototipos, la propuesta de los trabajos de la Facultad de
Ingeniera Elctrica utiliza componentes de tecnologa superior a la empleada en la propuesta del
presente trabajo. A pesar de sto ltimo, las prestaciones son similares; por ejemplo, la propuesta de
FernandoArielBeunza79156

179

Tesis de Grado en Ingeniera Informtica


la Facultad de Ingeniera Elctrica sintetiza directamente la seal smbolo con portadoras dentro
del rango entre los 4 a 16 MHz, mientras que las solucin de ste trabajo sintetiza la seal smbolo
en baja frecuencia (por debajo de los 3 MHz), y luego traslada la seal sintetizada por medio de un
convertidor de frecuencias al rango comprendido entre 12 y 16 MHz (aproximadamente).

5.2. Comparacin con redes existentes para


automviles
Luego de comparar la solucin propuesta por ste trabajo frente a las propuestas ofrecidas
por las alternativas referentes a comunicaciones PLC para automviles, se realizan comparaciones
frente a las redes de datos utilizadas en automviles en la actualidad. Para dichas comparaciones
toman como referentes a las redes de datos para automviles analizadas en el captulo 2.

5.2.1. Comparacin con CAN


El modelo de capas propuesto por CAN se compone de la capa fsica y la capa de enlace, lo
que le permite resolver los problemas bsicos de la comunicacin entre los dispositivos presentes en
un automvil. La solucin propuesta por ste trabajo, adems de implementar las capas fsica y de
enlace, implementa las restantes, siguiendo el modelo de capas propuesto por OSI. sto permite la
implementacin de redes lgicas, transporte confiable de datos por medio de las anteriores, manejo
de sesiones, estructurado de los datos transportados, e implementacin de una interfaz de
aplicacin; lo que permite facilitar la implementacin de los dispositivos clientes. En cambio,
cuando se trabaja con redes CAN, la implementacin de las funciones mencionadas anteriormente es
responsabilidad del dispositivo que hace uso de CAN, lo que hace su implementacin ms compleja,
o bien algunas de las funcionalidades no son implementadas.
La capa fsica de CAN no especifica un medio fsico particular, lo que permite a stas redes
poder expandir sus capacidades segn los avances tecnolgicos, sin realizar cambios de
implementacin. La propuesta de ste trabajo, a diferencia de CAN, se encuentra estrechamente
relacionada al medio fsico utilizado (lneas de potencia), ya que la capa fsica se encuentra diseada
especficamente para resolver todos los problemas relacionados con el medio fsico utilizado. La
consecuencia de sto es que si se desea trasladar la solucin propuesta a una nueva tecnologa que
haga uso de otro medio fsico, o haga uso del mismo medio fsico pero de forma ms eficiente, se
debe modificar la implementacin de la capa fsica.
La topologa empleada por CAN es tipo lineal, un cableado que recorre el automvil
interconectando cada uno de los dispositivos presentes en ste, con el inconveniente de que un dao
en el cableado fragmente la red, impidiendo la comunicacin entre dispositivos encontrados en
fragmentos distintos. La ventaja de la utilizacin de las lneas de potencia, es que la topologa de la
red de alimentacin del automvil es hbrida, permitiendo la combinacin de topologas tipo estrella
y tipo lineal, dando libertad de configuracin de la red para evitar o minimizar las posibilidades de
que se fragmente la red por rotura de un tramo del cableado.
El mtodo de acceso al medio utilizado por CAN permite un esquema multimaestro, en
donde todos los dispositivos tiene la capacidad de enviar mensajes a otros. sto ltimo abre la
posibilidad a la ocurrencia de colisiones que son resueltas por el protocolo CSMA/CR, en base a la
prioridad de los mensajes, de forma determinstica. La solucin propuesta por sus caractersticas no
es capaz de implementar un protocolo como el utilizado por CAN, pero implementa una versin
180

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


similar derivada del CSMA/CA, diseada para evitar las colisiones de mensajes, con el agregado de
un esquema de prioridades. El protocolo no resulta ser determinstico, pero el esquema de
prioridades introduce mejoras respecto a ste tema, comparado con la versin original CSMA/CA.
La independencia de CAN sobre el medio fsico, permite la implementacin de redes con
diversas capacidades. Pueden configurarse redes extensas para interconectar dispositivos que
requieran comunicaciones de baja velocidad de transferencia, o bien redes de longitud limitada pero
que permitan altas velocidades de transferencia de datos para aplicaciones crticas. Las tramas
utilizadas por CAN para el transporte de datos presentan una capacidad limitada de 8 bytes,
suficiente para las aplicaciones a las que se orienta este tipo de red. La propuesta de ste trabajo,
solamente brinda soporte de comunicaciones a aplicaciones de uso general y de telemtica
(velocidades de transferencia baja y media), y para expandir las capacidades se requiere de
modificaciones a la implementacin de la capa fsica. Como ventaja sobre CAN, la solucin
propuesta emplea tramas que pueden contener hasta 1024 bytes, ya que se encuentran orientadas a
aplicaciones generales.

5.2.2. Comparacin con J1850


El estndar J1850 implementa las capas fsica y de enlace como CAN, con el agregado de
una capa de aplicacin, lo que solamente le permite brindar los servicios bsicos de comunicacin
entre los dispositivos presentes en un automvil, y diagnstico de los mismos. Las observaciones
realizadas en la comparacin con respecto a la solucin propuesta por ste trabajo, son similares a
las realizadas a CAN, con la diferencia que en ste caso se incorpora una capa de aplicacin.
La capa fsica de J1850 define dos alternativas de cableado elctrico, una emplea un slo
cable (J1850 VPW), y la otra dos cables (J1850 PWM). Para el caso de la propuesta del presente
trabajo solamente se dispone de una sola variante. En ambas soluciones se puede apreciar la
dependencia del diseo de la capa fsica con respecto al medio utilizado, lo que hace que un cambio
tecnolgico sobre el medio fsico provoque un cambio en la implementacin de la capa fsica.
La topologa empleada por J1850 es del tipo lineal, como en el caso de CAN. sta
configuracin presenta las mismas desventajas con respecto a la propuesta de ste trabajo sealadas
anteriormente, cuando se realiz la comparacin con CAN.
El mtodo de acceso al medio utilizado por J1850 implementa un esquema multimaestro,
con alguna similitud con el que emplea CAN, en donde todos los dispositivos tiene la capacidad de
enviar mensajes. La consecuencia natural de sto ltimo es la posibilidad a la ocurrencia de
colisiones que son resueltas por el protocolo CSMA/CR, en base a la prioridad de los mensajes, de
forma determinstica. La solucin propuesta por sus caractersticas no es capaz de implementar un
protocolo como el utilizado por J1850, pero implementa una versin mejorada del protocolo
CSMA/CA.
Las redes J1850 se encuentras preparadas para dar soporte a aplicaciones generales que
requieren de velocidades de transferencia bajas. Aunque J1850 ofrece dos alternativas, ambas se
encuentran por debajo de los 100 kbps, lo que ofrece una capacidad bastante limitada. Las tramas
utilizadas por J1850 para el transporte de datos pueden tener hasta 12 bytes (incluyendo
informacin de control), suficiente para las aplicaciones a las que se orienta este tipo de red. La
solucin propuesta por el presente trabajo, brinda soporte de comunicaciones a aplicaciones de uso
general y de telemtica (velocidades de transferencia baja y media), por lo cual trabaja con tramas
que pueden contener hasta 1024 bytes, ya que se encuentran orientadas a aplicaciones generales.

FernandoArielBeunza79156

181

Tesis de Grado en Ingeniera Informtica

5.2.3. Comparacin con OSEK/VDX


La propuesta OSEK/VDX es independiente de los sistemas de comunicaciones utilizados por
los dispositivos. Fue diseado con el objetivo de proveer una plataforma comn de desarrollo de
software para los dispositivos, para independizar los aspectos del hardware de comunicacin de las
aplicaciones de los dispositivos. Siguiendo el modelo de capas propuesto por OSI, puede decirse
que las capas fsica y de enlace corresponden al sistema de comunicacin sobre el cual trabaja
OSEK/VDX, mientras que OSEK/VDX implementa la capa de red y la interfaz de aplicacin (capa
de aplicacin). ste estndar pretende implementar las capas no implementadas por CAN y J1850,
aunque no implementa las siete del modelo OSI. La solucin de ste trabajo adems de incluir las
capas fsica y de enlace, tambin implementa las de transporte, sesin y presentacin; lo que la hace
ms compleja que OSEK/VDX.
Con respecto al medio fsico, topologa de red y capacidades; ests dependen del estndar de
comunicacin sobre el cual se implemente OSEK/VDX, lo que no ocurre con la solucin propuesta
por el presente trabajo (porque define la capa fsica y de enlace).

5.2.4. Comparacin con LIN


El objetivo de LIN es proveer un sistema de comunicacin entre dispositivos a bajo costo,
por lo cual se hace necesario reducir la complejidad de la implementacin de los dispositivos. Por
sta razn LIN solamente implementa dos de las siete capas propuestas por el modelo OSI, que son
la capa fsica y la capa de enlace. La solucin propuesta por ste trabajo se encuentra orientada a
ofrecer una alternativa con mayor funcionalidad que la provistas por otro tipo de redes como CAN o
J1850, ms complejas que LIN, por eso implementa las siete capas del modelo OSI. Se debe
recordar que LIN trabaja junto a CAN y J1850, de forma tal que LIN permite interconectar
dispositivos cercanos entre s de baja complejidad, y CAN y J1850 se emplean como red de
interconexin entre las diferentes redes LIN que pueden existir en un automvil. En stos momentos
la complejidad de las comunicaciones PLC hace dificultoso trasladarlas a dispositivos de baja
complejidad.
La capa fsica implementada por LIN trabaja utilizando como medio fsico un slo cable que
permite interconectar dispositivos de forma simple y econmica. La solucin propuesta por ste
trabajo, aprovecha las lneas de alimentacin del automvil, lo que hace a ste medio fsico tambin
una alternativa simple y econmica (ya que se aprovecha algo existente).
La topologa de red adoptada por LIN es del tipo lineal, como CAN y J1850, con los mismos
inconvenientes frente a la solucin propuesta que propone una topologa hbrida.
Las redes LIN trabajan bajo un esquema de maestro/esclavo, a diferencia de la solucin
propuesto que presenta un esquema multimaestro. De esta forma, LIN controla el acceso al medio
de forma simple y eficaz, eliminando la posibilidad de colisiones de mensajes, como ocurre con la
solucin propuesta por el presente trabajo. La desventaja del esquema utilizado por LIN, es que el
dispositivo maestro es un dispositivo nico, que en caso de falla, deja de funcionar la red completa,
lo que no sucede con un esquema multimaestro.
LIN se encuentra destinada a dar soporte de comunicaciones a aplicaciones generales que
requieren de bajas velocidades de transferencia, ofreciendo diversas opciones de velocidad. En
cambio la solucin propuesta en ste trabajo ofrece una nica opcin de velocidad de rango medio
porque est orientado a un ambiente de trabajo diferente.

182

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

5.2.5. Comparacin con D2B


El estndar de comunicacin D2B se encuentra diseado para ofrecer servicios de
transmisin de datos a alta velocidad para aplicaciones de multimedia en automviles. ste
estndar, al igual que otros, implementa las capas fsica y de enlace propuestas por el modelo OSI;
dejando sin resolver algunas cuestiones del proceso de comunicacin que deben ser resueltas por los
dispositivos que hacen uso de D2B, a diferencia de la propuesta del presente trabajo que opta por
implementar todas las capas del modelo OSI para no incrementar la implementacin de los
dispositivos clientes.
La caracterstica que diferencia D2B del resto de las redes es que introduce como medio
fsico para transmisin de datos la fibra ptica. La capa fsica implementa una red de fibra ptica
dedicada al transporte de datos y una red cableada para seales de control. La utilizacin de fibra
ptica permite trabajar con altas velocidades de transferencia requeridas por las aplicaciones
multimedia gracias a su inmunidad al ruido electromagntico, a diferencia de la solucin propuesta
por el presente trabajo que encuentra limitada su capacidad, y destina muchos recursos, en brindar
un servicio de comunicacin por medio de la red de alimentacin de un automvil, caracterizada por
la gran presencia de ruido electromagntico. La capa fsica, tanto en D2B como en la solucin
propuesta son dependientes del medio fsico, por lo cual un cambio en ste ltimo implica una
modificacin en la implementacin de la capa fsica.
La topologa de red que presenta D2B es muy particular, ya que dispone de un canal ptico y
un canal elctrico, cada uno con una topologa distinta. La red de fibra ptica presenta una topologa
tipo anillo, mientras que la red elctrica adopta una topologa tipo estrella. sta configuracin de red
no ofrece el grado de libertad que presenta la red de alimentacin de un automvil, medio utilizado
para la propuesta de ste trabajo. La topologa tipo anillo de D2B requiere de un dispositivo con
funciones de maestro, lo cual hace de sto su punto de debilidad ante fallas; algo que no ocurre en
un esquema multimaestro como el implementado en la solucin propuesta por ste trabajo.
El control de acceso al medio provisto por D2B consiste en el mtodo de paso de testigo, el
cual asegura un tiempo determinstico y un canal libre de colisiones. En cambio, la propuesta del
presente trabajo emplea un protocolo CSMA/CA mejorado que no asegura tiempo determinstico ni
un canal libre de colisiones (solamente las evita). Por las caractersticas de D2B, resulta
relativamente sencillo implementar un esquema de paso de testigo ya que aprovecha la existencia de
un dispositivo maestro que ejerce el rol de supervisor de red, lo que no ocurre en un esquema
multimaestro. El inconveniente del mtodo de paso de testigo es que ante la falla del dispositivo
maestro, el resto de los dispositivos no pueden comunicarse entre s, lo que no sucede en un
esquema multimaestro.
Las capacidad de transferencia de datos que presenta D2B es muy superior a la propuesta de
ste trabajo, ya que la fibra ptica permite comunicaciones de alta velocidad, lo que no ocurre con
las lneas de potencia. A pesar de sto, la fibra ptica es un medio fsico bastante delicado por lo
cual las redes D2B estn pensadas para interconectar dispositivos presentes dentro del habitculo de
pasajeros del automvil, a diferencia de las lneas de potencia que se encuentran presentes en todas
las partes del automvil. Por sta razn, D2B resulta se adecuada para aplicaciones multimedia ya
que stas residen dentro del habitculo de pasajeros del automvil; a diferencia de otro tipo de
aplicaciones que no necesitan altas velocidades de transferencia, pero se encuentran en todas partes
del automvil, y en ste ltimo caso resulta ms adecuado lo que ofrece la propuesta del presente
trabajo.

FernandoArielBeunza79156

183

Tesis de Grado en Ingeniera Informtica

5.2.6. Comparacin con MOST


El estndar MOST es una mejora con respecto a D2B, estudiado anteriormente; aunque
conserva muchas similitudes. MOST se encuentra diseado para ofrecer comunicaciones de alta
velocidad para aplicaciones de multimedia en automviles. ste estndar se encuentra constituido
por tres capas: capa fsica, capa de red y capa de aplicacin; siendo la capa de red equivalente a las
capas de enlace, red y transporte del modelo OSI. A pesar de ser un estndar que implementa ms
funcionalidades no implementa la capa de presentacin, a diferencia de la solucin propuesta en ste
trabajo que implementa las siete capas del modelo OSI.
La capa fsica de MOST est pensada para funcionar utilizando como medio fsico tanto
cableado elctrico como ptico (mejora respecto de D2B). La fibra ptica utilizada es de mejor
calidad a la empleada en D2B, lo que permite mayores longitudes y capacidades de transferencia. Al
igual que D2B, MOST tambin trabaja con una red de cableado ptico y cableado elctrico. La
propuesta de ste trabajo implementa una capa fsica dependiente del medio fsico utilizado (lneas
de potencia), a diferencia de MOST. Con respecto a las ventajas de la fibra ptica sobre las lneas de
potencia, son las mismas que las detalladas en la comparacin con D2B.
La topologa de red que presenta MOST es muy similar a la que posee D2B. La red de fibra
ptica adopta una topologa tipo anillo, mientras que la red de cableado elctrico presenta una
topologa tipo estrella. Al igual que en D2B, en MOST existe un dispositivo maestro, con todas las
ventajas y desventajas que tiene ste ltimo. Con respecto a la propuesta del presente trabajo, las
observaciones son similares a las realizadas con referencia a D2B, la topologa de la red de
alimentacin y el esquema multimaestro, presenta menos lmites que la propuesta de D2B y MOST.
El control de acceso al medio implementado por MOST tambin consiste en el mtodo de
paso de testigo, como el empleado por D2B. El tiempo determinsitco y comunicaciones libre de
colisiones son sus puntos a favor frente al protocolo implementado por la propuesta de ste trabajo,
mientras que el esquema maestro/esclavo es el punto en contra.
La capacidad de transferencia de datos de MOST supera al mismo D2B gracias a la mejora
en la calidad de la fibra ptica utilizada. A pesar de que la red puede ser ms extensa, por la calidad
de la fibra ptica, no es adecuada para cualquier lugar dentro del automvil as que sigue reservada
a uso dentro del habitculo de pasajeros del automvil para la interconexin de los distintos
dispositivos multimedia que pueden existir. Adems de la velocidad, MOST supera a la propuesta
de ste trabajo, en la cantidad de bytes que puede transportar una trama, ya que las tramas MOST
pueden contener hasta 1524 bytes, mayor a los 1024 bytes ofrecidos por la solucin propuesta de
ste trabajo. Tambin MOST ofrece diversas formas de transporte de datos que pueden ser: paquetes
de datos de control, paquetes de datos comunes y flujos de datos; de sta forma se pueden
transportar datos entre los distintos dispositivos, y flujos de datos correspondientes a audio y video.
La propuesta de ste trabajo slo se limita a brindar un servicio de transporte de datos por medio de
paquetes, ya que sta orientado a aplicaciones generales y no de multimedia.

5.2.7. Comparacin con FlexRay


Las redes FlexRay fueron pensadas para aplicaciones crticas que requieren comunicaciones
de alta velocidad. La idea de ste estndar es presentar una evolucin a redes CAN de alta velocidad.
FlexRay, como muchos otros estndares, implementan las dos primeras capas del modelo OSI,
denominadas capa fsica y capa lgica (equivalentes a las capas fsica y de enlace), y de sta forma
brinda los servicios bsicos de comunicacin entre dispositivos. La solucin propuesta por el

184

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


presente trabajo se orienta ms a ofrecer servicios de comunicacin ms avanzados sobre el alto
desempeo que ofrece FlexRay.
La capa fsica de FlexRay utiliza un medio fsico que permite a un bajo costo, comparado
con soluciones que emplean fibra ptica, comunicaciones confiables de alta velocidad. El medio
fsico empleado es cable par trenzado sin blindaje, ms inmune al ruido electromagntico que el
cableado elctrico utilizado para alimentacin, utilizado por la propuesta de ste trabajo. sto
determina las diferencias de capacidades que existen entre FlexRay y la solucin propuesta por ste
trabajo. En ambos casos la capa fsica es dependiente del medio fsico, por lo cual una evolucin
tecnolgica de ste ltimo debe ir acompaado de una evolucin de la implementacin de la capa
fsica.
Los dispositivos compatibles con FlexRay presenta una particularidad nica con respecto a
los otros estndares analizados en ste trabajo, stos pueden conectarse a dos cableados diferentes.
De sta manera FlexRay brinda dos canales de comunicacin que pueden ser utilizados en
simultneo por los dispositivos, aumentando la velocidad y confiabilidad de las comunicaciones.
sta caracterstica permite que las redes FlexRay puedan implementar diversas topologas, pueden
configurarse redes con topologa lineal, estrella o combinacin de ambas, respetando algunas
restricciones impuestas por el estndar. De sta forma FlexRay se asemeja a la solucin propuesta
por el presente trabajo, en cuanto a los beneficios que presentan las topologas hbridas.
En cuanto al control de acceso al medio, FlexRay implementa ciclos de tiempo de recurrente
compuesto por un segmento esttico y uno dinmico. El segmento esttico se compone de ranuras
de tiempo de longitud fija, cada una asignada un identificador de trama y a un determinado nodo,
no existiendo posibilidad de colisiones. El segmento dinmico se compone de ranuras de longitud
variable y su uso se determina en base a la prioridad de la trama a enviar, para resolver las
colisiones. De sta forma FlexRay ofrece un control mixto de acceso al medio, uno libre de
colisiones y otro con resolucin de colisiones en base a prioridad, en comparacin a la solucin
propuesta por ste trabajo que slo ofrece un esquema CSMA/CA mejorado, que tambin se basa en
la prioridad.
En cuanto a las capacidades, FlexRay es notablemente superior a la propuesta de ste trabajo
ya que puede alcanzar hasta 10 Mbps de velocidad de transferencia, frente a los aproximados 140
Kbps ofrecidos por la solucin propuesta. FlexRay est destinado a dispositivos de aplicaciones
crticas que requieren de velocidades altas de transferencia para funcionar de forma adecuada, en
cambio la propuesta del presente trabajo est orientado a aplicaciones generales y telemtica que
trabajan con velocidades bajas a medias. Respecto al tamao de las tramas, FlexRay trabaja con
tramas que pueden alcanzar hasta 262 bytes, mucho mejor que otro tipo de redes como CAN y
J1850; aunque no supera a la capacidad de transporte ofrecida por la propuesta de este trabajo de
1024 bytes.

5.3. Caractersticas particulares de la solucin


propuesta
Con anterioridad se han analizado los puntos en comn que presenta la solucin propuesta
por el presente trabajo y otras alternativas aplicadas en automviles. Se determinaron las ventajas y
desventajas de la solucin propuesta frente a las otras alternativas, pero quedaron pendientes de
estudio ciertas particularidades que ofrece la solucin propuesta y no las alternativas.
La primer particularidad, vista en el anlisis comparativo realizado con anterioridad, es que
ninguna alternativa existente implementa de forma completa las siete capas propuestas por el
modelos OSI. Generalmente implementan las capas fsicas y de enlace, y en algunos casos la capa
FernandoArielBeunza79156

185

Tesis de Grado en Ingeniera Informtica


de aplicacin. Algunas alternativas unifican funcionalidades especificadas en varias capas del
modelo OSI en una capa de su propio modelo, y otras funcionalidades ni siquiera son
implementadas, como por ejemplo las funcionalidades de la capa de presentacin. Los motivos son
comprensibles ya que buscan reducir costos de implementacin de los dispositivos, dejando de lado
funcionalidades. La solucin propuesta en ste trabajo, por su carcter de prototipo, no persigue
fines de eficiencia, sino que propone una alternativa de la cual se puedan extraer ideas para futuros
trabajos. Por sta razn, implementa las siete capas siguiendo al modelo OSI, para mostrar las
ventajas de implementar todas las funcionalidades, que en el futuro, con el desarrollo de la
tecnologa de microcontroladores, puede resultar econmico y factible la implementacin de
dispositivos que contengan las siete capas. Igualmente la solucin propuesta intenta acercarse a la
realidad y proponer una forma de implementacin que no demande tantos recursos a los
dispositivos clientes, distribuyendo las siete capas entre el dispositivo cliente y el modem PLC. En el
dispositivo cliente se implementan las capas de aplicacin y presentacin, porque se relacionan
inevitablemente con la plataforma utilizada para la implementacin de ste dispositivo. En cambio
las restantes capas pueden implementarse en un microcontrolador aparte.
La forma de implementacin de la solucin propuesta descripta anteriormente abre una
posibilidad que no ofrece ninguna alternativa estudiada. Al implementar cinco de las siete capas en
un microcontrolador dedicado se dispone de un ncleo independiente del dispositivo cliente, que
puede ser un dispositivo real que realice una tarea en concreto o puede ser un dispositivo virtual. En
diseo de las capas no impide que puedan desarrollarse las capas de aplicacin y de presentacin
dentro de una PC, y que una aplicacin dentro de sta simule el funcionamiento de un dispositivo
cliente. sta caracterstica es muy importante ya que contribuye en el desarrollo de dispositivos
clientes de forma econmica, ya que se pueden simular antes de implementarse.
Dentro de una PC, para simular los dispositivos clientes deben crearse aplicaciones por
medio de algn lenguaje de programacin que utiliza la interfaz provista por la capa de aplicacin.
No siempre los desarrolladores de dispositivos clientes tienen conocimientos de programacin, por
lo cual la solucin propuesta incluye una interfaz grfica que se encuentra por encima de la capa de
aplicacin. La interfaz grfica consiste en un conjunto de bloques funcionales Simulink, que permite
desarrollar realizando un modelo grfico que las funcionalidades que debe cumplir el dispositivo
cliente en desarrollo a simular.

5.4. Desempeo de la solucin propuesta


Para evaluar como se desempea el sistema desarrollado en ste trabajo en forma conjunta se
propone un esquema de prueba, cuyos detalles se especifican en el Apndice G (Implementacin de
pruebas). La evaluacin consiste en observar el funcionamiento del sistema desde el nivel de capa
de aplicacin. sto se realiza por medio de aplicaciones de prueba desarrolladas en diferentes
entornos (C, C++ y Simulink), para tambin incluir en la evaluacin a las extensiones del sistema
desarrolladas. La configuracin de la red implementada para la realizacin de las pruebas es similar
a la utilizada para evaluar el funcionamiento del mdulo analgico y el mdulo de procesamiento
de seales. Tambin se incluye un dispositivo cliente real conectado a uno de los modems PLC, de
forma tal de implementar un esquema de comunicacin entre un dispositivo cliente real y un
dispositivo cliente virtual, implementado por las aplicaciones de prueba anteriormente mencionadas
ejecutndose en una PC conectada al otro modem. Para supervisar el funcionamiento de la red se
emplean las herramientas de depuracin provistas por el sistema desarrollado, que ahorran la
implementacin de un dispositivo de diagnstico (que requiere de un tercer modem PLC), o la

186

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


implementacin de una aplicacin de diagnstico que se ejecute en la misma PC donde se encuentra
el dispositivo cliente virtual.
El dispositivo cliente real consiste simplemente en un dispositivo que simula un sistema de
iluminacin de un automvil, con distintos focos de iluminacin accionados por diferentes
mensajes. El dispositivo cliente virtual es una aplicacin que simula un dispositivo que acciona los
focos de iluminacin del dispositivo cliente real. De sta forma se puede evaluar como funciona el
sistema en comparacin al modo utilizado tradicionalmente en un automvil para comandar las
luces de iluminacin.
Las aplicaciones de prueba y el modelo Simulink de prueba implementan una secuencia de
encendido y apagado de los diferentes focos de iluminacin implementados en el dispositivo cliente
real. De sta forma se puede comprobar, por simple observacin, que la velocidad de respuesta no
es tan veloz como en un sistema de iluminacin tradicional. sto se debe a que el poder de computo
de los microcontroladores utilizados en la implementacin de los modems PLC no es suficiente para
dar una respuesta en tiempo real, como requiere el accionamiento de los focos de iluminacin. Sin
embargo, la calidad de servicio brindada por el sistema desarrollado sera adecuada para
aplicaciones que suministren informacin de baja velocidad de variacin (nivel de combustible,
temperatura de motor, etc.) y otros dispositivos de uso general (control de la radio, etc.). Un
resultado as era esperable, ya que la propuesta presentada en el presente trabajo es un prototipo
orientado a implementar un sistema de comunicaciones para aplicaciones de uso general, colocando
su nfasis en demostrar que se lo puede implementar sobre las lneas de alimentacin, y siguiendo el
modelo de capas OSI. Demostrado sto ltimo queda abierta la posibilidad futura de continuar
avanzando en trabajos futuros para mejorar el desempeo.

FernandoArielBeunza79156

187

Tesis de Grado en Ingeniera Informtica

188

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

6. Conclusiones
En ste ltimo captulo del presente trabajo se describen las conclusiones que se pueden
extraer a partir del anlisis de los resultados obtenidos de la evaluacin de la solucin propuesta
realizada en el captulo anterior. A partir de los logros obtenidos y de los aspectos mejorables de la
propuesta presentada, se pueden definir futuras lneas de investigacin para trabajos futuros que
quieran contribuir con el desarrollo de las comunicaciones PLC para automviles.

6.1. Anlisis de resultados


Una de las conclusiones a la que se puede arribar a partir del presente trabajo es que se ha
demostrado el potencial de plantear un sistema para el ambiente automotriz que siga el modelo de
siete capas de OSI. Como se analiz con anterioridad, cuando se habl del antecedente OSEK/VDX,
se mencion que la idea ste antecedente era implementar una plataforma estndar para permitir la
interoperabilidad de los distintos dispositivos presentes en un automvil, y de sta manera
simplificar la implementacin de los dispositivos y bajar los costos de los mismos. Seguir las pautas
del modelo OSI, en cualquier mbito de aplicacin, logra ese objetivo porque el modelo de capas
persigue el fin de independizar los distintos elementos que conforman el proceso de comunicacin
(hardware, medio fsico, protocolos de transporte de informacin, etc.). Las redes IP son un ejemplo
de las ventajas ofrecidas por el modelo de capas, ya que ha permitido bajar los costos de las mismas
y difundirlas a muchos mbitos de aplicacin. La misma idea se pretende aplicar al mbito de los
automviles para bajar los costos de los mismos, en tiempos en donde cada vez se integran ms
dispositivos electrnicos a los mismos. Los microcontroladores actuales son capaces de cubrir el
costo de procesamiento demandado por las siete capas, aunque no en todas partes del mundo se
tiene libre acceso a los mismos, por lo cual todava no resulta del todo conveniente la introduccin
de sta tecnologa en automviles que pretendan ser vendidos en cualquier parte del mundo.
Otra cuestin que se demuestra en ste trabajo, es el potencial que presentan las
comunicaciones PLC. Siempre se ha estudiado el problema que presentan las redes cableadas en
cuanto a costos de instalacin, y las ventajas de las redes inalmbricas sobre sta ltimo problema.
Las redes PLC poseen cualidades comunes a los dos tipos de redes anteriores: las lneas elctricas
llegan a todos los lugares donde existan dispositivos electrnicos (ahorro de instalacin de una red
para datos), y stas son un medio guiado (sin los inconvenientes que presentan las redes
inalmbricas). Igualmente, las lneas de potencia tienen en su contra, que no fueron diseadas para
la transmisin de datos, lo que requiere de inteligencia adicional en los dispositivos de
comunicacin para brindar un servicio de transporte de datos de forma confiable. El
aprovechamiento de las lneas de potencia en infraestructura edilicia se ha demostrado que es
factible segn los antecedentes en la materia estudiados en el presente trabajo, aunque existen
estndares comerciales todava se contina trabajando en el tema, ya que todava existen
discusiones sobre las interferencias que pueden causar las comunicaciones PLC en otros
dispositivos que trabajan en los mismos rangos de frecuencia. En el ambiente de un automvil
resulta cada vez ms necesario formas de interconexin de dispositivos electrnicos que
economicen el uso de cableado, ya que cada vez se emplean ms dispositivos y los cableados
dedicados resultan voluminosos y poco confiables susceptibles a interferencia por agrupar
demasiados conductores en volmenes reducidos. Redes como CAN, J1850, LIN, D2B, MOST y
FlexRay; proponen alternativas de interconexin que superan las dificultades del cableado dedicado,
aunque el aumento de la cantidad de dispositivos ya vuelve complejos los cableados actuales de los
FernandoArielBeunza79156

189

Tesis de Grado en Ingeniera Informtica


automviles. Introducir la tecnologa PLC en los automviles resulta una idea adecuada ya que se
reduce al mnimo el cableado, ya que siempre se va a requerir de alimentacin a los dispositivos por
lo cual la red de alimentacin nunca se podr eliminar. Es un medio fsico con algunas dificultades
adicionales con respecto a las lneas de potencia presentes en infraestructura edilicia, es un medio
mucho ms ruidoso que dificulta las comunicaciones confiables; de hecho las redes utilizadas en la
actualidad se caracterizan por su robustez ante interferencias, y hasta emplean fibra ptica para
transmisiones de alta velocidad. Sin embargo, el poder de los microcontroladores en aumento
permite la implementacin de tcnicas de modulacin y codificacin de la informacin que
permiten comunicaciones de mejor calidad, a pesar del medio sobre el cual se llevan a cabo.
El diseo del prototipo alcanza resultados satisfactorios comparado con el prototipo
propuesto por los trabajos realizados por la Facultad de Ingeniera Elctrica de la Universidad
Tcnica Checa de Praga. Aunque la tecnologa aplicada para la implementacin del prototipo
propuesto por el presente trabajo es inferior a la utilizada en el prototipo propuesto en el antecedente
mencionado anteriormente, cumple con los requerimientos bsicos necesarios para demostrar el
funcionamiento correcto del conjunto que compone la propuesta planteada por ste trabajo. Gracias
a sto se puede decir que en el futuro, se puede proponer un prototipo ms evolucionado
tecnolgicamente, y se van obtener iguales o mejores resultados ya que muchos conceptos
planteados en el presente trabajo continan siendo vlidos independientemente de la tecnologa de
implementacin, porque el modelo de capas adoptado permite sto ltimo.
Aunque el servicio de comunicacin que puede brindar el sistema propuesto en el presente
trabajo no alcance la calidad de estndares comerciales, en cuanto a soluciones determinsticas
como por ejemplo las ofrecidas por CAN y J1850, o altas velocidades de transferencia como D2B,
MOST y FlexRay; se debe recordar que el desarrollo se trata de un prototipo que fundamentalmente
pretende evaluar la viabilidad de la propuesta y servir para la construccin en un futuro de un
sistema comercial que tome como antecedentes los conceptos probados en ste trabajo. La solucin
propuesta tiene inconvenientes similares que el antecedente DC-BUS, a la hora de implementar un
mecanismo de control de acceso al medio, porque a diferencia de muchas de las redes de datos de
automviles que pueden escuchar el medio fsico y transmitir en simultneo, stas no lo pueden
realizar por cuestiones de complejidad en la implementacin. Los mecanismos implementados en
ambos casos fueron diseados especialmente, DC-BUS implementa un mecanismo propio, mientras
que la solucin propuesta en ste trabajo adapta el protocolo CSMA/CA y lo combina con un
esquema de prioridad para acercarlo a una solucin determinstica. De todos modos, el prototipo no
fue pensado para aplicaciones crticas sino para aplicaciones generales y telemtica que requieren
velocidades bajas y medias. El empleo de microcontroladores ms potentes en un futuro podra
mejorar el sistema prototipo propuesto para brindar varios tipos de servicios de comunicaciones
como ofrecen, por ejemplo MOST y FlexRay, paquetes de datos, flujos de datos de multimedia, etc.
La implementacin de las siete capas por parte del solucin propuesta en ste trabajo permite
la introduccin de funcionalidades no encontradas en las alternativas para automviles estudiadas.
Una de ellas es el concepto de redes lgicas, por lo cual se independiza la red fsica asociada al
cableado instalado, de como se organizan los distintos dispositivos conectados a la red anterior. ste
concepto es tomado de las redes IP, donde el protocolo IP de la capa de red implementa un esquema
de direccionamiento y de encaminado de paquetes independiente del soporte fsico utilizado para
comunicaciones. De ste modo se da libertad de evolucin a las capas inferiores (capa fsica y de
enlace), ms vinculadas al hardware y de ms rpida evolucin acompaando a las nuevas
tecnolgicas.
Otro aspecto que merece ser analizado es el transporte de datos, que aunque muchos de los
antecedentes estudiados no implemente una capa de transporte especfica, resuelven de alguna
forma la problemtica relacionada con ste tema. En general, el transporte de datos de forma
confiable, viene garantizado por la capa de enlace, por ejemplo CAN y J1850 implementan un
190

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


mecanismo de multicast confiable, D2B y MOST trabajan con esquema de paso de testigo. sta
manera de encarar el problema resulta las ms simple de implementar, a diferencia de redes IP que
requieren de un protocolo de transporte de una cierta complejidad, aceptable en una computadora,
pero que resulta inadecuada para la implementacin de dispositivos de un automvil. La solucin
propuesta tambin toma la idea de sus antecedentes y fortalece las capacidades de la capa de enlace,
lo que le permite implementar una capa de transporte ms simple que la del modelo TCP/IP. Los
servicios brindados por sta capa de transporte son dos tipos de mensajera, una de mensajes
secuenciados orientadas a transporte de datos de configuracin de dispositivo que no requieren
urgencia pero si garanta de que lleguen a destino y en siguiendo un orden, y otro de mensajes no
secuenciado orientado a rdenes que requieren que lleguen a destino lo ms rpido posible. Como
ya se hizo mencin con anterioridad, la solucin propuesta no ofrece otros tipos de servicios de
comunicacin orientados por ejemplo a multimedia, como si lo ofrece MOST, ya que se trata de un
sistema prototipo cuyo objetivo no es proponer un sistema comercial, aunque el diseo no impide
que en el futuro se puedan proponer nuevas ideas.
El diseo del prototipo de modem PLC implementa las capas fsica, de enlace, red,
transporte y sesin; no puede implementar las capas de presentacin y aplicacin porque dependen
del dispositivo cliente. Si se quisiera implementar las siete capas de forma conjunta debe realizarse
dentro del mismo microcontrolador del dispositivo cliente, por la dependencia mencionada
anteriormente. Las capas de presentacin y aplicacin son dependientes del dispositivo cliente
porque la primera est relacionada como se representan y estructuran los datos (dependiente de la
plataforma), y la segunda es la interfaz con la cual se relaciona la aplicacin cliente con el sistema
de comunicacin. Ninguno de los antecedentes analizados en ste trabajo implementa la capa de
presentacin, salvo el modelo LonWorks que implementa las siete capas pero no se utiliza en
automviles; trasladndose el problema al dispositivo cliente para que lo resuelva de alguna forma.
En cambio la propuesta del presente trabajo, resuelve todos los problemas planteados por cada una
de las siete capas, y disea el prototipo para que la solucin tenga la mejor relacin costo beneficio
para el dispositivo cliente (agrega la implementacin de dos capas, pero el sistema ofrece los
beneficios de las siete).
Un beneficio adicional, a consecuencia de lo anterior, es que se puede implementar una
versin de capa de presentacin y de aplicacin para PC. La propuesta del presente trabajo las
implementa para brindar una herramienta de simulacin de dispositivos clientes, que resulta de gran
utilidad para el diseo y posterior implementacin de los mismos, algo no ofrecido por ninguno de
los antecedentes estudiados. Tambin permite la implementacin de un entorno grfico como
Simulink para el modelado de dispositivos clientes virtuales, que libera a los desarrolladores de
dichos dispositivos de tener conocimientos de programacin

6.2. Trabajos futuros


Los trabajos futuros para contribuir en ste arte deben estar orientados a tomar las ideas
planteadas en el presente trabajo, mejorando los xitos logrados y avanzar sobre los aspectos
mejorables, sealados con anterioridad. La solucin propuesta en el presente trabajo es un sistema
prototipo con todas las limitaciones del mismo, no puede ser visto como un sistema comercial, por
lo cual una de las lneas de investigacin puede derivar en optimizacin del sistema prototipo.
Tambin se pueden seguir otras lneas de investigacin que incluyan partes y no la totalidad de la
solucin propuesta, por ejemplo el modelo de siete capas es independiente de la tecnologa PLC y
puede aplicarse a otras tecnologas de comunicacin presentes en un automvil. Incluso se puede
pensar en adaptar la solucin propuestas a otras aplicaciones diferentes al automvil; por ejemplo

FernandoArielBeunza79156

191

Tesis de Grado en Ingeniera Informtica


maquinaria agrcola, barcos, aviones, etc. La solucin propuesta podra adaptarse a todo mbito en
donde exista el problema de reduccin de cableado como ocurre en los automviles.
Uno de los aspectos mejorables a la solucin propuesta por el presente trabajo se encuentra
relacionado con las tcnicas de modulacin y codificacin de la informacin. La implementacin
propuesta resulta en una solucin bsica orientada a brindar servicios de comunicacin elementales.
Conociendo las opciones que brindan algunos antecedentes estudiados, se puede tomar la idea
planteada por DC-BUS de trabajar con varias bandas de frecuencia para proveer distintos tipos de
canales de comunicacin para aplicaciones generales, telemtica y multimedia. Tambin se puede
mejorar la velocidad de transferencia empleando otras tcnicas de modulacin y codificacin de la
informacin que requieren necesariamente mayor capacidad de computo por parte del
microcontrolador utilizado para implementar el modem PLC.
Algo relacionado con el tema anterior, y tambin mejorable es el protocolo de control de
acceso al medio. Si en el futuro se desea brindar soporte para comunicacin de diversos tipos de
datos, como paquetes de datos, multimedia, etc., como por ejemplo brinda MOST, debe volverse a
plantear el protocolo de acceso al medio; los paquetes de datos pueden contener informacin crtica
o no (por lo cual las caractersticas del protocolo empleado pueden variar), y la informacin
multimedia requiere la asignacin de un ancho de banda constante. Por un razn lgica, para
implementar la sugerencia anterior, necesariamente debe utilizarse un microcontrolador con mayor
poder de computo (como el ofrecido por los micrcocontroladores de la familia ARM) que el
utilizado en la solucin propuesta en el presente trabajo.
Una funcionalidad futura que se puede sugerir es la integracin del sistema propuesto con
otras redes, similar a lo que ocurre con CAN y LIN. La implementacin de dispositivos que
funcionen como puente entre el sistema de comunicaciones PLC y otro tipo de red, contribuye en la
adopcin progresiva de sta tecnologa en aplicaciones comerciales. Adems toda nueva tecnologa
al comienzo es costosa de implementar, por lo cual al comienzo no muchos dispositivos la adoptan,
entonces el disponer de algunos dispositivos puente con otras redes que ofrezcan soluciones de
interconexin ms econmicas resultan en una propuesta razonable.
El modelo de implementacin de cinco capas dentro del modem PLC y dos en el dispositivo
cliente en un futuro puede ser replanteado, disponiendo de microcontroladores con alto poder de
computo (por ejemplo, ARM9) para implementar las siete capas en un slo dispositivo electrnico.
Tambin puede ser viable si el dispositivo cliente es tan complejo que supere en varios rdenes de
complejidad a las siete capas del sistema de comunicacin.
En cuanto a las interfaces de uso del sistema de comunicacin planteado en ste trabajo, la
implementacin incluye una interfaz C/C++ y una biblioteca de bloques Simulink para mostrar que
se puede continuar el desarrollo por encima de la capa de aplicacin. Las interfaces mencionadas
son de utilidad para simulaciones en una PC de dispositivos clientes virtuales, pero se limita a dos
entornos. Una contribucin hacia el futuro puede ser plantear interfaces para distintos lenguajes de
programacin e interfaces grficas para entornos de simulacin similares a Simulink.

192

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

7. Referencias
[Alcar07]

Alcar H.: Power Line Communicacion en Argentina Revista


Coordenadas, 2007

[AlleyAtwood68]

Alley C., Atwood K.: Ingeniera Electrnica 1ra. Edicin, 1968

[AmraniRubin]

Amrani O., Rubin A.: A new multiple access scheme for DC power
line communications
http://www.yamar.com/articles/A-new-multiple-access-scheme-forpowerline.pdf

[AT89S52]

Atmel: 8-bit Microcontroller with 8K Bytes In-System


Programmable Flash AT89S52
http://www.atmel.com/dyn/resources/prod_documents/doc1919.pdf

[AT89CMemOrg]

Atmel: Flash Microcontroller Memory Organization


http://www.atmel.com/dyn/resources/prod_documents/doc0498.pdf

[AT89mega8515]

Atmel: 8-bit AVR Microcontroller with 8K Bytes In-System


Programmable Flash ATmega8515 Atmega8515L
http://www.atmel.com/dyn/resources/prod_documents/doc2512.pdf

[BenziFacchinettiCaprini08] Benzi F., Facchinetti T., Caprini D.: Powerline Protocols Review,
evaluation and test for automotive applications, 2008
www.etec.polimi.it/emc-chapit/download/slides_Pavia_4_nov_2008.pdf
[Bosch91]

Robert Bosch GmbH, CAN Specification Version 2.0, 1991

[D2B02]

Mercedes Benz: Domestic Digital Bus (D2B), 2002


http://www.mercedestechstore.com/pdfs/507%20Systems
%20I/507%20HO%20D2B%20(ICC)%2010-30-02.pdf

[D2B04]

Mercedes Benz: Domestic Digital Bus (D2B), 2004


http://www.mercedestechstore.com/pdfs/416_Telematics/416%20H
O%20D2B%20(CooksonI)%2003-09-04.pdf

[Echelon99]

Echelon: Introduction to the LonWorks Platform Revision 2, 1999


http://www.echelon.com/support/documentation/manuals/general/07
8-0183-01B_Intro_to_LonWorks_Rev_2.pdf

FernandoArielBeunza79156

193

Tesis de Grado en Ingeniera Informtica


[FlexRay]

UPC (Universidad Politcnica de Catalua): El Protocolo FlexRay


http://upcommons.upc.edu/pfc/bitstream/2099.1/6115/4/2.%20El
%20protocolo%20Flexray.pdf

[HFDrahtfunk]

Exordio: HF-Drahtfunk (Radio por cable)


http://www.exordio.com/1939-1945/civilis/telecom/hfdrahtfunk.html

[HomePlug1.0]

Home Plug Powerline Alliance: HomePlug 1.0.1 Specification, 2001


http://read.pudn.com/downloads114/ebook/479147/HOMEPLUG.pd
f

[HomePlugAV]

Home Plug Powerline Alliance: HomePlug AV White Paper, 2005


http://www.homeplug.org/tech/whitepapers/HPAV-WhitePaper_050818.pdf

[HomePlugGP]

HomePlug Powerline Alliance: Home Plug Green PHY The


Standard For In-Home Smart Grid Powerline Communications,
2010
http://www.homeplug.org/tech/whitepapers/HomePlug_Green_PHY
_whitepaper_100614.pdf

[House]

House P.: CEBus for the Masses


http://www.integrasoft.ro/~barni/hpg/cjava/EIA-600%20Draft
%20Specifications/CEBus%20For%20The%20Masses.pdf

[IEEEP1901]

IEEE, IEEE P1901: Standard for Broadband over Power Line


Networks: Medium Access Control and Physical Layer
Specifications, 2010
http://grouper.ieee.org/groups/1901/

[IEEE754]

IEEE, IEEE 754: Standard for Binary Floating-Point Arithmetic,


1985

[IEEE802.2]

IEEE, IEEE 802.2: Lan/Man Logic Link Control, 1998


http://standards.ieee.org/getieee802/802.2.html

[ISO74981]

ISO, ISO 7498-1, 1994


http://standards.iso.org/ittf/PubliclyAvailableStandards/s020269_IS
O_IEC_7498-1_1994(E).zip

194

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


[ISO/IEC149081]

ISO, ISO/IEC 14908-1, Open Data Communication in Building


Automation, Controls and Building Management Control Network
Protocol Part 1: Protocol Stack, 1999
http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.h
tm?csnumber=56523

[Kaspar]

Kaspar Z.: Power-Line Communication - Regulation Introduction,


PL Modem Implementation and Possible Application
http://www.urel.feec.vutbr.cz/ra2007/archive/ra2002/pdf/41.pdf

[LeenHeffernanDunne]

Leen G., Heffernan D., Dunne A.: Digital Networks in Automotive


Vehicle
http://nicozone.free.fr/206/VAN/fp16.pdf

[LIN10]

LIN Consortium: LIN Specification Package Revision 2.2, 2010


http://www.lin-subbus.org/

[Linjesender]

Wikipedia: Linjesender
http://en.wikipedia.org/wiki/Linjesender

[Maryanka00]

Maryanka Y.: Wiring Reduction by Battery Power Line


Communications, 2000
http://www.yamar.com/articles/Wiring-reduction-by-DC-powerlinecommunication.pdf

[Montoya06]

Montoya L.: Power Line Communications Performance Overview of


the Physical Layer of Available protocols, 2006
http://masters.donntu.edu.ua/2006/kita/avramenko/library/lib9a.pdf

[MOST04]

Mercedes Benz: MOST System, 2004


http://www.mercedestechstore.com/pdfs/416_Telematics/416%20H
O%20MOST%20%28CooksonI%29%2007-01-04.pdf

[MOST10]

MOST: MOST Specification Rev. 3.0 E2, 2010


http://www.mostcooperation.com/publications/Specifications_Organ
izational_Procedures/index.html?doc=4425&dir=291

[Oliver]

Oliver J.: Implementing the J1850 Protocol


http://download.intel.com/design/intarch/papers/j1850_wp.pdf

[OppenheimWillsky97]

Oppenheim A., Willsky A.: Seales y Sistemas 2da. Edicin, 1997

FernandoArielBeunza79156

195

Tesis de Grado en Ingeniera Informtica


[Paret05]

Paret D.: Multiplexed Networks for Embbeded Systems CAN, LIN,


Flexray, Safe-by-Wire..., 2005
http://books.google.com.ar/books?
id=GfY38U8s3DIC&printsec=frontcover&hl=es#v=onepage&q&f=f
alse

[PLCEc]

UPS (Universidad Politcnica Salesiana): Investigacin y Anlisis de


la Tecnologa PLC desde la Perspectiva del Mercado Ecuatoriano
http://dspace.ups.edu.ec/bitstream/123456789/539/4/CAPITULO2.p
df

[Rey03]

Rey S.: Introduction to LIN (Local Interconnect Network), 2003


http://rs-rey.pagesperso-orange.fr/electronic_ressources/Ressources/
Networks/LIN/LIN_bus.pdf

[Reuss93]

Reuss H.: Extended Frame Format - A New Option of the CAN


Protocol, 1993
http://cst.mi.fuberlin.de/projects/ScatterWeb/moduleComponents/CanBus_CAN2.p
df

[RFC791]

USC (University of Southern California): Internet Protocol DARPA


Internet Program Protocol Specification, 1991
http://www.ietf.org/rfc/rfc791.txt

[RFC793]

USC (University of Southern California): Transport Control


Protocol DARPA Internet Program Protocol Specification, 1991
http://www.ietf.org/rfc/rfc793.txt

[RFC826]

Plummer D.: Ethernet Address Resolution Protocol, 1982


http://www.ietf.org/rfc/rfc826.txt

[SAE94]

SAE (Society of Automotive Engineers): SAE Standard J1850


Class B Data Communication Network Interface, 1994
www.autoelectric.cn/discuz/attachment.php?aid=6

[Stallings97]

Stallings W.: Data and Computer Comunications 5th. Edition, 1997

[StrangRckl]

Strang T., Rckl M.: Vehicle Networks Controller Area Network


(CAN)
http://www.sti-innsbruck.at/fileadmin/documents/vn-ws0809/02VN-CAN.pdf

196

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


[Trnka05]

Trnka M.: Power Line Communications in Automotive Industry,


2005
http://measure.feld.cvut.cz/usr/doctoral/Trnka/teze.pdf

[Trnka061]

Trnka M.: Optimization of the Data Transmissions over DC Power


Lines, 2006
http://measure.feld.cvut.cz/usr/doctoral/Trnka/thesis.pdf

[Trnka062]

Trnka M.: Optimization of the Data Transmissions over DC Power


Lines, 2006
http://www3.fs.cvut.cz/web/fileadmin/documents/12241BOZEK/publikace/2006/2006_020_01.pdf

[TrnkaPurkert05]

Trnka M. ,Purkert M.: Development System for Communications


over DC Power Lines, 2005
http://measure.feld.cvut.cz/usr/doctoral/Trnka/appel05.pdf

[Tropeano03]

Tropeano F.: Introduccin al Procesamiento y Transmisin de datos,


2003

[UPB]

PCS (Power Control Systems): The UPB System Description


Version 1.1, 2003
http://www.smarthomeusa.com/Common/UPB/UPBdescription.pdf

[VerssimoRodrigues01]

Verssimo P., Rodrigues L.: Distributed Systems for Systems


Architects, 2001

[Wense00]

Wense H.: Introduction to LIN, 2000


http://www.linsubbus.org/downloads/publications/introduction_to_lin.pdf

[X10SignalTheory]

EuroX10: Teoria da Transmisso de Sinais X-10


http://www.eurox10.com/Content/X10SignalTheory.htm

[X10TechNote]

X10 POWERHOUSE, Technical Note The X-10 POWERHOUSE


Power Line Interface Model # PLC513 and Two-Way Power Line
interface # TW523
ftp://ftp.x10.com/pub/manuals/technicalnote.pdf

[Zeltwanger]

Zeltwanger H.: Introduction into CAN physical and data link layer
http://www.can-expo.ru/files/physical.pdf

FernandoArielBeunza79156

197

Tesis de Grado en Ingeniera Informtica

198

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice A: Implementacin del hardware


del modem PLC
En el ste apndice se describe y detalla la implementacin de cada uno de los componentes
que conforman el hardware del prototipo de modem PLC construido para evaluar el funcionamiento
de sistema propuesto en el presente trabajo

A.1. Organizacin del hardware


Debido a que el modem PLC implementado se trata de un prototipo, no se ve la necesidad de
implementar el mismo en una nica plaqueta, lo cual evita ciertos problemas de interferencia entre
los componentes electrnicos al no encontrarse concentrados en un espacio reducido. Adems, no es
el objetivo del presente trabajo, realizar un dispositivo comercial en donde se exige la
miniaturizacin. Por stos motivos la mejor forma de implementar el modem PLC es dividiendo las
principales funcionalidades en mdulos separados (cada uno de stos corresponde a una plaqueta
diferente) interconectados entre s para conformar un nico dispositivo.
La organizacin propuesta permite separar los circuitos puramente analgicos, de los mixtos
(digital/analgico) y de los puramente digitales. Adems cada mdulo trabaja con seales de
distintos rangos de frecuencia. El mdulo analgico es puramente analgico y trabaja con seales de
alta frecuencia por encima de 10 MHz. En cambio el mdulo de procesamiento de seales presenta
una combinacin de partes analgicas y digitales, y las seales que procesa presentan frecuencias de
rango intermedio por debajo de 5 MHz. El mdulo de procesamiento es puramente digital y trabaja
con seales digitales con frecuencias por debajo de 1 MHz. sta organizacin permite tambin
continuar investigando y desarrollando el tema tratado por ste trabajo, ya que pueden proponerse
nuevas implementaciones de cada mdulo por separado, por ejemplo se puede mejorar la tecnologa
de implementacin del mdulo analgico sin alterar los restantes mdulos, o bien mejorar la
codificacin de la informacin sin alterar el mdulo analgico y el mdulo de procesamiento, o
tambin aumentar la capacidad de procesamiento de mensajes del mdulo de procesamiento sin
alterar los otros mdulos.

Figura A1. Diagrama de organizacin del hardware.

Los mdulos constituyentes del modem PLC prototipo (figura A1), se describe a
continuacin:

Mdulo analgico: se compone de un Filtro, un Transmisor y un Receptor.

FernandoArielBeunza79156

199

Tesis de Grado en Ingeniera Informtica


El Filtro consiste en un filtro pasivo que rechaza la banda de frecuencias utilizada para
transmitir la informacin. Entrega por un lado la seal de potencia utilizada para
alimentacin libre de ruido, y por otro, la seal de informacin, en forma separada.
El Transmisor se encuentra constituido por un amplificador de entrada, un convertidor de
frecuencias, un amplificador de salida y un circuito de acoplamiento. La seal de
informacin es filtrada y amplificada por el amplificador de entradas. Luego la seal
resultante es trasladada en frecuencia por el convertidor de frecuencias. La resultante de la
conversin de frecuencias es amplificada por el amplificador de salida que se encarga de
repetir la misma seal de entrada con la fuerza suficiente para propagarse por la red PLC.
El circuito de acoplamiento se encarga de acoplar la salida del amplificador de salida con
la red de potencia.
El Receptor se encuentra constituido por un circuito de desacomplamiento, un
amplificador de entrada, un convertidor de frecuencias y un amplificador de salida. El
circuito de desacomplamiento filtra la seal de potencia, dejando solamente la seal con
la informacin que es amplificada y filtrada por el amplificador de entrada. La seal
resultante es convertida en frecuencia por el convertidor de frecuencias, y la seal de
salida de dicho convertidor es filtrada y amplificada por el amplificador de salida.

Mdulo de procesamiento de seal: se compone de un microcontrolador dedicado al


procesamiento de seales. Dicho microcontrolador es el encargado de sintetizar la seal
de informacin, por medio de un DAC, que es tomada por el Transmisor del mdulo
analgico y de detectar la informacin contenida en la seal proporcionada por el
Receptor del mdulo analgico, por medio de un ADC. Dicha seal es retardada y
posteriormente multiplicada por la seal sin retardar. La seal resultante de la
multiplicacin es procesada por un integrador que acta como filtro pasabajos resultando
a la salida de ste ltimo una seal donde se puede detectar la informacin contenida en
la seal original.

Mdulo de Procesamiento: se compone de


un microcontrolador dedicado al
procesamiento de mensajes. Dicho microcontrolador se encarga de ejecutar la lgica
relacionada con las capas de enlace, red, transporte y sesin del modelo OSI. El
microcontrolador de procesamiento interacta con otros dispositivos por medio de una
interfaz serial de comunicaciones.

Mdulo de Adaptacin RS232: se trata de un mdulo opcional que permite interconectar


el modem PLC a una PC mediante un puerto serie. El mdulo de procesamiento provee de
una interfaz serial de comunicaciones que permite la interconexin con otros dispositivos
con ste tipo de interfaz sin necesidad de ninguna adaptacin. Para el caso de la PC es
necesario un hardware adicional para adaptar las seales de la PC con las del mdulo de
procesamiento.

Se debe notar que no existe ningn mdulo referido a la alimentacin del modem PLC,
debido a que la funcin de fuente de alimentacin se encuentra distribuida entre los distintos
mdulos, es decir que cada mdulo posee su propia fuente de alimentacin para independizar
elctricamente a cada mdulo para evitar interferencias que hagan al mal funcionamiento de los
mismos.

200

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

A.2. Implementacin del mdulo analgico


La implementacin de los circuitos constituyentes del mdulo analgico son similares a los
detallados en el Apndice B (Simulacin del mdulo analgico). Pueden variar algunos
componentes utilizados debido a que fsicamente no se comportan como indicaban los resultados de
las simulaciones.
En la primer pgina se puede observar las interfaz del mdulo analgico con la red de PLC y
el mdulo de procesamiento de seales. En la segunda pgina se detalla circuito de alimentacin del
mdulo analgico. En la tercer pgina se pueden observar los circuitos constituyentes del
Transmisor (amplificador de entrada, oscilador, convertidor de frecuencias, amplificador de salida y
circuito de acoplamiento). Finalmente en la cuarta pgina se pueden observar los circuitos que
conforman el Receptor (circuito de desacoplamiento, amplificador de entrada, oscilador, convertidor
de frecuencias, amplificador de salida).

FernandoArielBeunza79156

201

Tesis de Grado en Ingeniera Informtica

202

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

203

Tesis de Grado en Ingeniera Informtica

204

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

205

Tesis de Grado en Ingeniera Informtica

206

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

A.3. Implementacin del mdulo de procesamiento


de seales
La implementacin de los circuitos constituyentes del mdulo procesamiento de seales son
similares a los detallados en el Apndice B (Simulacin del mdulo de procesamiento de seales).
Pueden variar algunos componentes utilizados debido a que fsicamente no se comportan como
indicaban los resultados de las simulaciones.
En la primer pgina se puede observar las interfaz del mdulo procesamiento de seales con
el mdulo analgico y el mdulo de procesamiento. En la segunda pgina se detalla circuito de
alimentacin del mdulo de procesamiento de seales. En la tercer pgina se puede observar el
procesador de seales y el oscilador. En la cuarta pgina se detalla el DAC y el amplificador de
salida. En la quinta pgina se puede observar el amplificador de entrada y el ADC. Finalmente en la
sexta pgina se pueden el integrador y el sintetizador del nivel de umbral.

FernandoArielBeunza79156

207

Tesis de Grado en Ingeniera Informtica

208

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

209

Tesis de Grado en Ingeniera Informtica

210

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

211

Tesis de Grado en Ingeniera Informtica

212

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

213

Tesis de Grado en Ingeniera Informtica

A.4. Implementacin del mdulo de procesamiento


El mdulo de procesamiento se encuentra constituido un microcontrolador dedicado a todas
las funcionalidades del modem PLC referidas al procesamiento de mensajes, salvo el procesamiento
de seales que es realizado en el mdulo mencionado anteriormente. Este microcontrolador,
necesita tener la posibilidad de expandir su memoria de cdigo y datos para poder contener el
firmware con las capas de enlace, red, transporte y sesin del modelo OSI; resultando ms adecuada
la utilizacin del microcontrolador 8052 AT89S52.
Junto con el microcontrolador dedicado al procesamiento de mensajes se implementa un
banco de memoria comn para cdigo y datos, en donde se utiliza un sector de la misma para datos
y otro para cdigo. La memoria de datos se implementa con una memoria RAM de 32KB, ya que los
datos no necesitan persistir en el tiempo; mientras que la memoria de cdigo se implementa con una
memoria EEPROM, tambin de 32KB. A pesar que el microcontrolador AT89S52 ofrece la
posibilidad de trabajar con bancos de memoria separados (cdigo y datos), en este caso se unifican
ambos en un nico banco para permitir que el firmware cargador pueda utilizar a toda la memoria
como memoria de datos, y poder llevar a cabo su tarea principal que es la carga del firmware del
modem PLC, que para el cargador no son ms que datos que deben ser escritos en el sector de
memoria no voltil. El mencionado firmware cargador se encuentra alojado en la memoria de
cdigo interna del microcontrolador, ya que el AT89S52 permite trabajar con su memoria interna y
el banco externo en forma simultnea, permitiendo dejar totalmente libre la memoria no voltil del
banco para el firmware del modem PLC. Otra funcionalidad del cargador es permitir la ejecucin
del firmware del modem PLC, ya que cuando se enciende el modem, lo primero que se ejecuta es el
cargador, que mediante un comando de ste, se pasa a ejecutar el firmware del modem PLC,
alojado en la memoria no voltil.
Firmware
Cargador
RAM de
datos

0x0000
0x1FFF
0x2000
0x7FFF
0x8000

Firmware
Modem PLC
0xFFFF
Figura A2. Organizacin del banco de memoria (vista por el firmware cargador).

214

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

0x0000
RAM de
datos
0x7FFF
0x8000
Firmware
Modem PLC
0xFFFF
Figura A3. Organizacin del banco de memoria (vista por el firmware del modem PLC).

En la figuras A2 y A3, se pueden observar las organizaciones de memoria vistas desde el


punto de vista del firmware cargador y del firmware del modem PLC, en donde el rea sombreada
corresponde al cdigo que se ejecuta en ambos casos. Desde el punto de vista del firmware
cargador, los primeros 8KB corresponden a su cdigo, luego le siguen 24KB de memoria RAM que
no tiene ninguna utilidad (ya que el cargador trabaja con la memoria de datos interna del
microcontrolador) y finalmente se ubican 32KB de memoria no voltil en donde el cargador aloja el
firmware del modem PLC. Cuando el firmware cargador le pasa el control de ejecucin al firmware
del modem PLC, la configuracin cambia a 32KB de memoria RAM voltil para datos y 32KB de
memoria no voltil donde reside el firmware del modem PLC.
Finalmente, el microcontrolador provee una interfaz de comunicacin serial que permite la
interaccin con otros dispositivos. Fsicamente la interfaz trabaja con niveles de tensin compatibles
con TTL lo que permite la interconexin directa con otros microcontroladores de otros dispositivos
si necesidad de interponer un adaptador. En el caso de establecer una conexin con una PC, es
necesario interponer el mdulo de adaptacin RS232 que realiza el ajuste de niveles de tensin entre
la PC y el mdulo de procesamiento.
A continuacin se detalla el esquema del mdulo de procesamiento en donde se muestran
cada uno de los componentes descriptos con anterioridad. En la primer pgina se pueden observar la
fuente de alimentacin, la interfaz de comunicacin con el mdulo de procesamiento de seal y la
interfaz de comunicacin con el dispositivo cliente. En la segunda pgina se puede observar el
microcontrolador junto a su reloj. Por ltimo en la tercer pgina se puede observar la composicin
del banco de memoria.

FernandoArielBeunza79156

215

Tesis de Grado en Ingeniera Informtica

216

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

217

Tesis de Grado en Ingeniera Informtica

218

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

A.5. Implementacin del mdulo de adaptacin


RS232
Como se hizo mencin en el tratamiento del mdulo de procesamiento, ste posee una
interfaz de comunicacin serial para interactuar con otros dispositivos que pueden ser otros
microcontroladores o una PC. Para el caso de ste ltimo es necesario introducir un adaptador
debido a que los niveles de tensin utilizados por ambos dispositivos son distintos. La finalidad de
ste mdulo es justamente la adaptacin de niveles de tensin y no posee ninguna otra funcin, lo
cual resulta en un hardware simple, que es un opcional, ya que si el modem PLC no necesita ser
conectado a una PC, no es necesario que tenga este mdulo adaptador.
A continuacin se detalla el esquema del mdulo de adaptacin RS232 en donde se
muestran cada uno de los componentes constitutivos.

FernandoArielBeunza79156

219

Tesis de Grado en Ingeniera Informtica

220

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice B: Simulacin del hardware del


modem PLC
En el ste apndice se describe y detalla la implementacin de cada uno de los componentes
que conforman el hardware del modem PLC utilizado para la realizacin de las simulaciones,
empleadas para evaluar el comportamiento de algunos componentes dicho modem en situaciones
controladas.

B.1. Organizacin del hardware


El modem PLC se encuentra constituidos de tres mdulos, cuya descripcin ms detallada se
encuentra en el Apndice A. Debido a diferencias entre los componentes reales y los simulados, la
implementacin de los circuitos presentan leves diferencias entre la implementacin utilizada para
simulacin y la implementacin real. En el presente apndice se detalla la implementacin (para
simulacin) del mdulo analgico y del mdulo de procesamiento de seales, que son los mdulos
ms vinculados con los aspectos fsicos. El mdulo de procesamiento no es necesario
implementarlo para simulacin porque en l reside todo la lgica del sistema que no es simulada.

B.2. Implementacin del mdulo analgico


Los circuitos constituyentes del mdulo analgico que fueron simulados se enumeran a
continuacin ordenados por orden de aparicin de los esquemas:

Esquema 1: Batera y seales de prueba. Proporcionan la alimentacin y las seales de


estmulo para los circuitos bajo prueba.

Esquema 2: Fuente de alimentacin. Proporciona alimentacin estable a los circuitos bajo


prueba.

Esquema 3: Oscilador. Genera una seal con la frecuencia necesaria para el


funcionamiento de los Convertidores de frecuencias utilizados en el Transmisor y en el
Receptor.

Esquema 4: Transmisor. Se compone de un Amplificador de entrada, un Convertidor de


frecuencias, un Amplificador de salida y un Circuito de acoplamiento. El Amplificador
de entrada se encarga de limitar en frecuencia la seal de entrada a ser transmitida y
amplificarla para que pueda ser modulada por el Convertidor de Frecuencias. El
Convertidor de frecuencias consiste en un modulador VSB-SC, que se encarga de
trasladar las seales de entrada a un rango de frecuencias superior a partir de la frecuencia
generada por el Oscilador. El Amplificador de salida se encarga de repetir la seal
generada por el Convertidor de frecuencias con la suficiente potencia para que la misma
viaje por la red de potencia. El Circuito de acoplamiento es un circuito compuesto por
elementos pasivo que bloquea el ingreso de la componente continua de potencia a la

FernandoArielBeunza79156

221

Tesis de Grado en Ingeniera Informtica


salida del Amplificador de salida, a la vez que permite el paso de la seal generada por el
Amplificador de salida hacia la red de potencia.

222

Esquema 5: Receptor. Se compone de un Circuito de desacoplamiento, un Amplificador


de entrada, un Convertidor de frecuencias y un Amplificador de salida. El Circuito de
desacoplamiento es un circuito compuesto por elementos pasivos que rechaza la
componente continua de potencia y deja pasar a la seal de informacin. El Amplificador
de entrada se encarga de amplificar dicha seal para que pueda ser demodulada por el
Convertidor de frecuencias. El Convertidor de frecuencias consiste en un demodulador
VSB-SC, que traslada la seal recibida del Amplificador de entrada a un rango de
frecuencias manejable por el microcontrolador a partir de la frecuencia de traslacin
generada por el Oscilador. Finalmente el Amplificador de salida se encarga de amplificar
la seal generada por el Convertidor de frecuencias y eliminar el ruido generado por ste
ltimo.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

223

Tesis de Grado en Ingeniera Informtica

224

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

225

Tesis de Grado en Ingeniera Informtica

226

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

227

Tesis de Grado en Ingeniera Informtica

B.3. Implementacin del mdulo de procesamiento


de seales
Los circuitos constituyentes del mdulo de procesamiento de seales que fueron simulados
se enumeran a continuacin ordenados por orden de aparicin de los esquemas:

228

Esquema 1: Estmulo. Proporciona la alimentacin y las seales de estmulo para los


circuitos bajo prueba.

Esquema 2: Alimentacin. Proporciona alimentacin estable a los circuitos bajo prueba.

Esquema 3: Microcontrolador I. Simula el algoritmo, que se ejecuta dentro del


microcontrolador procesador de seal, encargado codificar la trama de bits suministrada
utilizando codificacin diferencial (modulacin DBPSK) y de sintetizar la seal que
transporta a dicha trama de bits codificada.

Esquema 4: DAC. Se encarga de generar la seal analgica correspondiente a la


sintetizada por el Microcontrolador I y amplificarla. El DAC utilizado es de 4 bits.

Esquema 5: Canal de transmisin. Simula el canal de transmisin utilizado para enviar la


seal con la informacin. Dicho canal incluye del mdulo analgico y la red de potencia.

Esquema 6: ADC. Se encarga de amplificar la seal recibida para su posterior


digitalizacin. El ADC utilizado es de 1 bit.

Esquema 7: Microcontrolador II. Simula el algoritmo, que se ejecuta dentro del


microcontrolador procesador de seal, encargado de leer la salida del ADC, implementar
en retardo de seal y realizar la multiplicacin entre la seal de leda directamente y la
seal retardada (demodulacin DBPSK).

Esquema 8: Integrador. Implementa un filtro pasabajos que trabaja con


Microcontrolador II para implementar el demodulador DBPSK. La seal resultante
contiene la trama de bits originalmente transmitida.

Esquema 9: Microcontrolador III. Simula el algoritmo, que se ejecuta dentro del


microcontrolador procesador de seal, encargado de detectar el valor de cada bit de la
trama recibida del integrador conforme a un umbral de referencia determinado tambin
por dicho algoritmo.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

229

Tesis de Grado en Ingeniera Informtica

230

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

231

Tesis de Grado en Ingeniera Informtica

232

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

233

Tesis de Grado en Ingeniera Informtica

234

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

235

Tesis de Grado en Ingeniera Informtica

236

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

237

Tesis de Grado en Ingeniera Informtica

238

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice C: Cdigo fuente


En el presente apndice se describe la organizacin del cdigo fuente que constituye el
sistema desarrollado como propuesta en ste trabajo, as como tambin se detalla cada componente
de dicho cdigo fuente.

C.1. Organizacin del cdigo fuente


El cdigo fuente se compone de cuatro partes correspondientes al driver e interfaces del
modem PLC, al firmware del modem PLC, al firmware del procesador de seales y al firmware
cargador. Cada una de stas partes se encuentra organizada en mdulos, cada uno constituido por
un archivo .h donde se declaran las primitivas y un .c donde se implementan las mismas.
Los mdulos constituyentes del driver e interfaces del modem PLC corresponden a las capas
de presentacin y aplicacin del modelo OSI, que se encuentran implementadas dentro de los
dispositivos clientes (reales o virtuales), y vara su implementacin segn la plataforma sobre la
cual se trabaje. Para la plataformas Windows y Linux, adems de implementarse la capa de
presentacin y la capa de aplicacin, se implementan interfaces de acceso a la capa de enlace y la
capa fsica para la realizacin de pruebas, y desarrollo de futuras aplicaciones. Para el caso de la
plataforma AT89X5X, solamente se implementa la capa de presentacin y de aplicacin.
Los mdulos que conforman el firmware del modem PLC, corresponden a parte de la capa
fsica y las capas de enlace, red, transporte y sesin del modelo OSI. ste firmware se ubica
fsicamente en la memoria de cdigo externa del microcontrolador de procesamiento.
El firmware del procesador de seales implementa parte de la capa fsica no implementada
en el firmware del modem PLC, y se encuentra ubicado fsicamente en un microcontrolador
dedicado exclusivamente a la tarea del procesamiento de seales de informacin.
Por ltimo el firmware cargador es una utilidad que permite cargar el firmware del modem
PLC en la memoria de cdigo externa del microcontrolador de procesamiento. Dicho cargador se
encuentra alojado en la memoria interna de cdigo del microcontrolador de procesamiento.

FernandoArielBeunza79156

239

Tesis de Grado en Ingeniera Informtica

Capa de aplicacin
(varia segn plataforma)

Capa de presentacin
(varia segn plataforma)

Interfaz RS232 (dispositivo cliente)


(varia segn plataforma)


Interfaz RS232 (mdulo de procesamiento)
serial.h serial.c modem.c

Capa de sesin
sp.h sp.c

Capa de transporte
tp.h tp.c

Capa de red
net.h net.c

Capa de enlace
Resolucin de direcciones
(ARP)

Control de lgica de enlace


(LLC)

arp.h arp.c

llc.h llc.c

Control de acceso al medio (MAC)


mac.h mac.c

Capa fsica (mdulo de procesamiento)


phy.h phy.c


Capa fsica (mdulo de procesamiento de seales)
phy.h phy.c main.c

Figura C1. Diagrama de organizacin de cdigo.

En la figura C1 se detalla la distribucin de cada uno de los archivos del cdigo fuente
dentro del modelo de capas. Se puede observar que las capas se encuentran distribuidas en tres
grupos asociados al lugar donde se encuentran implementadas (mdulo de procesamiento de
seales, mdulo de procesamiento y dispositivo cliente).
Capa de aplicacin
ap.h ap.c

Capa de presentacin
pp.h pp.c

Interfaz RS232 (dispositivo cliente)


serial.h serial.c

Figura C2. Diagrama de organizacin de cdigo del dispositivo cliente para plataforma AT89X5X.

En la figura C2 se puede observar la distribucin de cada uno de los archivos del cdigo
fuente correspondiente a la capa de presentacin y la capa de aplicacin para la plataforma

240

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


AT89X5X. Debajo la capa de presentacin existe una interfaz RS232 encargada de las
comunicaciones entre el modem PLC y el dispositivo cliente.
Capa de aplicacin
modplcap.h modplcap.c

Capa de presentacin

Interfaz capa de enlace

Interfaz capa fsica

modplcpp.h modplcpp.c

modplcdl.h modplcdl.c

modplcphy.h modplcphy.c

Interfaz capa de sesin


modplcsp.h modplcsp.c

Interfaz RS232 Driver (dispositivo cliente)


serial.h serial.c modplc.h modplc.c modsp.h modsp.c moddl.h moddl.c modphy.h
modphy.c moddrv.h moddrv.c modem_driver.c

Figura C3. Diagrama de organizacin de cdigo del dispositivo cliente para plataformas Windows y Linux.

En la figura C3 se detalla la distribucin de cada uno de los archivos del cdigo fuente
correspondiente a la capa de presentacin y la capa de aplicacin para las plataformas Windows y
Linux; adems de las interfaces de acceso a la capa de enlace y a la capa fsica. Tanto la pila de
capas de presentacin y aplicacin, como las interfaces a capa de enlace y capa fsica se comunican
con el modem PLC por medio del driver del mismo.

C.2. Especificacin del cdigo fuente de las


bibliotecas de uso del modem PLC (plataforma
AT89X5X)
En esta seccin se detalla el cdigo fuente de las bibliotecas de uso del modem PLC
compuesto por los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin de las


bibliotecas de uso del modem PLC que no pueden ser modificados.

Archivo modplcap.h: en este archivo se declaran las primitivas correspondientes al


manejo de la capa de aplicacin.

Archivos modplcap*.c: en estos archivos se encuentran implementadas las primitivas


declaradas en el archivo modplcap.h.

Archivo modplcpp.h: en este archivo se declaran las primitivas correspondientes al


manejo de la capa de presentacin. Dichas primitivas brindan la capacidad de trabajar con
estructuras de datos independientes de la plataforma.

Archivos modplcpp*.c: en estos archivos se encuentran implementadas las primitivas


declaradas en el archivo modplcpp.h.

FernandoArielBeunza79156

241

Tesis de Grado en Ingeniera Informtica

Archivo modplcsp.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa de sesin. Dichas primitivas brindan un conjunto de funcionalidades
que permiten la comunicacin con la capa de sesin implementada en el modem PLC.

Archivos modplcsp*.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcsp.h.

Archivo serial.h: en este archivo se declaran primitivas con funcionalidades referentes a


la entrada y salida va UART.

Archivo serial.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo serial.h.

C.2.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz del modem PLC. */


/* Tipos de prompt utilizados. */
#define MODPLC_INITPROMPT
#define MODPLC_LAYPROMPT
#define MODPLC_NORMPROMPT
#define MODPLC_PARAMPROMPT

'#'
'?'
'$'
'>'

/* Tipos de reset. */
#define MODPLC_NORMRESET
#define MODPLC_PARAMRESET

'0'
'$'

/* Capas de acceso. */
#define MODPLC_PHYSICALLAYER
#define MODPLC_DATALINKLAYER
#define MODPLC_SESSIONLAYER

'1'
'2'
'3'

/* Capa de sesin. */
/* Intervalo de tiempo en milisegundos de verificacin de mensaje recibido. */
#define MODPLCSP_POLLINTERVAL
250
/* Cdigo de operaciones de la capa de sesin. */
#define MODPLCSP_RESET
#define MODPLCSP_PUBLISH
#define MODPLCSP_SUBSCRIBE
#define MODPLCSP_LEAVE
#define MODPLCSP_SEND
#define MODPLCSP_RECEIVE
#define MODPLCSP_POLL
#define MODPLCSP_GETPAYLOADSIZE

'0'
'1'
'2'
'3'
'4'
'5'
'6'
'7'

#endif

242

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.2.2. Archivo modplcap.h


/*
modplcap.h:
Declaracin de funciones referentes a la capa de aplicacin del modem PLC.
*/

#if !defined(__MODPLCAP_H__)
#define __MODPLCAP_H__

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica que se encuentre definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#warning "MODPLCAP_MSGSIZE not defined"
#define MODPLCAP_MSGSIZE 0
#endif
#define MODPLCPP_MSGSIZE MODPLCAP_MSGSIZE

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcap_grpid;
/* Identificador de mensaje. */
typedef unsigned short int modplcap_msgid;
/* Tipo de campo. */
typedef unsigned char modplcap_ftype;
/* Tipo mensaje. */
typedef struct
{
modplcap_msgid msgid;
modplcpp_msg msg;
} modplcap_msg;
/* Manejador de capa de aplicacin. */
#if defined SDCC_MODEL_SMALL
typedef struct
{
__data modplcpp_hd *modpphd;
__data modplcap_msg *recvbuff;
void (*recfun)
(__data void *,
__data modplcap_msg *,
__data void *) __reentrant;
__data void *param;

} modplcap_hd;
#else
typedef struct
{
modplcpp_hd *modpphd;

FernandoArielBeunza79156

/* Identificador de mensaje. */
/* Mensaje. */

/* Manejador de interfaz con la


capa de sesin del modem PLC. */
/* Puntero al buffer de
recepcin. */

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */

/* Manejador de interfaz con la


capa de sesin del modem PLC. */

243

Tesis de Grado en Ingeniera Informtica


modplcap_msg *recvbuff;
void (*recfun)
(void *, modplcap_msg *, void *)
__reentrant;
void *param;

/* Puntero al buffer de
recepcin. */

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */

} modplcap_hd;
#endif

/* Definicin de constantes. */
/* Tipos de datos. */
#define MODPLCAP_NULLTYPE
#define MODPLCAP_CHARTYPE
#define MODPLCAP_SINT8TYPE
#define MODPLCAP_UINT8TYPE
#define MODPLCAP_SINT16TYPE
#define MODPLCAP_UINT16TYPE
#define MODPLCAP_SINT32TYPE
#define MODPLCAP_UINT32TYPE
#define MODPLCAP_FLOATTYPE

0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08

/* Declaracin de funciones pblicas. */


/*
Funcin modplcap__init:
Inicializa los recursos utilizados por la capa de aplicacin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
__data modplcap_hd *modplcap__init(int, short int);
#else
modplcap_hd *modplcap__init(int, short int);
#endif
/*
Funcin modplcap__init:
Inicializa los recursos utilizados por la capa de aplicacin del modem PLC.
*/
#define modplcap_init(sid)\
modplcap__init(sid, MODPLCAP_MSGSIZE)
/*
Funcin modplcap_release:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_release(__data modplcap_hd *);
#else
int modplcap_release(modplcap_hd *);
#endif
/*
Funcin modplcap_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_publish(__data modplcap_hd *, modplcap_grpid);
#else
int modplcap_publish(modplcap_hd *, modplcap_grpid);
#endif
/*
Funcin modplcap_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL

244

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int modplcap_subscribe(__data modplcap_hd *, modplcap_grpid);
#else
int modplcap_subscribe(modplcap_hd *, modplcap_grpid);
#endif
/*
Funcin modplcap_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_leave(__data modplcap_hd *, modplcap_grpid);
#else
int modplcap_leave(modplcap_hd *, modplcap_grpid);
#endif
/*
Funcin modplcap_newmsg:
Crea un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_newmsg(__data modplcap_hd *, __data modplcap_msg *,
modplcap_grpid, modplcap_msgid);
#else
int modplcap_newmsg(modplcap_hd *, modplcap_msg *, modplcap_grpid,
modplcap_msgid);
#endif
/*
Funcin modplcap_copymsg:
Crea un copia de un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_copymsg(__data modplcap_msg *, __data modplcap_msg *);
#else
int modplcap_copymsg(modplcap_msg *, modplcap_msg *);
#endif
/*
Funcin modplcap_putfield:
Agrega un nuevo campo al mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_putfield(__data modplcap_msg *, modplcap_ftype, unsigned char,
const __data void *);
#else
int modplcap_putfield(modplcap_msg *, modplcap_ftype, unsigned char,
const void *);
#endif
/*
Funcin modplcap_sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_sendmsg(__data modplcap_msg *);
#else
int modplcap_sendmsg(modplcap_msg *);
#endif
/*
Funcin modplcap_receivemsg:
Recibe un mensaje por medio de la capa de aplicacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_receivemsg(__data modplcap_hd *, __data modplcap_msg *);
#else
int modplcap_receivemsg(modplcap_hd *, modplcap_msg *);
#endif
/*
Funcin modplcap_getfield:

FernandoArielBeunza79156

245

Tesis de Grado en Ingeniera Informtica


Extrae un campo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_getfield(__data modplcap_msg *, __data modplcap_ftype *,
__data unsigned char *, __data void *);
#else
int modplcap_getfield(modplcap_msg *, modplcap_ftype *, unsigned char *,
void *);
#endif
/*
Funcin modplcap_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
modplcap_grpid modplcap_getgrpid(__data modplcap_msg *);
#else
modplcap_grpid modplcap_getgrpid(modplcap_msg *);
#endif
/*
Funcin modplcap_getmsgid:
Devuelve el identificador de mensaje.
*/
#if defined SDCC_MODEL_SMALL
modplcap_msgid modplcap_getmsgid(__data modplcap_msg *);
#else
modplcap_msgid modplcap_getmsgid(modplcap_msg *);
#endif
/*
Funcin modplcap_destroymsg:
Destruye un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_destroymsg(__data modplcap_msg *);
#else
int modplcap_destroymsg(modplcap_msg *);
#endif
/*
Funcin modplcap_setbuffer:
Define el buffer de recepcin.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_setbuffer(__data modplcap_hd *, __data modplcap_msg *);
#else
int modplcap_setbuffer(modplcap_hd *, modplcap_msg *);
#endif
/*
Funcin modplcap_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_notify(__data modplcap_hd *, void (*func)(__data modplcap_hd *,
__data modplcap_msg *, __data void *), __data void *);
#else
int modplcap_notify(modplcap_hd *, void (*func)(modplcap_hd *, modplcap_msg *,
void *), void *);
#endif
/*
Funcin modplcap_poll:
Verifica la llegada de un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_poll(__data modplcap_hd *);
#else
int modplcap_poll(modplcap_hd *);
#endif

246

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcap_status:
Devuelve el estado del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_status(__data modplcap_hd *);
#else
int modplcap_status(modplcap_hd *);
#endif

#endif

C.2.3. Archivo modplcap__init.c


/*
modplcap__init.c:
Implementacin de la funcin modplcap__init de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Variables globales. */
volatile modplcap_hd __modplcap_hd__;

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap__init:
Inicializa los recursos utilizados por la capa de aplicacin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
__data modplcap_hd *modplcap__init(int sid, short int msgsize)
#else
modplcap_hd *modplcap__init(int sid, short int msgsize)
#endif
{
/* Inicializa la interfaz de la capa de presentacindel modem PLC. */
__modplcap_hd__.modpphd = modplcpp__init(sid, msgsize);
if (!__modplcap_hd__.modpphd) return NULL;
/* Inicializa el buffer de recepcin. */
__modplcap_hd__.recvbuff = NULL;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__modplcap_hd__.recfun = NULL;
/* Devuelve el manejador creado. */
return &__modplcap_hd__;
}

FernandoArielBeunza79156

247

Tesis de Grado en Ingeniera Informtica

C.2.4. Archivo modplcap_release.c


/*
modplcap_release.c:
Implementacin de la funcin modplcap_release de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_release:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_release(__data modplcap_hd *hd)
#else
int modplcap_release(modplcap_hd *hd)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Libera los recursos utilizados por la capa de presentacin del modem
PLC. */
return modplcpp_release(hd->modpphd);
}

C.2.5. Archivo modplcap_publish.c


/*
modplcap_publish.c:
Implementacin de la funcin modplcap_publish de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

248

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Implementacin de funciones pblicas. */
/*
Funcin modplcap_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_publish(__data modplcap_hd *hd, modplcap_grpid grpid)
#else
int modplcap_publish(modplcap_hd *hd, modplcap_grpid grpid)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
return modplcpp_publish(hd->modpphd, (modplcap_grpid) grpid);
}

C.2.6. Archivo modplcap_subscribe.c


/*
modplcap_subscribe.c:
Implementacin de la funcin modplcap_subscribe de la capa de aplicacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_subscribe(__data modplcap_hd *hd, modplcap_grpid grpid)
#else
int modplcap_subscribe(modplcap_hd *hd, modplcap_grpid grpid)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
return modplcpp_subscribe(hd->modpphd, (modplcpp_grpid) grpid);
}

FernandoArielBeunza79156

249

Tesis de Grado en Ingeniera Informtica

C.2.7. Archivo modplcap_leave.c


/*
modplcpa_leave.c:
Implementacin de la funcin modplcap_leave de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_leave(__data modplcap_hd *hd, modplcap_grpid grpid)
#else
int modplcap_leave(modplcap_hd *hd, modplcap_grpid grpid)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
return modplcpp_leave(hd->modpphd, (modplcap_grpid) grpid);
}

C.2.8. Archivo modplcap_newmsg.c


/*
modplcap_newmsg.c:
Implementacin de la funcin modplcap_newmsg de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */

250

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcap_newmsg:
Crea un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_newmsg(__data modplcap_hd *hd, __data modplcap_msg *msg,
modplcap_grpid grpid, modplcap_msgid msgid)
#else
int modplcap_newmsg(modplcap_hd *hd, modplcap_msg *msg, modplcap_grpid grpid,
modplcap_msgid msgid)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Inicializa el mensaje. */
msg->msgid = msgid;
if (msgid & 0x8000)
{
if (!modplcpp_newmsg(hd->modpphd, &(msg->msg), grpid,
MODPLCPP_NOSECMSG))
return 0;
}
else
{
if (!modplcpp_newmsg(hd->modpphd, &(msg->msg), grpid, MODPLCPP_SECMSG))
return 0;
}
if (!modplcpp_putfield(&(msg->msg), MODPLCPP_UINT16TYPE, 1, &msgid))
return 0;
return 1;
}

C.2.9. Archivo modplcap_copymsg.c


/*
modplcap_copymsg.c:
Implementacin de la funcin modplcap_copymsg de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_copymsg:
Crea un copia de un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_copymsg(__data modplcap_msg *dest, __data modplcap_msg *src)

FernandoArielBeunza79156

251

Tesis de Grado en Ingeniera Informtica


#else
int modplcap_copymsg(modplcap_msg *dest, modplcap_msg *src)
#endif
{
/* Verifica que el puntero al mensaje original no sea nulo. */
if (!src) return 0;
/* Verifica que el puntero a la copia del mensaje no sea nulo. */
if (!dest) return 0;
/* Copia el contenido del mensaje. */
dest->msgid = src->msgid;
return modplcpp_copymsg(&(dest->msg), &(src->msg));
}

C.2.10. Archivo modplcap_putfield.c


/*
modplcap_putfield.c:
Implementacin de la funcin modplcap_putfield de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_putfield:
Agrega un nuevo campo al mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_putfield(__data modplcap_msg *msg, modplcap_ftype type,
unsigned char count, const __data void *dat)
#else
int modplcap_putfield(modplcap_msg *msg, modplcap_ftype type,
unsigned char count, const void *dat)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Agrega un nuevo campo al mensaje. */
return modplcpp_putfield(&(msg->msg), type, count, dat);
}

C.2.11. Archivo modplcap_sendmsg.c


/*
modplcap_sendmsg.c:
Implementacin de la funcin modplcap_sendmsg de la capa de aplicacin del
modem PLC.

252

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_sendmsg(__data modplcap_msg *msg)
#else
int modplcap_sendmsg(modplcap_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Enva un mensaje. */
return modplcpp_sendmsg(&(msg->msg));
}

C.2.12. Archivo modplcap_receivemsg.c


/*
modplcap_receivemsg.c:
Implementacin de la funcin modplcap_receivemsg de la capa de aplicacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_receivemsg:
Recibe un mensaje por medio de la capa de aplicacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_receivemsg(__data modplcap_hd *hd, __data modplcap_msg *msg)
#else

FernandoArielBeunza79156

253

Tesis de Grado en Ingeniera Informtica


int modplcap_receivemsg(modplcap_hd *hd, modplcap_msg *msg)
#endif
{
/* Variables. */
modplcpp_ftype type;
/* Tipo de campo. */
unsigned char count;
/* Multiplicidad del campo. */

/* Verifica el estado del modem PLC. */


if (!modplcap_status(hd)) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Espera la llegada de un mensaje. */
while(!modplcap_poll(hd));
/* Recibe el mensaje. */
while(1)
{
if (!modplcpp_receivemsg(hd->modpphd, &(msg->msg)))
break;
if (!modplcpp_getfield(&(msg->msg), &type, &count, &(msg->msgid)))
break;
if (type != MODPLCPP_UINT16TYPE)
break;
if (count != 1)
break;
return 1;
}
modplcap_destroymsg(msg);
return 0;
}

C.2.13. Archivo modplcap_getfield.c


/*
modplcap_getfield.c:
Implementacin de la funcin modplcap_getfield de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_getfield:
Extrae un campo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_getfield(__data modplcap_msg *msg, __data modplcap_ftype *type,
__data unsigned char *count, __data void *dat)
#else
int modplcap_getfield(modplcap_msg *msg, modplcap_ftype *type,

254

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


unsigned char *count, void *dat)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Extrae un campo del mensaje. */
return modplcpp_getfield(&(msg->msg), type, count, dat);
}

C.2.14. Archivo modplcap_getgrpid.c


/*
modplcap_getgrpid.c:
Implementacin de la funcin modplcap_getgrpid de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
modplcap_grpid modplcap_getgrpid(__data modplcap_msg *msg)
#else
modplcap_grpid modplcap_getgrpid(modplcap_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return modplcpp_getgrpid(&(msg->msg));
}

C.2.15. Archivo modplcap_getmsgid.c


/*
modplcap_getmsgid.c:
Implementacin de la funcin modplcap_getmsgid de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

FernandoArielBeunza79156

255

Tesis de Grado en Ingeniera Informtica


/* Verifica si se encuentra definido el tamao mximo del mensaje. */
#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_getmsgid:
Devuelve el identificador de mensaje.
*/
#if defined SDCC_MODEL_SMALL
modplcap_msgid modplcap_getmsgid(__data modplcap_msg *msg)
#else
modplcap_msgid modplcap_getmsgid(modplcap_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de mensaje. */
return msg->msgid;
}

C.2.16. Archivo modplcap_destroymsg.c


/*
modplcap_destroymsg.c:
Implementacin de la funcin modplcap_destroymsg de la capa de aplicacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_destroymsg:
Destruye un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_destroymsg(__data modplcap_msg *msg)
#else
int modplcap_destroymsg(modplcap_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Destruye el mensaje. */

256

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


msg->msgid = 0;
return modplcpp_destroymsg(&(msg->msg));
}

C.2.17. Archivo modplcap_setbuffer.c


/*
modplcap_setbuffer.c:
Implementacin de la funcin modplcap_setbuffer de la capa de aplicacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_setbuffer:
Define el buffer de recepcin.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_setbuffer(__data modplcap_hd *hd, __data modplcap_msg *buffer)
#else
int modplcap_setbuffer(modplcap_hd *hd, modplcap_msg *buffer)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcap_status(hd)) return 0;
/* Define el buffer de recepcin. */
hd->recvbuff = buffer;
return 1;
}

C.2.18. Archivo modplcap_notify.c


/*
modplcap_notify.c:
Implementacin de la funcin modplcap_notify de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

FernandoArielBeunza79156

257

Tesis de Grado en Ingeniera Informtica

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Declaracin de funciones privadas. */


#if defined SDCC_MODEL_SMALL
static void __modplcap_procmsg__(__data modplcpp_hd *, __data modplcpp_msg *,
__data void *) __reentrant;
#else
static void __modplcap_procmsg__(modplcpp_hd *, modplcpp_msg *, void *)
__reentrant;
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_notify(__data modplcap_hd *hd, void (*func)(__data modplcap_hd *,
__data modplcap_msg *, __data void *), __data void *param)
#else
int modplcap_notify(modplcap_hd *hd, void (*func)(modplcap_hd *,
modplcap_msg *, void *), void *param)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Define un manejador de mensajes recibidos. */
#if defined SDCC_MODEL_SMALL
hd->recfun = (void (*)(__data void *, __data modplcap_msg *,
__data void *)) func;
#else
hd->recfun = (void (*)(void *, modplcap_msg *, void *)) func;
#endif
if (!modplcpp_notify(hd->modpphd, __modplcap_procmsg__, hd))
{
hd->recfun = NULL;
return 0;
}
hd->param = param;
return 1;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcap_procmsg__:
Procesa un mensaje recibido por medio de la capa de presentacin.
*/
#if defined SDCC_MODEL_SMALL
static void __modplcap_procmsg__(__data modplcpp_hd *hd,
__data modplcpp_msg *msg,
__data void *param) __reentrant
#else
static void __modplcap_procmsg__(modplcpp_hd *hd, modplcpp_msg *msg,
void *param) __reentrant
#endif
{
/* Variables. */
#if defined SDCC_MODEL_SMALL
__data modplcap_hd *aphd;
/* Manejador de capa de
aplicacin. */
#else
modplcap_hd *aphd;
/* Manejador de capa de

258

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


aplicacin. */
#endif
/* Carga el manejador de capa de presentacin. */
#if defined SDCC_MODEL_SMALL
aphd = (__data modplcap_hd *) param;
#else
aphd = (modplcap_hd *) param;
#endif
/* Recibe el mensaje. */
if (aphd->recvbuff)
{
if (!modplcap_receivemsg(aphd, aphd->recvbuff)) return;
}
/* Invoca a la funcin de atencin de recepcin de mensajes registrada. */
if (!aphd->recfun) return;
aphd->recfun(aphd, aphd->recvbuff, aphd->param);
hd;
msg;
}

C.2.19. Archivo modplcap_poll.c


/*
modplcap_poll.c:
Implementacin de la funcin modplcap_poll de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_poll:
Verifica la llegada de un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_poll(__data modplcap_hd *hd)
#else
int modplcap_poll(modplcap_hd *hd)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Verifica la llegada de un nuevo mensaje. */
return modplcpp_poll(hd->modpphd);
}

FernandoArielBeunza79156

259

Tesis de Grado en Ingeniera Informtica

C.2.20. Archivo modplcap_status.c


/*
modplcap_status.c:
Implementacin de la funcin modplcap_status de la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCAP_MSGSIZE)
#define MODPLCAP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcap.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_status:
Devuelve el estado del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcap_status(__data modplcap_hd *hd)
#else
int modplcap_status(modplcap_hd *hd)
#endif
{
/* Verifica que el manejador de capa de aplicacin del modem PLC exista. */
if (!hd) return 0;
/* Devuelve el estado del modem PLC. */
return modplcpp_status(hd->modpphd);
}

C.2.21. Archivo modplcpp.h


/*
modplcpp.h:
Declaracin de funciones referentes a la capa de presentacin del modem
PLC.
*/

#if !defined(__MODPLCPP_H__)
#define __MODPLCPP_H__

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica que se encuentre definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#warning "MODPLCPP_MSGSIZE not defined"
#define MODPLCPP_MSGSIZE 0
#endif
#if (MODPLCPP_MSGSIZE < 1)
#undef MODPLCPP_MSGSIZE

260

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#define MODPLCPP_MSGSIZE 1
#endif
#define MODPLCSP_MSGSIZE MODPLCPP_MSGSIZE

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcpp_grpid;
/* Tipo de mensaje. */
typedef unsigned char modplcpp_mtype;
/* Tipo de campo. */
typedef unsigned char modplcpp_ftype;
/* Tipo mensaje. */
typedef struct
{
unsigned short int startoffset;
unsigned short int endoffset;
modplcpp_grpid grpid;
modplcpp_mtype mtype;
#if defined SDCC_MODEL_SMALL
__data void *pphd;

/*
/*
/*
/*

Comienzo del mensaje. */


Fin del mensaje. */
Identificador de grupo. */
Tipo de mensaje. */

/* Manejador de capa de
presentacin. */

#else
void *pphd;

/* Manejador de capa de
presentacin. */

#endif
unsigned char dat[MODPLCPP_MSGSIZE];
} modplcpp_msg;

/* Contenido del mensaje. */

/* Manejador de capa de presentacin. */


typedef struct
{
short int msgsize;
#if defined SDCC_MODEL_SMALL
__data modplcsp_hd *modsphd;
__data modplcpp_msg *recvbuff;
void (*recfun)
(__data void *,
__data modplcpp_msg *,
__data void *) __reentrant;
__data void *param;

/* Cantidad mxima de bytes que


puede contener un mensaje. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */
/* Puntero al buffer de
recepcin. */

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */

#else
modplcsp_hd *modsphd;
modplcpp_msg *recvbuff;
void (*recfun)
(void *, modplcpp_msg *, void *)
__reentrant;
void *param;

/* Manejador de interfaz con la


capa de sesin del modem PLC. */
/* Puntero al buffer de
recepcin. */

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */

#endif
} modplcpp_hd;

FernandoArielBeunza79156

261

Tesis de Grado en Ingeniera Informtica


/* Definicin de constantes. */
/* Tipo de mensaje. */
#define MODPLCPP_SECMSG
#define MODPLCPP_NOSECMSG

0x00
0x01

/* Tipos de datos. */
#define MODPLCPP_NULLTYPE
#define MODPLCPP_CHARTYPE
#define MODPLCPP_SINT8TYPE
#define MODPLCPP_UINT8TYPE
#define MODPLCPP_SINT16TYPE
#define MODPLCPP_UINT16TYPE
#define MODPLCPP_SINT32TYPE
#define MODPLCPP_UINT32TYPE
#define MODPLCPP_FLOATTYPE

0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08

/* Declaracin de funciones pblicas. */


/*
Funcin modplcpp__init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/
#if defined SDCC_MODEL_SMALL
__data modplcpp_hd *modplcpp__init(int, short int);
#else
modplcpp_hd *modplcpp__init(int, short int);
#endif
/*
Funcin modplcpp_init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/
#define modplcpp_init(sid)\
modplcpp__init(sid, MODPLCPP_MSGSIZE)
/*
Funcin modplcpp_release:
Libera los recursos utilizados por la capa de presentacin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_release(__data modplcpp_hd *);
#else
int modplcpp_release(modplcpp_hd *);
#endif
/*
Funcin modplcpp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_publish(__data modplcpp_hd *, modplcpp_grpid);
#else
int modplcpp_publish(modplcpp_hd *, modplcpp_grpid);
#endif
/*
Funcin modplcpp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_subscribe(__data modplcpp_hd *, modplcpp_grpid);
#else
int modplcpp_subscribe(modplcpp_hd *, modplcpp_grpid);
#endif
/*

262

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin modplcpp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_leave(__data modplcpp_hd *, modplcpp_grpid);
#else
int modplcpp_leave(modplcpp_hd *, modplcpp_grpid);
#endif
/*
Funcin modplcpp_newmsg:
Crea un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_newmsg(__data modplcpp_hd *, __data modplcpp_msg *,
modplcpp_grpid, modplcpp_mtype);
#else
int modplcpp_newmsg(modplcpp_hd *, modplcpp_msg *, modplcpp_grpid,
modplcpp_mtype);
#endif
/*
Funcin modplcpp_copymsg:
Crea un copia de un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_copymsg(__data modplcpp_msg *, __data modplcpp_msg *);
#else
int modplcpp_copymsg(modplcpp_msg *, modplcpp_msg *);
#endif
/*
Funcin modplcpp_putfield:
Agrega un nuevo campo al mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_putfield(__data modplcpp_msg *, modplcpp_ftype, unsigned char,
const __data void *);
#else
int modplcpp_putfield(modplcpp_msg *, modplcpp_ftype, unsigned char,
const void *);
#endif
/*
Funcin modplcpp_sendmsg:
Enva un mensaje por medio de la capa de presentacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_sendmsg(__data modplcpp_msg *);
#else
int modplcpp_sendmsg(modplcpp_msg *);
#endif
/*
Funcin modplcpp_receivemsg:
Recibe un mensaje por medio de la capa de presentacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_receivemsg(__data modplcpp_hd *, __data modplcpp_msg *);
#else
int modplcpp_receivemsg(modplcpp_hd *, modplcpp_msg *);
#endif
/*
Funcin modplcpp_getfield:
Extrae un campo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_getfield(__data modplcpp_msg *, __data modplcpp_ftype *,
__data unsigned char *, __data void *);
#else

FernandoArielBeunza79156

263

Tesis de Grado en Ingeniera Informtica


int modplcpp_getfield(modplcpp_msg *, modplcpp_ftype *, unsigned char *,
void *);
#endif
/*
Funcin modplcpp_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
modplcpp_grpid modplcpp_getgrpid(__data modplcpp_msg *);
#else
modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *);
#endif
/*
Funcin modplcpp_destroymsg:
Destruye un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_destroymsg(__data modplcpp_msg *);
#else
int modplcpp_destroymsg(modplcpp_msg *);
#endif
/*
Funcin modplcpp_setbuffer:
Define el buffer de recepcin.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_setbuffer(__data modplcpp_hd *, __data modplcpp_msg *);
#else
int modplcpp_setbuffer(modplcpp_hd *, modplcpp_msg *);
#endif
/*
Funcin modplcpp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_notify(__data modplcpp_hd *, void (*func)(__data modplcpp_hd *,
__data modplcpp_msg *, __data void *), __data void *);
#else
int modplcpp_notify(modplcpp_hd *, void (*func)(modplcpp_hd *, modplcpp_msg *,
void *), void *);
#endif
/*
Funcin modplcpp_poll:
Verifica la llegada de un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_poll(__data modplcpp_hd *);
#else
int modplcpp_poll(modplcpp_hd *);
#endif
/*
Funcin modplcpp_status:
Devuelve el estado del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_status(__data modplcpp_hd *);
#else
int modplcpp_status(modplcpp_hd *);
#endif

#endif

264

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.2.22. Archivo modplcpp__init.c


/*
modplcpp__init.c:
Implementacin de la funcin modplcpp__init de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Variables globales. */
volatile modplcpp_hd __modplcpp_hd__;

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp__init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/
#if defined SDCC_MODEL_SMALL
__data modplcpp_hd *modplcpp__init(int sid, short int msgsize)
#else
modplcpp_hd *modplcpp__init(int sid, short int msgsize)
#endif
{
/* Inicializa la interfaz de la capa de sesin del modem PLC. */
__modplcpp_hd__.modsphd = modplcsp__init(sid, msgsize);
if (!__modplcpp_hd__.modsphd) return NULL;
/* Define la cantidad mxima de bytes que puede contener un mensaje. */
__modplcpp_hd__.msgsize = msgsize;
/* Inicializa el buffer de recepcin. */
__modplcpp_hd__.recvbuff = NULL;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__modplcpp_hd__.recfun = NULL;
/* Devuelve el manejador creado. */
return &__modplcpp_hd__;
}

C.2.23. Archivo modplcpp_release.c


/*
modplcpp_release.c:
Implementacin de la funcin modplcpp_release de la capa de presentacin
del modem PLC.
*/

FernandoArielBeunza79156

265

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_release:
Libera los recursos utilizados por la capa de presentacin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_release(__data modplcpp_hd *hd)
#else
int modplcpp_release(modplcpp_hd *hd)
#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Libera los recursos utilizados por la capa de sesin del modem PLC. */
return modplcsp_release(hd->modsphd);
}

C.2.24. Archivo modplcpp_publish.c


/*
modplcpp_publish.c:
Implementacin de la funcin modplcpp_publish de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_publish(__data modplcpp_hd *hd, modplcpp_grpid grpid)
#else
int modplcpp_publish(modplcpp_hd *hd, modplcpp_grpid grpid)

266

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
return modplcsp_publish(hd->modsphd, (modplcsp_grpid) grpid);
}

C.2.25. Archivo modplcpp_subscribe.c


/*
modplcpp_subscribe.c:
Implementacin de la funcin modplcpp_subscribe de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_subscribe(__data modplcpp_hd *hd, modplcpp_grpid grpid)
#else
int modplcpp_subscribe(modplcpp_hd *hd, modplcpp_grpid grpid)
#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
return modplcsp_subscribe(hd->modsphd, (modplcsp_grpid) grpid);
}

C.2.26. Archivo modplcpp_leave.c


/*
modplcpp_leave.c:
Implementacin de la funcin modplcpp_leave de la capa de presentacin del
modem PLC.
*/

/* Archivos includos necesarios. */

FernandoArielBeunza79156

267

Tesis de Grado en Ingeniera Informtica


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_leave(__data modplcpp_hd *hd, modplcpp_grpid grpid)
#else
int modplcpp_leave(modplcpp_hd *hd, modplcpp_grpid grpid)
#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
return modplcsp_leave(hd->modsphd, (modplcsp_grpid) grpid);
}

C.2.27. Archivo modplcpp_newmsg.c


/*
modplcpp_newmsg.c:
Implementacin de la funcin modplcpp_newmsg de la capa de presentacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_newmsg:
Crea un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_newmsg(__data modplcpp_hd *hd, __data modplcpp_msg *msg,
modplcpp_grpid grpid, modplcpp_mtype mtype)
#else
int modplcpp_newmsg(modplcpp_hd *hd, modplcpp_msg *msg, modplcpp_grpid grpid,
modplcpp_mtype mtype)

268

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Inicializa el mensaje. */
msg->startoffset = 0;
msg->endoffset = 0;
msg->grpid = grpid;
msg->mtype = mtype;
msg->pphd = hd;
return 1;
}

C.2.28. Archivo modplcpp_copymsg.c


/*
modplcpp_copymsg.c:
Implementacin de la funcin modplcpp_copymsg de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_copymsg:
Crea un copia de un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_copymsg(__data modplcpp_msg *dest, __data modplcpp_msg *src)
#else
int modplcpp_copymsg(modplcpp_msg *dest, modplcpp_msg *src)
#endif
{
/* Variables. */
short int i;
/* Contador. */

/* Verifica que el puntero al mensaje original no sea nulo. */


if (!src) return 0;
/* Verifica que el puntero a la copia del mensaje no sea nulo. */
if (!dest) return 0;
/* Copia el contenido del mensaje. */
dest->startoffset = src->startoffset;
dest->endoffset = src->endoffset;
dest->grpid = src->grpid;
dest->mtype = src->mtype;

FernandoArielBeunza79156

269

Tesis de Grado en Ingeniera Informtica


dest->pphd = src->pphd;
for(i = 0; i < dest->endoffset; i++) dest->dat[i] = src->dat[i];
/* xito. */
return 1;
}

C.2.29. Archivo modplcpp_putfield.c


/*
modplcpp_putfield.c:
Implementacin de la funcin modplcpp_putfield de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_putfield:
Agrega un nuevo campo al mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_putfield(__data modplcpp_msg *msg, modplcpp_ftype type,
unsigned char count, const __data void *dat)
#else
int modplcpp_putfield(modplcpp_msg *msg, modplcpp_ftype type,
unsigned char count, const void *dat)
#endif
{
/* Variables. */
short int msgsize;
/* Tamao del mensaje. */
#if defined SDCC_MODEL_SMALL
__data unsigned char *ptr;
/* Puntero a los datos. */
#else
unsigned char *ptr;
/* Puntero a los datos. */
#endif

/* Verifica que el puntero al mensaje no sea nulo. */


if (!msg) return 0;
/* Inicializa el puntero a los datos. */
#if defined SDCC_MODEL_SMALL
ptr = (__data unsigned char *) dat;
#else
ptr = (unsigned char *) dat;
#endif
/* Verifica si el nuevo campo puede entrar en el mensaje. */
msgsize = msg->endoffset;
msgsize += sizeof(modplcpp_ftype);
msgsize += sizeof(unsigned char);
if ((type == MODPLCPP_CHARTYPE) || (type == MODPLCPP_UINT8TYPE))

270

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


msgsize += count * sizeof(unsigned char);
else if (type == MODPLCPP_SINT8TYPE)
msgsize += count * sizeof(char);
else if ((type == MODPLCPP_SINT16TYPE) || (type == MODPLCPP_UINT16TYPE))
msgsize += count * sizeof(unsigned short int);
else if ((type == MODPLCPP_SINT32TYPE) || (type == MODPLCPP_UINT32TYPE))
msgsize += count * sizeof(unsigned long int);
else if (type == MODPLCPP_FLOATTYPE)
msgsize += count * sizeof(float);
else
return 0;
if (msgsize > modplcsp_getpayloadsize(((modplcpp_hd *)
(msg->pphd))->modsphd))
return 0;
/* Agrega el tipo de dato. */
*(msg->dat + msg->endoffset) = type;
msg->endoffset += sizeof(modplcpp_ftype);
/* Agrega la cantidad de datos. */
*(msg->dat + msg->endoffset) = count;
msg->endoffset += sizeof(unsigned char);
/* Agrega datos tipo caracter o entero de 8 bits sin signo. */
if ((type == MODPLCPP_CHARTYPE) || (type == MODPLCPP_UINT8TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(unsigned char);
msg->endoffset += sizeof(unsigned char);
}
}
/* Agrega datos tipo entero de 8 bits con signo. */
else if (type == MODPLCPP_SINT8TYPE)
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(char);
msg->endoffset += sizeof(char);
}
}
/* Agrega datos tipo entero de 16 bits. */
else if ((type == MODPLCPP_SINT16TYPE) || (type == MODPLCPP_UINT16TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset + 0) = *(ptr + 1);
*(msg->dat + msg->endoffset + 1) = *(ptr + 0);
ptr += sizeof(unsigned short int);
msg->endoffset += sizeof(unsigned short int);
}
}
/* Agrega datos tipo entero de 32 bits. */
else if ((type == MODPLCPP_SINT32TYPE) || (type == MODPLCPP_UINT32TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset + 0) = *(ptr + 3);
*(msg->dat + msg->endoffset + 1) = *(ptr + 2);
*(msg->dat + msg->endoffset + 2) = *(ptr + 1);
*(msg->dat + msg->endoffset + 3) = *(ptr + 0);
ptr += sizeof(unsigned long int);
msg->endoffset += sizeof(unsigned long int);
}
}
/* Agrega datos tipo punto flotante. */
else if (type == MODPLCPP_FLOATTYPE)
{
while(count--)

FernandoArielBeunza79156

271

Tesis de Grado en Ingeniera Informtica


{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(float);
msg->endoffset += sizeof(float);
}
}
/* xito. */
return 1;
}

C.2.30. Archivo modplcpp_sendmsg.c


/*
modplcpp_sendmsg.c:
Implementacin de la funcin modplcpp_sendmsg de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_sendmsg:
Enva un mensaje por medio de la capa de presentacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_sendmsg(__data modplcpp_msg *msg)
#else
int modplcpp_sendmsg(modplcpp_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Enva un mensaje. */
if (modplcsp_send(((modplcpp_hd *) (msg->pphd))->modsphd, msg->grpid,
msg->mtype, msg->dat, msg->endoffset) == msg->endoffset)
return 1;
return 0;
}

C.2.31. Archivo modplcpp_receivemsg.c


/*
modplcpp_receivemsg.c:
Implementacin de la funcin modplcpp_receivemsg de la capa de presentacin
del modem PLC.
*/

272

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_receivemsg:
Recibe un mensaje por medio de la capa de presentacin.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_receivemsg(__data modplcpp_hd *hd, __data modplcpp_msg *msg)
#else
int modplcpp_receivemsg(modplcpp_hd *hd, modplcpp_msg *msg)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcpp_status(hd)) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Espera la llegada de un mensaje. */
while(!modplcpp_poll(hd));
/* Recibe el mensaje. */
msg->startoffset = 0;
msg->endoffset = modplcsp_receive(hd->modsphd, &(msg->grpid), msg->dat,
hd->msgsize);
return (msg->endoffset != 0);
}

C.2.32. Archivo modplcpp_getfield.c


/*
modplcpp_getfield.c:
Implementacin de la funcin modplcpp_getfield de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*

FernandoArielBeunza79156

273

Tesis de Grado en Ingeniera Informtica


Funcin modplcpp_getfield:
Extrae un campo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_getfield(__data modplcpp_msg *msg, __data modplcpp_ftype *type,
__data unsigned char *count, __data void *dat)
#else
int modplcpp_getfield(modplcpp_msg *msg, modplcpp_ftype *type,
unsigned char *count, void *dat)
#endif
{
/* Variables. */
unsigned char c;
/* Contador. */
#if defined SDCC_MODEL_SMALL
__data unsigned char *ptr;
/* Puntero a los datos. */
#else
unsigned char *ptr;
/* Puntero a los datos. */
#endif

/* Verifica que el puntero al mensaje no sea nulo. */


if (!msg) return 0;
/* Inicializa el puntero a los datos. */
#if defined SDCC_MODEL_SMALL
ptr = (__data unsigned char *) dat;
#else
ptr = (unsigned char *) dat;
#endif
/* Extrae el tipo de dato. */
*type = *(msg->dat + msg->startoffset);
msg->startoffset += sizeof(modplcpp_ftype);
/* Extrae la cantidad de datos. */
c = *(msg->dat + msg->startoffset);
*count = c;
msg->startoffset += sizeof(unsigned char);
/* Agrega datos tipo caracter o entero de 8 bits. */
if ((*type == MODPLCPP_CHARTYPE) || (*type == MODPLCPP_SINT8TYPE) ||
(*type == MODPLCPP_UINT8TYPE))
{
while(c --)
{
*ptr = *(msg->dat + msg->startoffset);
ptr += sizeof(unsigned char);
msg->startoffset += sizeof(unsigned char);
}
return 1;
}
/* Agrega datos tipo entero de 16 bits. */
if ((*type == MODPLCPP_SINT16TYPE) || (*type == MODPLCPP_UINT16TYPE))
{
while(c --)
{
*(ptr + 1) = *(msg->dat + msg->startoffset + 0);
*(ptr + 0) = *(msg->dat + msg->startoffset + 1);
ptr += sizeof(unsigned short int);
msg->startoffset += sizeof(unsigned short int);
}
return 1;
}
/* Agrega datos tipo entero de 32 bits. */
if ((*type == MODPLCPP_SINT32TYPE) || (*type == MODPLCPP_UINT32TYPE))
{
while(c --)
{
*(ptr + 3) = *(msg->dat + msg->startoffset + 0);

274

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*(ptr + 2) = *(msg->dat + msg->startoffset + 1);
*(ptr + 1) = *(msg->dat + msg->startoffset + 2);
*(ptr + 0) = *(msg->dat + msg->startoffset + 3);
ptr += sizeof(unsigned long int);
msg->startoffset += sizeof(unsigned long int);
}
return 1;
}
/* Agrega datos tipo punto flotante. */
if (*type == MODPLCPP_FLOATTYPE)
{
while(c --)
{
*ptr = *(msg->dat + msg->startoffset);
ptr += sizeof(float);
msg->startoffset += sizeof(float);
}
return 1;
}
/* Tipo de dato desconocido. */
msg->startoffset -= sizeof(unsigned char);
msg->startoffset -= sizeof(modplcpp_ftype);
return 0;
}

C.2.33. Archivo modplcpp_getgrpid.c


/*
modplcpp_getgrpid.c:
Implementacin de la funcin modplcpp_getgrpid de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
#if defined SDCC_MODEL_SMALL
modplcpp_grpid modplcpp_getgrpid(__data modplcpp_msg *msg)
#else
modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return msg->grpid;
}

FernandoArielBeunza79156

275

Tesis de Grado en Ingeniera Informtica

C.2.34. Archivo modplcpp_destroymsg.c


/*
modplcpp_destroymsg.c:
Implementacin de la funcin modplcpp_destroymsg de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_destroymsg:
Destruye un mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_destroymsg(__data modplcpp_msg *msg)
#else
int modplcpp_destroymsg(modplcpp_msg *msg)
#endif
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Destruye el mensaje. */
msg->startoffset = 0;
msg->endoffset = 0;
msg->grpid = 0;
msg->mtype = 0;
msg->pphd = NULL;
return 1;
}

C.2.35. Archivo modplcpp_setbuffer.c


/*
modplcpp_setbuffer.c:
Implementacin de la funcin modplcsp_setbuffer de la capa de presentacin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

276

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_setbuffer:
Define el buffer de recepcin.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_setbuffer(__data modplcpp_hd *hd, __data modplcpp_msg *buffer)
#else
int modplcpp_setbuffer(modplcpp_hd *hd, modplcpp_msg *buffer)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcpp_status(hd)) return 0;
/* Define el buffer de recepcin. */
hd->recvbuff = buffer;
return 1;
}

C.2.36. Archivo modplcpp_notify.c


/*
modplcpp_notify.c:
Implementacin de la funcin modplcpp_notify de la capa de presentacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Declaracin de funciones privadas. */


#if defined SDCC_MODEL_SMALL
static void __modplcpp_procmsg__(__data modplcsp_hd *, modplcsp_grpid,
__data void *, short int,
__data void *) __reentrant;
#else
static void __modplcpp_procmsg__(modplcsp_hd *, modplcsp_grpid, void *,
short int, void *) __reentrant;
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_notify(__data modplcpp_hd *hd, void (*func)(__data modplcpp_hd *,

FernandoArielBeunza79156

277

Tesis de Grado en Ingeniera Informtica


__data modplcpp_msg *, __data void *), __data void *param)
#else
int modplcpp_notify(modplcpp_hd *hd, void (*func)(modplcpp_hd *,
modplcpp_msg *, void *), void *param)
#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Define un manejador de mensajes recibidos. */
#if defined SDCC_MODEL_SMALL
hd->recfun = (void (*)(__data void *, __data modplcpp_msg *,
__data void *)) func;
#else
hd->recfun = (void (*)(void *, modplcpp_msg *, void *)) func;
#endif
if (!modplcsp_notify(hd->modsphd, __modplcpp_procmsg__, hd))
{
hd->recfun = NULL;
return 0;
}
hd->param = param;
return 1;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcpp_procmsg__:
Procesa un mensaje recibido por medio de la capa de sesin.
*/
#if defined SDCC_MODEL_SMALL
static void __modplcpp_procmsg__(__data modplcsp_hd *hd, modplcsp_grpid grpid,
__data void *msg, short int msgsize,
__data void *param) __reentrant
#else
static void __modplcpp_procmsg__(modplcsp_hd *hd, modplcsp_grpid grpid,
void *msg, short int msgsize,
void *param) __reentrant
#endif
{
/* Variables. */
#if defined SDCC_MODEL_SMALL
__data modplcpp_hd *pphd;
/* Manejador de capa de
presentacin. */
#else
modplcpp_hd *pphd;
/* Manejador de capa de
presentacin. */
#endif
/* Carga el manejador de capa de presentacin. */
#if defined SDCC_MODEL_SMALL
pphd = (__data modplcpp_hd *) param;
#else
pphd = (modplcpp_hd *) param;
#endif
/* Recibe el mensaje. */
if (pphd->recvbuff)
{
if (!modplcpp_receivemsg(pphd, pphd->recvbuff)) return;
}
/* Invoca a la funcin de atencin de recepcin de mensajes registrada. */
if (!pphd->recfun) return;
pphd->recfun(pphd, pphd->recvbuff, pphd->param);
modplcpp_destroymsg(pphd->recvbuff);
hd;
grpid;

278

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


msg;
msgsize;
}

C.2.37. Archivo modplcpp_poll.c


/*
modplcpp_poll.c:
Implementacin de la funcin modplcpp_poll de la capa de presentacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_poll:
Verifica la llegada de un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_poll(__data modplcpp_hd *hd)
#else
int modplcpp_poll(modplcpp_hd *hd)
#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Verifica la llegada de un nuevo mensaje. */
return modplcsp_poll(hd->modsphd);
}

C.2.38. Archivo modplcpp_status.c


/*
modplcpp_status.c:
Implementacin de la funcin modplcpp_status de la capa de presentacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCPP_MSGSIZE)
#define MODPLCPP_MSGSIZE 0
#endif

FernandoArielBeunza79156

279

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include "modplcpp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_status:
Devuelve el estado del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcpp_status(__data modplcpp_hd *hd)
#else
int modplcpp_status(modplcpp_hd *hd)
#endif
{
/* Verifica que el manejador de capa de presentacin del modem PLC
exista. */
if (!hd) return 0;
/* Devuelve el estado del modem PLC. */
return modplcsp_status(hd->modsphd);
}

C.2.39. Archivo modplcsp.h


/*
modplcsp.h:
Declaracin de funciones referentes a la interfaz de la capa de sesin del
modem PLC.
*/

#if !defined(__MODPLCSP_H__)
#define __MODPLCSP_H__

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica que se encuentre definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#warning "MODPLCSP_MSGSIZE not defined"
#define MODPLCSP_MSGSIZE 0
#endif

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcsp_grpid;
/* Manejador de interfaz con la capa de sesin del modem PLC. */
typedef struct
{
int status;
/* Estado del modem PLC. */
short int msgsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
short int buffsize;
/* Tamao del buffer de
recepcin. */
short int polltimer;
/* Temporizador de verificacin de
recepcin de mensaje. */
short int payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
#if defined SDCC_MODEL_SMALL
__data unsigned char *recvbuff;
/* Puntero al buffer de

280

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


recepcin. */
void (*recfun)
(__data void *, modplcsp_grpid,
__data void *, short int,
__data void *) __reentrant;
__data void *param;

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */

#else
unsigned char *recvbuff;
void (*recfun)
(void *, modplcsp_grpid, void *,
short int, void *) __reentrant;
void *param;

/* Puntero al buffer de
recepcin. */

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */

#endif
} modplcsp_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin modplcsp__init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
__data modplcsp_hd *modplcsp__init(int, short int);
#else
modplcsp_hd *modplcsp__init(int, short int);
#endif
/*
Funcin modplcsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
#define modplcsp_init(sid)\
modplcsp__init(sid, MODPLCSP_MSGSIZE)
/*
Funcin modplcsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_release(__data modplcsp_hd *);
#else
int modplcsp_release(modplcsp_hd *);
#endif
/*
Funcin modplcsp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_publish(__data modplcsp_hd *, modplcsp_grpid);
#else
int modplcsp_publish(modplcsp_hd *, modplcsp_grpid);
#endif
/*
Funcin modplcsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_subscribe(__data modplcsp_hd *, modplcsp_grpid);
#else
int modplcsp_subscribe(modplcsp_hd *, modplcsp_grpid);
#endif

FernandoArielBeunza79156

281

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_leave(__data modplcsp_hd *, modplcsp_grpid);
#else
int modplcsp_leave(modplcsp_hd *, modplcsp_grpid);
#endif
/*
Funcin modplcsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
short int modplcsp_send(__data modplcsp_hd *, modplcsp_grpid, unsigned char,
const __data void *, short int);
#else
short int modplcsp_send(modplcsp_hd *, modplcsp_grpid, unsigned char,
const void *, short int);
#endif
/*
Funcin modplcsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
short int modplcsp_receive(__data modplcsp_hd *, __data modplcsp_grpid *,
__data void *, short int);
#else
short int modplcsp_receive(modplcsp_hd *, modplcsp_grpid *, void *, short int);
#endif
/*
Funcin modplcsp_setbuffer:
Define el buffer de recepcin.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_setbuffer(__data modplcsp_hd *, __data void *, short int);
#else
int modplcsp_setbuffer(modplcsp_hd *, void *, short int);
#endif
/*
Funcin modplcsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_notify(__data modplcsp_hd *, void (*func)(__data modplcsp_hd *,
modplcsp_grpid, __data void *, short int, __data void *),
__data void *);
#else
int modplcsp_notify(modplcsp_hd *, void (*func)(modplcsp_hd *, modplcsp_grpid,
void *, short int, void *), void *);
#endif
/*
Funcin modplcsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_poll(__data modplcsp_hd *);
#else
int modplcsp_poll(modplcsp_hd *);
#endif
/*
Funcin modplcsp_status:
Devuelve el estado del modem PLC.
*/

282

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#if defined SDCC_MODEL_SMALL
int modplcsp_status(__data modplcsp_hd *);
#else
int modplcsp_status(modplcsp_hd *);
#endif
/*
Funcin modplcsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
short int modplcsp_getpayloadsize(__data modplcsp_hd *);
#else
short int modplcsp_getpayloadsize(modplcsp_hd *);
#endif
/*
Interrupcin INT1:
Procesa el mensaje recibido.
*/
extern void __modplcsp_int1__(void) __interrupt 1;

#endif

C.2.40. Archivo modplcsp__init.c


/*
modplcsp__init.c:
Implementacin de la funcin modplcsp__init de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Definicin de SFR necesarias. */


__sfr __at (0x8a) SIO_TL0;
__sfr __at (0x8c) SIO_TH0;
__sbit __at (0x8c) SIO_TR0;

/* Variables globales. */
volatile modplcsp_hd __modplcsp_hd__;

/* Declaracin de funciones privadas. */


void __modplcsp_waitchar__(char);
short int __modplcsp_sendcmd0__(modplcsp_hd *, char);

/* Implementacin de funciones pblicas. */

FernandoArielBeunza79156

283

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcsp__init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
__data modplcsp_hd *modplcsp__init(int sid, short int msgsize)
#else
modplcsp_hd *modplcsp__init(int sid, short int msgsize)
#endif
{
/* Variables. */
char c;
/* Caracter recibido. */

/* Verifica la validez del identificador de interface fsica. */


if (sid != 1) return NULL;
/* Inicializa la interfaz fsica. */
inituart(0xff);
/* Solicita acceder a la capa de sesin del modem PLC. */
c = 0;
while(1)
{
if (!c) putchar('\n');
c = getchar();
if (c == MODPLC_INITPROMPT)
{
putchar('i');
putchar('n');
putchar('i');
putchar('t');
}
else if ((c == MODPLC_LAYPROMPT) || (c == MODPLC_NORMPROMPT))
putchar(MODPLC_NORMRESET);
else if (c == MODPLC_PARAMPROMPT)
putchar(MODPLC_PARAMRESET);
else
continue;
putchar('\n');
break;
}
__modplcsp_waitchar__(MODPLC_LAYPROMPT);
putchar(MODPLC_SESSIONLAYER);
putchar('\n');
__modplcsp_waitchar__(MODPLC_NORMPROMPT);
/* Inicializa el buffer de recepcin. */
__modplcsp_hd__.buffsize = 0;
__modplcsp_hd__.recvbuff = NULL;
/* Define la cantidad mxima de bytes que puede contener un mensaje. */
__modplcsp_hd__.msgsize = msgsize;
/* Inicializa el estado del modem PLC. */
__modplcsp_hd__.status = 1;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__modplcsp_hd__.recfun = NULL;
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
__modplcsp_hd__.payloadsize =
__modplcsp_sendcmd0__(&__modplcsp_hd__, MODPLCSP_GETPAYLOADSIZE);
if (!__modplcsp_hd__.payloadsize) return NULL;
/* Devuelve el manejador creado. */
return &__modplcsp_hd__;
}

/* Implementacin de funciones privadas. */

284

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Interrupcin INT1:
Procesa el mensaje recibido.
*/
void __modplcsp_int1__(void) __interrupt 1
{
/* Variables. */
short int msgsize;
modplcsp_grpid grpid;

/* Tamao del mensaje. */


/* Identificador de grupo. */

/* Desactiva las interrupciones. */


__asm clr EA __endasm;
/* Verifica la recepcin de un mensaje y lo procesa. */
SIO_TR0 = 0;
while(1)
{
/* Verifica si transcurri el intervalo de espera. */
if (__modplcsp_hd__.polltimer < MODPLCSP_POLLINTERVAL)
{
__modplcsp_hd__.polltimer ++;
break;
}
__modplcsp_hd__.polltimer = 0;
/* Verifica la recepcin de un nuevo mensaje. */
if (!modplcsp_poll(&__modplcsp_hd__)) break;
/* Recibe el mensaje. */
grpid = 0;
msgsize = 0;
if (__modplcsp_hd__.recvbuff && __modplcsp_hd__.buffsize)
{
msgsize = modplcsp_receive(&__modplcsp_hd__, &grpid,
__modplcsp_hd__.recvbuff,
__modplcsp_hd__.buffsize);
if (!msgsize) break;
}
/* Invoca a la funcin manejadora de mensajes recibidos. */
if (!__modplcsp_hd__.recfun) break;
__modplcsp_hd__.recfun(&__modplcsp_hd__, grpid,
__modplcsp_hd__.recvbuff, msgsize,
__modplcsp_hd__.param);
}
SIO_TH0 = 0xfc;
SIO_TL0 = 0x66;
SIO_TR0 = 1;
/* Activa las interrupciones. */
__asm setb EA __endasm;
}

C.2.41. Archivo modplcsp_release.c


/*
modplcsp_release.c:
Implementacin de la funcin modplcsp_release de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

FernandoArielBeunza79156

285

Tesis de Grado en Ingeniera Informtica


/* Verifica si se encuentra definido el tamao mximo del mensaje. */
#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_release(__data modplcsp_hd *hd)
#else
int modplcsp_release(modplcsp_hd *hd)
#endif
{
/* Verifica que el manejador de interfaz con la capa de sesin del modem
PLC exista. */
if (!hd) return 0;
/* xito. */
return 1;
}

C.2.42. Archivo modplcsp_publish.c


/*
modplcsp_publish.c:
Implementacin de la funcin modplcsp_publish de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


#if defined SDCC_MODEL_SMALL
short int __modplcsp_sendcmd1__(__data modplcsp_hd *, char, unsigned char);
#else
short int __modplcsp_sendcmd1__(modplcsp_hd *, char, unsigned char);
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL

286

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int modplcsp_publish(__data modplcsp_hd *hd, modplcsp_grpid grpid)
#else
int modplcsp_publish(modplcsp_hd *hd, modplcsp_grpid grpid)
#endif
{
return (__modplcsp_sendcmd1__(hd, MODPLCSP_PUBLISH, grpid) != 0);
}

C.2.43. Archivo modplcsp_subscribe.c


/*
modplcsp_subscribe.c:
Implementacin de la funcin modplcsp_subscribe de la interfaz de la capa
de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


#if defined SDCC_MODEL_SMALL
short int __modplcsp_sendcmd1__(__data modplcsp_hd *, char, unsigned char);
#else
short int __modplcsp_sendcmd1__(modplcsp_hd *, char, unsigned char);
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_subscribe(__data modplcsp_hd *hd, modplcsp_grpid grpid)
#else
int modplcsp_subscribe(modplcsp_hd *hd, modplcsp_grpid grpid)
#endif
{
return (__modplcsp_sendcmd1__(hd, MODPLCSP_SUBSCRIBE, grpid) != 0);
}

C.2.44. Archivo modplcsp_leave.c


/*
modplcsp_leave.c:
Implementacin de la funcin modplcsp_leave de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

FernandoArielBeunza79156

287

Tesis de Grado en Ingeniera Informtica

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


#if defined SDCC_MODEL_SMALL
short int __modplcsp_sendcmd1__(__data modplcsp_hd *, char, unsigned char);
#else
short int __modplcsp_sendcmd1__(modplcsp_hd *, char, unsigned char);
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_leave(__data modplcsp_hd *hd, modplcsp_grpid grpid)
#else
int modplcsp_leave(modplcsp_hd *hd, modplcsp_grpid grpid)
#endif
{
return (__modplcsp_sendcmd1__(hd, MODPLCSP_LEAVE, grpid) != 0);
}

C.2.45. Archivo modplcsp_send.c


/*
modplcsp_send.c:
Implementacin de la funcin modplcsp_send de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_putcmd__(char);
void __modplcsp_waitchar__(char);
void __modplcsp_putint__(short int);
short int __modplcsp_getbyte__(void);
void __modplcsp_puthex__(unsigned char);
void __modplcsp_putbyte__(unsigned char);
#if defined SDCC_MODEL_SMALL
short int __modplcsp_getresult__(__data modplcsp_hd *);

288

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#else
short int __modplcsp_getresult__(modplcsp_hd *);
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
short int modplcsp_send(__data modplcsp_hd *hd, modplcsp_grpid grpid,
unsigned char nosec, const __data void *msg,
short int msgsize)
#else
short int modplcsp_send(modplcsp_hd *hd, modplcsp_grpid grpid,
unsigned char nosec, const void *msg,
short int msgsize)
#endif
{
/* Variables. */
int i;
/* Contador. */
char c;
/* Caracter recibido. */
#if defined SDCC_MODEL_SMALL
__data unsigned char *ptr;
/* Puntero al mensaje. */
#else
unsigned char *ptr;
/* Puntero al mensaje. */
#endif
/* Verifica el estado del modem PLC. */
if (!modplcsp_status(hd)) return 0;
/* Enva un mensaje. */
__modplcsp_putcmd__(MODPLCSP_SEND);
__modplcsp_putbyte__(grpid);
__modplcsp_putbyte__(nosec);
__modplcsp_putint__(msgsize);
__modplcsp_waitchar__('\n');
i = 0;
#if defined SDCC_MODEL_SMALL
ptr = (__data unsigned char *) msg;
#else
ptr = (unsigned char *) msg;
#endif
while(msgsize)
{
if (i >= 32)
{
putchar('\n');
i = 0;
}
while(!i)
{
c = getchar();
if (c == '>') break;
}
c = *ptr;
if ((c >= 0x20) && (c <= 0x7e) && (c != '\\') &&
(c != MODPLC_INITPROMPT) && (c != MODPLC_LAYPROMPT) &&
(c != MODPLC_NORMPROMPT) && (c != MODPLC_PARAMPROMPT))
putchar(*ptr);
else
__modplcsp_puthex__(*ptr);
msgsize --;
ptr ++;
i ++;
}
if (i) putchar('\n');
/* Devuelve la cantidad de bytes envados. */

FernandoArielBeunza79156

289

Tesis de Grado en Ingeniera Informtica


return __modplcsp_getresult__(hd);
}

C.2.46. Archivo modplcsp_receive.c


/*
modplcsp_receive.c:
Implementacin de la funcin modplcsp_receive de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_putcmd__(char);
void __modplcsp_waitchar__(char);
void __modplcsp_putint__(short int);
short int __modplcsp_getbyte__(void);
short int __modplcsp_getresult__(void);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
short int modplcsp_receive(__data modplcsp_hd *hd,
__data modplcsp_grpid *grpid, __data void *msg,
short int msgsize)
#else
short int modplcsp_receive(modplcsp_hd *hd, modplcsp_grpid *grpid, void *msg,
short int msgsize)
#endif
{
/* Variables. */
short int recvbyte;
/* Byte recibido. */
short int received;
/* Cantidad de bytes recibido. */
unsigned char i;
/* Contador. */
#if defined SDCC_MODEL_SMALL
__data unsigned char *ptr;
/* Puntero al mensaje. */
#else
unsigned char *ptr;
/* Puntero al mensaje. */
#endif

/* Verifica el estado del modem PLC. */


if (!modplcsp_status(hd)) return 0;
/* Solicita el mensaje recibido. */
__modplcsp_putcmd__(MODPLCSP_RECEIVE);
__modplcsp_putint__(0x7fff);
__modplcsp_waitchar__('\n');

290

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Recibe el identificador de grupo asociado al mensaje. */
*grpid = __modplcsp_getbyte__() & 0x00ff;
__modplcsp_waitchar__('\n');
/* Recibe la cantidad de bytes del mensaje. */
msgsize = __modplcsp_getresult__();
/* Recibe el mensaje. */
received = 0;
#if defined SDCC_MODEL_SMALL
ptr = (__data unsigned char *) msg;
#else
ptr = (unsigned char *) msg;
#endif
while(1)
{
recvbyte = __modplcsp_getbyte__();
if (recvbyte & 0xff00)
break;
else if ((msgsize) && (received <= hd->msgsize))
{
*ptr = recvbyte & 0x00ff;
received ++;
msgsize --;
ptr ++;
}
}
/* Verifica el estado del modem PLC. */
if (((char) (recvbyte >> 8)) == MODPLC_INITPROMPT)
{
received = 0;
hd->status = 0;
}
/* Verifica si el mensaje recibido super el tamao permitido. */
if (received > hd->msgsize)
{
received = 0;
hd->status = 0;
do
{
putchar('0');
for(i = 0; i < 10; i++) putchar('\n');
} while(__modplcsp_getbyte__() != (MODPLC_INITPROMPT << 8));
}
/* Devuelve la cantidad de bytes recibidos. */
return received;
}

C.2.47. Archivo modplcsp_setbuffer.c


/*
modplcsp_setbuffer.c:
Implementacin de la funcin modplcsp_setbuffer de la interfaz de la capa
de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)

FernandoArielBeunza79156

291

Tesis de Grado en Ingeniera Informtica


#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_setbuffer:
Define el buffer de recepcin.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_setbuffer(__data modplcsp_hd *hd, __data void *buffer, short int size)
#else
int modplcsp_setbuffer(modplcsp_hd *hd, void *buffer, short int size)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcsp_status(hd)) return 0;
/* Define el buffer de recepcin. */
hd->buffsize = size;
hd->recvbuff = buffer;
return 1;
}

C.2.48. Archivo modplcsp_notify.c


/*
modplcsp_notify.c:
Implementacin de la funcin modplcsp_notify de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Definicin de SFR necesarias. */


__sfr __at (0x89) SIO_TMOD;
__sfr __at (0x8a) SIO_TL0;
__sfr __at (0x8c) SIO_TH0;
__sfr __at (0xa8) SIO_IE;
__sbit __at (0x8c) SIO_TR0;
__sbit __at (0x8d) SIO_TF0;

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#if defined SDCC_MODEL_SMALL

292

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int modplcsp_notify(__data modplcsp_hd *hd, void (*func)(__data modplcsp_hd *,
modplcsp_grpid, __data void *, short int, __data void *),
__data void *param)
#else
int modplcsp_notify(modplcsp_hd *hd, void (*func)(modplcsp_hd *,
modplcsp_grpid, void *, short int, void *), void *param)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcsp_status(hd)) return 0;
/* Define una funcin manejadora de mensajes recibidos.*/
#if defined SDCC_MODEL_SMALL
hd->recfun = (void (*)(__data void *, modplcsp_grpid, __data void *,
short int, __data void *)) func;
#else
hd->recfun = (void (*)(void *, modplcsp_grpid, void *, short int, void *))
func;
#endif
hd->param = param;
/* Activa la verificacin de recepcin de mensajes. */
SIO_IE &= 0xfd;
if (hd->recfun)
{
hd->polltimer = 0;
SIO_TMOD = (SIO_TMOD & 0xf0) | 0x01;
SIO_TH0 = 0xfc;
SIO_TL0 = 0x66;
SIO_TR0 = 1;
SIO_IE |= 0x82;
}
else
{
SIO_TMOD &= 0xfd;
SIO_TR0 = 0;
}
/* xito. */
return 1;
}

C.2.49. Archivo modplcsp_poll.c


/*
modplcsp_poll.c:
Implementacin de la funcin modplcsp_poll de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


#if defined SDCC_MODEL_SMALL
short int __modplcsp_sendcmd0__(__data modplcsp_hd *, char);

FernandoArielBeunza79156

293

Tesis de Grado en Ingeniera Informtica


#else
short int __modplcsp_sendcmd0__(modplcsp_hd *, char);
#endif

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_poll(__data modplcsp_hd *hd)
#else
int modplcsp_poll(modplcsp_hd *hd)
#endif
{
return (__modplcsp_sendcmd0__(hd, MODPLCSP_POLL) != 0);
}

C.2.50. Archivo modplcsp_status.c


/*
modplcsp_status.c:
Implementacin de la funcin modplcsp_status de la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_waitchar__(char);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_status:
Devuelve el estado del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
int modplcsp_status(__data modplcsp_hd *hd)
#else
int modplcsp_status(modplcsp_hd *hd)
#endif
{
/* Variables. */
char c;

/* Caracter recibido. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;

294

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Verifica el estado del modem PLC. */
if (!hd->status) return 0;
putchar('\n');
while(1)
{
c = getchar();
if (c == MODPLC_NORMPROMPT)
break;
else if (c == MODPLC_INITPROMPT)
{
hd->status = 0;
break;
}
}
return hd->status;
}

C.2.51. Archivo modplcsp_getpayloadsize.c


/*
modplcsp_getpayloadsize.c:
Implementacin de la funcin modplcsp_getpayloadsize de la interfaz de la
capa de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
#if defined SDCC_MODEL_SMALL
short int modplcsp_getpayloadsize(__data modplcsp_hd *hd)
#else
short int modplcsp_getpayloadsize(modplcsp_hd *hd)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcsp_status(hd)) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener un mensaje. */
return hd->payloadsize;
}

C.2.52. Archivo __modplcsp_getbyte__.c


/*
__modplcsp_getbyte__.c:
Implementacin de la funcin __modplcsp_waitbyte__ de la interfaz de la

FernandoArielBeunza79156

295

Tesis de Grado en Ingeniera Informtica


capa de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_getbyte__:
Obtiene un byte recibido por la UART.
*/
short int __modplcsp_getbyte__(void)
{
/* Variables. */
int i;
short int resp;
char c;

/* Contador. */
/* Respuesta. */
/* Caracter recibido. */

/* Obtiene el byte recibido. */


while(1)
{
c = getchar();
if ((c == '\n') || (c == MODPLC_INITPROMPT) ||
(c == MODPLC_LAYPROMPT) || (c == MODPLC_NORMPROMPT) ||
(c == MODPLC_PARAMPROMPT))
return (c << 8);
else if (c == '\\')
{
resp = 0;
for(i = 0; i < 2; i++)
{
c = getchar();
if ((c >= '0') && (c <= '9'))
c -= '0';
else if ((c >= 'a') && (c <= 'f'))
c = c - 'a' + 10;
else if ((c >= 'A') && (c <= 'F'))
c = c - 'A' + 10;
resp <<= 4;
resp |= c;
}
return resp;
}
else if ((c >= 0x20) && (c <= 0x7e))
return c;
}
}

C.2.53. Archivo __modplcsp_getresult__.c


/*
__modplcsp_getresult__.c:
Implementacin de la funcin __modplcsp_getresult__ de la interfaz de la

296

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


capa de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_waitchar__(char);
short int __modplcsp_getbyte__(void);

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_getresult__:
Devuelve el resultado de una solicitud.
*/
#if defined SDCC_MODEL_SMALL
short int __modplcsp_getresult__(__data modplcsp_hd *hd)
#else
short int __modplcsp_getresult__(modplcsp_hd *hd)
#endif
{
/* Variables. */
short int result;
short int recvbyte;

/* Resultado de la solicitud. */
/* Byte recibido. */

/* Recibe el resultado de la solicitud. */


result = __modplcsp_getbyte__() & 0x00ff;
recvbyte = __modplcsp_getbyte__();
if (!(recvbyte & 0xff00)) result = (result << 8) | (recvbyte & 0x00ff);
while(!(recvbyte & 0xff00)) recvbyte = __modplcsp_getbyte__();
/* Verifica el estado del modem PLC. */
if (((char) (recvbyte >> 8)) == MODPLC_INITPROMPT) hd->status = 0;
/* Devuelve el resultado recibido. */
return result;
}

C.2.54. Archivo __modplcsp_putbyte__.c


/*
__modplcsp_putbyte__.c:
Implementacin de la funcin __modplcsp_putbyte__ de la interfaz de la capa
de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

FernandoArielBeunza79156

297

Tesis de Grado en Ingeniera Informtica


/* Verifica si se encuentra definido el tamao mximo del mensaje. */
#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_puthex__(unsigned char);
void __modplcsp_waitchar__(char);

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_putbyte__:
Enva un byte a travs de la UART.
*/
void __modplcsp_putbyte__(unsigned char val)
{
__modplcsp_waitchar__(MODPLC_PARAMPROMPT);
__modplcsp_puthex__(val);
putchar('\n');
}

C.2.55. Archivo __modplcsp_putcmd__.c


/*
__modplcsp_putcmd__.c:
Implementacin de la funcin __modplcsp_putcmd__ de la interfaz de la capa
de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_waitchar__(char);

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_putcmd__:
Enva un comando a travs de la UART.
*/
void __modplcsp_putcmd__(char cmd)
{
putchar(cmd);
__modplcsp_waitchar__(cmd);
putchar('\n');
}

298

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.2.56. Archivo __modplcsp_puthex__.c


/*
__modplcsp_puthex__.c:
Implementacin de la funcin __modplcsp_puthex__ de la interfaz de la capa
de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_waitchar__(char);

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_puthex__:
Enva un byte codificado en hexadecimal a travs de la UART.
*/
void __modplcsp_puthex__(unsigned char ch)
{
/* Variables. */
int i;
unsigned char dig;

/* Contador. */
/* Dgito. */

/* Enva un byte codificado en hexadecimal. */


putchar('\\');
__modplcsp_waitchar__('\\');
for(i = 0; i < 2; i++)
{
dig = ch >> 4;
ch <<= 4;
if (dig > 9)
putchar(dig + 'A' - 10);
else
putchar(dig + '0');
}
}

C.2.57. Archivo __modplcsp_putint__.c


/*
__modplcsp_putint__.c:
Implementacin de la funcin __modplcsp_putint__ de la interfaz de la capa
de sesin del modem PLC.
*/

FernandoArielBeunza79156

299

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_puthex__(unsigned char);
void __modplcsp_waitchar__(char);

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_putint__:
Enva un entero a travs de la UART.
*/
void __modplcsp_putint__(short int val)
{
__modplcsp_waitchar__(MODPLC_PARAMPROMPT);
__modplcsp_puthex__((unsigned char) (val >> 8));
__modplcsp_puthex__((unsigned char) (val & 0x00ff));
putchar('\n');
}

C.2.58. Archivo __modplcsp_sendcmd0__.c


/*
__modplcsp_sendcmd0__.c:
Implementacin de la funcin __modplcsp_sendcmd0__ de la interfaz de la
capa de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_putcmd__(char);
void __modplcsp_waitchar__(char);
short int __modplcsp_getbyte__(void);
#if defined SDCC_MODEL_SMALL
short int __modplcsp_getresult__(__data modplcsp_hd *);
#else
short int __modplcsp_getresult__(modplcsp_hd *);
#endif

300

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Implementacin de funciones privadas. */
/*
Funcin __modplcsp_sendcmd0__:
Enva una solicitud sin parmetros.
*/
#if defined SDCC_MODEL_SMALL
short int __modplcsp_sendcmd0__(__data modplcsp_hd *hd, char cmd)
#else
short int __modplcsp_sendcmd0__(modplcsp_hd *hd, char cmd)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcsp_status(hd)) return 0;
/* Solicita verificar la recepcin de un mensaje. */
__modplcsp_putcmd__(cmd);
__modplcsp_waitchar__('\n');
/* Devuelve el resultado de la solicitud. */
return __modplcsp_getresult__(hd);
}

C.2.59. Archivo __modplcsp_sendcmd1__.c


/*
__modplcsp_sendcmd1__.c:
Implementacin de la funcin __modplcsp_sendcmd1__ de la interfaz de la
capa de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Declaracin de funciones privadas. */


void __modplcsp_putcmd__(char);
void __modplcsp_waitchar__(char);
short int __modplcsp_getbyte__(void);
void __modplcsp_putbyte__(unsigned char);
#if defined SDCC_MODEL_SMALL
short int __modplcsp_getresult__(__data modplcsp_hd *);
#else
short int __modplcsp_getresult__(modplcsp_hd *);
#endif

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_sendcmd1__:
Enva una solicitud con un parmetro.
*/
#if defined SDCC_MODEL_SMALL
short int __modplcsp_sendcmd1__(__data modplcsp_hd *hd, char cmd,

FernandoArielBeunza79156

301

Tesis de Grado en Ingeniera Informtica


unsigned char param)
#else
short int __modplcsp_sendcmd1__(modplcsp_hd *hd, char cmd, unsigned char param)
#endif
{
/* Verifica el estado del modem PLC. */
if (!modplcsp_status(hd)) return 0;
/* Solicita verificar la recepcin de un mensaje. */
__modplcsp_putcmd__(cmd);
__modplcsp_putbyte__(param);
__modplcsp_waitchar__('\n');
/* Devuelve el resultado de la solicitud. */
return __modplcsp_getresult__(hd);
}

C.2.60. Archivo __modplcsp_waitchar__.c


/*
__modplcsp_waitchar__.c:
Implementacin de la funcin __modplcsp_waitchar__ de la interfaz de la
capa de sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Verifica si se encuentra definido el tamao mximo del mensaje. */


#if !defined(MODPLCSP_MSGSIZE)
#define MODPLCSP_MSGSIZE 0
#endif

/* Archivos includos necesarios. */


#include "modplcsp.h"

/* Implementacin de funciones privadas. */


/*
Funcin __modplcsp_waitchar__:
Espera la recepcin del caracter especificado.
*/
void __modplcsp_waitchar__(char ch)
{
while(getchar() != ch);
}

C.2.61. Archivo serial.h


/*
serial.h:
Declaracin de funciones referentes a la UART.
*/

#if !defined(__SERIAL_H__)
#define __SERIAL_H__

/* Declaracin de funciones pblicas. */

302

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin inituart:
Inicializa la UART del microcontrolador.
*/
void inituart(unsigned char);
/*
Funcin putchar:
Enva un caracter a travs de la UART.
*/
void putchar(char);
/*
Funcin poll:
Devuelve si hay un caracter almacenado en la UART.
*/
int poll(void);
/*
Funcin getchar:
Devuelve un caracter recibido por medio de la UART.
*/
char getchar(void);

#endif

C.2.62. Archivo serial.c


/*
serial.c:
Implementacin de funciones referentes a la UART.
*/

/* Archivos includos necesarios. */


#include "serial.h"

/* Definicin de SFR necesarias. */


__sfr __at (0x87) SIO_PCON;
__sfr __at (0x89) SIO_TMOD;
__sfr __at (0x98) SIO_SCON;
__sfr __at (0x99) SIO_SBUF;
__sfr __at (0x8B) SIO_TL1;
__sfr __at (0x8D) SIO_TH1;
__sbit __at (0x8E) SIO_TR1;
__sbit __at (0x98) SIO_RI;
__sbit __at (0x99) SIO_TI;

/*
Funcin inituart:
Inicializa la UART del microcontrolador.
*/
void inituart(unsigned char t1_reload)
{
/* Inicializa la UART. */
SIO_SCON = 0x50;
SIO_TR1 = 0;
SIO_TMOD = (SIO_TMOD & 0x0f) | 0x20;
SIO_PCON |= 0x80;
SIO_TH1 = t1_reload;
SIO_TR1 = 1;
SIO_TI = 1;
}

FernandoArielBeunza79156

303

Tesis de Grado en Ingeniera Informtica


/*
Funcin putchar:
Enva un caracter a travs de la UART.
*/
void putchar(char c)
{
while(!SIO_TI);
SIO_TI = 0;
SIO_SBUF = c;
__asm nop __endasm;
}
/*
Funcin poll:
Devuelve si hay un caracter almacenado en la UART.
*/
int poll(void)
{
return SIO_RI;
}
/*
Funcin getchar:
Devuelve un caracter recibido por medio de la UART.
*/
char getchar(void)
{
/* Varaibles. */
char c;

/* Caracter recibido. */

/* Recibe un caracter por medio de la UART. */


while(!poll());
SIO_RI = 0;
c = SIO_SBUF;
/* Devuelve el caracter recibido. */
return c;
}

C.3. Especificacin del cdigo fuente de las


bibliotecas de uso del modem PLC (plataforma
Windows)
El cdigo fuente que conforma las bibliotecas de uso del modem PLC, se encuentra
organizado en los siguientes componentes:

304

Interfaz capa de aplicacin.

Intefaz capa de enlace.

Interfaz capa fsica.

Driver del modem PLC.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.3.1. Interfaz capa de aplicacin modplcap.dll


En esta seccin se detalla el cdigo fuente de la biblioteca que implementa la capa de
aplicacin del modem PLC, que se compone de los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin de la biblioteca


dinmica que implementa la capa de aplicacin del modem PLC que no pueden ser
modificados en tiempo de ejecucin.

Archivo modplcap.h: en este archivo se declaran primitivas con funcionalidades


referentes a la capa de aplicacin del modem PLC.

Archivo modplcap.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcap.h.

Archivo modplcpp.h: en este archivo se declaran las primitivas correspondientes al


manejo de la capa de presentacin. Dichas primitivas brindan la capacidad de trabajar con
estructuras de datos independientes de la plataforma.

Archivo modplcpp.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcpp.h.

Archivo modplcsp.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa de sesin. Dichas primitivas brindan un conjunto de funcionalidades
que permiten la comunicacin con la capa de sesin implementada en el modem PLC por
medio del driver del mismo.

Archivo modplcsp.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcsp.h.

C.3.1.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz con el driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa de sesin. */
#define MODDRVSP_RELEASE
0x00
#define MODDRVSP_PUBLISH
0x01
#define MODDRVSP_SUBSCRIBE
0x02
#define MODDRVSP_LEAVE
0x03
#define MODDRVSP_SEND
0x04
#define MODDRVSP_RECEIVE
0x05
#define MODDRVSP_POLL
0x06
#define MODDRVSP_STATUS
0x07
#define MODDRVSP_GETPAYLOADSIZE
0x08

FernandoArielBeunza79156

305

Tesis de Grado en Ingeniera Informtica


#endif

C.3.1.2. Archivo modplcsp.h


/*
modplcsp.h:
Declaracin de funciones referentes a la interfaz de la capa de sesin del
modem PLC.
*/

#if !defined(__MODPLCSP_H__)
#define __MODPLCSP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <windows.h>

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcsp_grpid;
/* Manejador de interfaz con la capa de sesin del modem PLC. */
typedef struct
{
HANDLE hq;
/* Manejador de cola de
mensajes. */
HANDLE hm;
/* Semforo de exclusin mtua. */
HANDLE detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
void (*recfun)
(void *, modplcsp_grpid, void *,
size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} modplcsp_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin modplcsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modplcsp_hd *modplcsp_init(int);
/*
Funcin modplcsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modplcsp_release(modplcsp_hd *);
/*
Funcin modplcsp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modplcsp_publish(modplcsp_hd *, modplcsp_grpid);
/*
Funcin modplcsp_subscribe:

306

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int modplcsp_subscribe(modplcsp_hd *, modplcsp_grpid);
/*
Funcin modplcsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcsp_leave(modplcsp_hd *, modplcsp_grpid);
/*
Funcin modplcsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_send(modplcsp_hd *, modplcsp_grpid, unsigned char,
const void *, size_t);
/*
Funcin modplcsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_receive(modplcsp_hd *, modplcsp_grpid *, void *, size_t);
/*
Funcin modplcsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcsp_notify(modplcsp_hd *, void (*func)(modplcsp_hd *, modplcsp_grpid,
void *, size_t, void *), void *);
/*
Funcin modplcsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcsp_poll(modplcsp_hd *);
/*
Funcin modplcsp_status:
Devuelve el estado del modem PLC.
*/
int modplcsp_status(modplcsp_hd *);
/*
Funcin modplcsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
size_t modplcsp_getpayloadsize(modplcsp_hd *);

#endif

C.3.1.3. Archivo modplcsp.c


/*
modplcsp.c:
Implementacin de funciones referentes a la interfaz de la capa de sesin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "modplcsp.h"

FernandoArielBeunza79156

307

Tesis de Grado en Ingeniera Informtica


/* Declaracin de funciones privadas. */
static DWORD WINAPI __modplcsp_detectproc__(LPVOID);
static int __modplcsp_sendrecv__(HANDLE, void *, size_t, const void *, size_t);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modplcsp_hd *modplcsp_init(int sid)
{
/* Variables. */
int op;
int layer;
int result;
size_t payloadsize;
modplcsp_hd *handle;
char qname[256];

/* Identificador de operacin. */
/* Capa a la que se quiere
accerder. */
/* Resultado de la solicitud. */
/* Cantidad mxima de bytes que
puede contener un mensaje. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */
/* Nombre de la cola de
mensajes. */

/* Crea un nuevo manejador de interfaz con la capa de sesin del modem


PLC. */
handle = (modplcsp_hd *) malloc(sizeof(modplcsp_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de sesin del modem
PLC. */
while(1)
{
/* Abre una conexin con la cola de mensajes del driver del modem
PLC. */
sprintf(qname, "\\\\.\\pipe\\modemplc%i", sid);
handle->hq = CreateFile(qname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle->hq == INVALID_HANDLE_VALUE) break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Inicializa semforo de exclusin mtua. */
handle->hm = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->hm == INVALID_HANDLE_VALUE) break;
/* Solicita acceder a la capa de sesin del modem PLC. */
layer = 3;
if (!__modplcsp_sendrecv__(handle->hq, &result, sizeof(result), &layer,
sizeof(layer)))
break;
if (!result) break;
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
op = MODDRVSP_GETPAYLOADSIZE;
if (!__modplcsp_sendrecv__(handle->hq, &payloadsize,
sizeof(payloadsize), &op, sizeof(op)))
break;
if (!payloadsize) break;
handle->payloadsize = payloadsize;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de sesin del modem

308

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


PLC. */
CloseHandle(handle->hm);
CloseHandle(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modplcsp_release(modplcsp_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Libera la funcin manejadora de mensajes recibidos. */
modplcsp_notify(hd, NULL, NULL);
/* Solicita la finalizacin del acceso a la capa de sesin del modem
PLC. */
op = MODDRVSP_RELEASE;
if (!__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Libera los recursos utilizados por la interfaz con la capa de sesin del
modem PLC. */
CloseHandle(hd->hm);
CloseHandle(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcsp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modplcsp_publish(modplcsp_hd *hd, modplcsp_grpid grpid)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Solicita el registro del dispositivo como publicador. */
result = 0;
while(1)
{
/* Solicita el registro del dispositivo. */
op = MODDRVSP_PUBLISH;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de grupo. */
__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &grpid,

FernandoArielBeunza79156

309

Tesis de Grado en Ingeniera Informtica


sizeof(grpid));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modplcsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int modplcsp_subscribe(modplcsp_hd *hd, modplcsp_grpid grpid)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Solicita el registro del dispositivo como suscriptor. */
result = 0;
while(1)
{
/* Solicita el registro del dispositivo. */
op = MODDRVSP_SUBSCRIBE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de grupo. */
__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &grpid,
sizeof(grpid));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modplcsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcsp_leave(modplcsp_hd *hd, modplcsp_grpid grpid)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Solicita desvincular el dispositivo de un grupo de difusin. */
result = 0;
while(1)

310

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
/* Solicita desvincular el dispositivo. */
op = MODDRVSP_LEAVE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de grupo. */
__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &grpid,
sizeof(grpid));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la desvinculacin del dispositivo. */
return result;
}
/*
Funcin modplcsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_send(modplcsp_hd *hd, modplcsp_grpid grpid,
unsigned char nosec, const void *msg, size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Enva un mensaje. */
while(1)
{
/* Solicita el envo de un mensaje. */
op = MODDRVSP_SEND;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de grupo. */
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &grpid, sizeof(grpid)))
break;
/* Enva el identificador de mensaje fuera de secuencia. */
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &nosec, sizeof(nosec)))
break;
/* Enva el tamao del mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &msgsize, sizeof(msgsize)))
break;
/* Enva el mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &msgsize, sizeof(msgsize), msg,
msgsize))
break;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad de bytes enviados. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);

FernandoArielBeunza79156

311

Tesis de Grado en Ingeniera Informtica


/* No se pudo realizar el envo. */
return 0;
}
/*
Funcin modplcsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_receive(modplcsp_hd *hd, modplcsp_grpid *grpid, void *msg,
size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene un mensaje recibido. */
while(1)
{
/* Solicita recibir un mensaje. */
op = MODDRVSP_RECEIVE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva la cantidad de bytes que se quieren recibir del mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &msgsize, sizeof(msgsize), &msgsize,
sizeof(msgsize)))
break;
if (!msgsize) break;
/* Obtiene el identificador de grupo por el cual se recibi el
mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &grpid, sizeof(grpid), NULL, 0))
break;
/* Recibe el mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, msg, msgsize, NULL, 0))
break;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad de bytes ledos. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* No se pudo recibir el mensaje. */
return 0;
}
/*
Funcin modplcsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcsp_notify(modplcsp_hd *hd, void (*func)(modplcsp_hd *,
modplcsp_grpid, void *, size_t, void *), void *param)
{
/* Variables. */
DWORD tid;
/* Identificador de hilo. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem

312

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
WaitForSingleObject(hd->hm, INFINITE);
hd->recfun = func;
hd->param = param;
ReleaseSemaphore(hd->hm, 1, NULL);
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora definida
previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
WaitForSingleObject(hd->hm, INFINITE);
hd->recfun = NULL;
hd->param = param;
ReleaseSemaphore(hd->hm, 1, NULL);
WaitForSingleObject(hd->detectthread, INFINITE);
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
WaitForSingleObject(hd->hm, INFINITE);
hd->recfun = func;
hd->param = param;
hd->detectthread = CreateThread(NULL, 0, __modplcsp_detectproc__, hd,
0, &tid);
if (hd->detectthread == INVALID_HANDLE_VALUE)
{
hd->recfun = NULL;
hd->param = NULL;
ReleaseSemaphore(hd->hm, 1, NULL);
return 0;
}
ReleaseSemaphore(hd->hm, 1, NULL);
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modplcsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcsp_poll(modplcsp_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);

FernandoArielBeunza79156

313

Tesis de Grado en Ingeniera Informtica


/* Solicita verificar la recepcin de un mensaje. */
op = MODDRVSP_POLL;
if (!__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcsp_status:
Devuelve el estado del modem PLC.
*/
int modplcsp_status(modplcsp_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene el estado del modem PLC. */
op = MODDRVSP_STATUS;
if (!__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el estado del modem PLC. */
return result;
}
/*
Funcin modplcsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
size_t modplcsp_getpayloadsize(modplcsp_hd *hd)
{
/* Variables. */
int op;
size_t payloadsize;

/* Identificador de operacin. */
/* Cantidad de bytes que puede
contener un mensaje. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
op = MODDRVSP_GETPAYLOADSIZE;
if (!__modplcsp_sendrecv__(hd->hq, &payloadsize, sizeof(payloadsize), &op,
sizeof(op)))
payloadsize = 0;

314

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad mxima de bytes que puede contener un mensaje. */
return payloadsize;
}
/* Implementacin de funciones privadas. */
/*
Funcin __modplcsp_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser ledo.
*/
static DWORD WINAPI __modplcsp_detectproc__(LPVOID param)
{
/* Variables. */
int op;
int result;
int captureflag;
size_t msgsize;
modplcsp_grpid grpid;
modplcsp_hd *hd;
void (*func)(void *, modplcsp_grpid,
void *, size_t, void *);
unsigned char *msg;

/* Identificador de operacin. */
/* Resultado de la operacin. */
/* Indicador de recepcin de un
mensaje. */
/* Tamao del mensaje. */
/* Identificador de grupo. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */
/* Funcin manejadora de mensajes
recibidos. */
/* Puntero al mensaje. */

/* Carga el manejador de interfaz con la capa de sesin del modem PLC. */


hd = (modplcsp_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
op = MODDRVSP_POLL;
if (__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
captureflag = result;
/* Recibe el mensaje. */
while(captureflag)
{
/* Solicita la recepcin de un mensaje. */
op = MODDRVSP_RECEIVE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva la cantidad de bytes que se solicita recibir del
mensaje. */
msgsize = hd->payloadsize;
if (!__modplcsp_sendrecv__(hd->hq, &msgsize, sizeof(msgsize),
&msgsize, sizeof(msgsize)))
break;
if (!msgsize) break;
/* Recibe la direccin de origen del mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &grpid, sizeof(grpid), NULL, 0))
break;
/* Recibe el mensaje. */
msg = (unsigned char *) malloc(msgsize * sizeof(unsigned char));
if (!msg)

FernandoArielBeunza79156

315

Tesis de Grado en Ingeniera Informtica


{
captureflag = 0;
break;
}
__modplcsp_sendrecv__(hd->hq, msg, msgsize, NULL, 0);
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Verifica si se ha detectado la recepcin de un mensaje para invocar
a la funcin manejadora de mensajes recibidos. */
if (captureflag)
{
func(hd, grpid, msg, msgsize, hd->param);
free(msg);
captureflag = 0;
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
ReleaseSemaphore(hd->hm, 1, NULL);
return 0;
}
/*
Funcin __modplcsp_sendrecv__:
Intercambia datos con el driver del modem PLC.
*/
static int __modplcsp_sendrecv__(HANDLE hq, void *outdata, size_t outsize,
const void *indata, size_t insize)
{
/* Variables. */
size_t last;
/* Cantidad de bytes enviados o
recibidos. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Verifica que el manejador de cola de mensajes exista. */


if (hq == INVALID_HANDLE_VALUE) return 0;
/* Enva la operacin. */
sent = 0;
while((indata) && (sent < insize))
{
if (!WriteFile(hq, indata, insize, &last, NULL)) return 0;
sent += last;
}
/* Recibe la respuesta. */
received = 0;
while((outdata) && (received < outsize))
{
if (!ReadFile(hq, outdata, outsize, &last, NULL)) return 0;
received += last;
}
/* xito. */
return 1;
}

C.3.1.4. Archivo modplcpp.h


/*
modplcpp.h:

316

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Declaracin de funciones referentes a la capa de presentacin del modem
PLC.
*/

#if !defined(__MODPLCPP_H__)
#define __MODPLCPP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modplcsp.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcpp_grpid;
/* Tipo de mensaje. */
typedef unsigned char modplcpp_mtype;
/* Tipo de campo. */
typedef unsigned char modplcpp_ftype;
/* Estructura del mensaje. */
typedef struct
{
unsigned short int startoffset;
unsigned short int endoffset;
modplcpp_grpid grpid;
modplcpp_mtype mtype;
void *pphd;
unsigned char *dat;

/*
/*
/*
/*
/*

Comienzo del mensaje. */


Fin del mensaje. */
Identificador de grupo. */
Tipo de mensaje. */
Manejador de capa de
presentacin. */
/* Puntero al contenido del
mensaje. */

} modplcpp_msg;
/* Manejador de capa de presentacin. */
typedef struct
{
size_t payloadsize;
modplcpp_grpid grpid;

modplcsp_hd *modsphd;
void (*recfun)
(void *, modplcpp_msg *, void *);
void *param;

modplcpp_msg buffer;

/* Cantidad mxima de bytes que


puede contener un mensaje. */
/* Identificador de grupo del
mensaje almacenado en el
buffer. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */
/* Funcin manejadora de mensajes
recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
/* Puntero al buffer de campos
recibidos. */

} modplcpp_hd;

/* Definicin de constantes. */
/* Tipo de mensaje. */
#define MODPLCPP_SECMSG
#define MODPLCPP_NOSECMSG

0x00
0x01

/* Tipos de datos. */
#define MODPLCPP_NULLTYPE
#define MODPLCPP_CHARTYPE
#define MODPLCPP_SINT8TYPE
#define MODPLCPP_UINT8TYPE
#define MODPLCPP_SINT16TYPE

0x00
0x01
0x02
0x03
0x04

FernandoArielBeunza79156

317

Tesis de Grado en Ingeniera Informtica


#define
#define
#define
#define

MODPLCPP_UINT16TYPE
MODPLCPP_SINT32TYPE
MODPLCPP_UINT32TYPE
MODPLCPP_FLOATTYPE

0x05
0x06
0x07
0x08

/* Declaracin de funciones pblicas. */


/*
Funcin modplcpp_init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/
modplcpp_hd *modplcpp_init(int);
/*
Funcin modplcpp_release:
Libera los recursos utilizados por la capa de presentacin del modem PLC.
*/
int modplcpp_release(modplcpp_hd *);
/*
Funcin modplcpp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modplcpp_publish(modplcpp_hd *, modplcpp_grpid);
/*
Funcin modplcpp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int modplcpp_subscribe(modplcpp_hd *, modplcpp_grpid);
/*
Funcin modplcpp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcpp_leave(modplcpp_hd *, modplcpp_grpid);
/*
Funcin modplcpp_newmsg:
Crea un nuevo mensaje.
*/
int modplcpp_newmsg(modplcpp_hd *, modplcpp_msg *, modplcpp_grpid,
modplcpp_mtype);
/*
Funcin modplcpp_copymsg:
Crea un copia de un mensaje.
*/
int modplcpp_copymsg(modplcpp_msg *, modplcpp_msg *);
/*
Funcin modplcpp_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcpp_putfield(modplcpp_msg *, modplcpp_ftype, unsigned char,
const void *);
/*
Funcin modplcpp_sendmsg:
Enva un mensaje por medio de la capa de presentacin.
*/
int modplcpp_sendmsg(modplcpp_msg *);
/*
Funcin modplcpp_receivemsg:
Recibe un mensaje por medio de la capa de presentacin.
*/
int modplcpp_receivemsg(modplcpp_hd *, modplcpp_msg *);

318

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcpp_getfield:
Extrae un campo del mensaje.
*/
int modplcpp_getfield(modplcpp_msg *, modplcpp_ftype *, unsigned char *,
void *);
/*
Funcin modplcpp_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *);
/*
Funcin modplcpp_destroymsg:
Destruye un mensaje.
*/
int modplcpp_destroymsg(modplcpp_msg *);
/*
Funcin modplcpp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcpp_notify(modplcpp_hd *, void (*func)(modplcpp_hd *, modplcpp_msg *,
void *), void *);
/*
Funcin modplcpp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcpp_poll(modplcpp_hd *);
/*
Funcin modplcpp_status:
Devuelve el estado del modem PLC.
*/
int modplcpp_status(modplcpp_hd *);

#endif

C.3.1.5. Archivo modplcpp.c


/*
modplcpp.c:
Implementacin de funciones referentes a la capa de presentacin del modem
PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "modplcsp.h"
#include "modplcpp.h"

/* Declaracin de funciones privadas. */


static void __modplcpp_procmsg__(modplcsp_hd *, modplcsp_grpid, const void *,
size_t, void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcpp_init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/

FernandoArielBeunza79156

319

Tesis de Grado en Ingeniera Informtica


modplcpp_hd *modplcpp_init(int sid)
{
/* Variables. */
modplcpp_hd *handle;

/* Manejador de capa de
presentacin. */

/* Crea un nuevo manejador de capa de presentacin. */


handle = (modplcpp_hd *) malloc(sizeof(modplcpp_hd));
if (!handle) return NULL;
/* Inicializa el manejador de capa de presentacin. */
while(1)
{
/* Inicializa el manejador de interfaz con la capa de sesin del modem
PLC. */
handle->modsphd = modplcsp_init(sid);
if (!handle->modsphd) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
handle->payloadsize = modplcsp_getpayloadsize(handle->modsphd);
if (!handle->payloadsize) break;
/* Define un manejador de mensajes recibidos por la capa de sesin. */
if (!modplcsp_notify(handle->modsphd, __modplcpp_procmsg__, handle))
break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de presentacin. */
modplcsp_release(handle->modsphd);
free(handle);
return NULL;
}
/*
Funcin modplcpp_release:
Libera los recursos utilizados por la capa de presentacin del modem PLC.
*/
int modplcpp_release(modplcpp_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modplcsp_notify(hd->modsphd, NULL, NULL);
/* Libera la interfaz con la capa de sesin del modem PLC. */
modplcsp_release(hd->modsphd);
/* Libera los recursos utilizados por la capa de presentacin. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcpp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modplcpp_publish(modplcpp_hd *hd, modplcpp_grpid grpid)
{
/* Verifica que el manejador de la capa de presentacin exista. */

320

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (!hd) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
return modplcsp_publish(hd->modsphd, grpid);
}
/*
Funcin modplcpp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int modplcpp_subscribe(modplcpp_hd *hd, modplcpp_grpid grpid)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
return modplcsp_subscribe(hd->modsphd, grpid);
}
/*
Funcin modplcpp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcpp_leave(modplcpp_hd *hd, modplcpp_grpid grpid)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
return modplcsp_leave(hd->modsphd, grpid);
}
/*
Funcin modplcpp_newmsg:
Crea un nuevo mensaje.
*/
int modplcpp_newmsg(modplcpp_hd *hd, modplcpp_msg *msg, modplcpp_grpid grpid,
modplcpp_mtype mtype)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Asigna memoria para almacenar el contenido del mensaje. */
msg->dat = (unsigned char *)
malloc(hd->payloadsize * sizeof(unsigned char));
if (!msg->dat) return 0;
/* Inicializa el mensaje. */
msg->startoffset = 0;
msg->endoffset = 0;
msg->grpid = grpid;
msg->mtype = mtype;
msg->pphd = hd;
return 1;
}
/*
Funcin modplcpp_copymsg:
Crea un copia de un mensaje.
*/
int modplcpp_copymsg(modplcpp_msg *dest, modplcpp_msg *src)
{
/* Verifica que el puntero al mensaje original no sea nulo. */
if (!src) return 0;
/* Verifica que el puntero a la copia del mensaje no sea nulo. */

FernandoArielBeunza79156

321

Tesis de Grado en Ingeniera Informtica


if (!dest) return 0;
/* Asigna memoria para almacenar el contenido del mensaje. */
dest->dat = (unsigned char *)
malloc(((modplcpp_hd *) src->pphd)->payloadsize *
sizeof(unsigned char));
if (!dest->dat) return 0;
/* Inicializa la copia del mensaje. */
dest->startoffset = src->startoffset;
dest->endoffset = src->endoffset;
dest->grpid = src->grpid;
dest->mtype = src->mtype;
dest->pphd = src->pphd;
memcpy(dest->dat, src->dat, src->endoffset);
return 1;
}
/*
Funcin modplcpp_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcpp_putfield(modplcpp_msg *msg, modplcpp_ftype type,
unsigned char count, const void *dat)
{
/* Variables. */
unsigned char *ptr;
/* Puntero a los datos. */
size_t msgsize;
/* Tamao del mensaje. */

/* Verifica que el puntero al mensaje no sea nulo. */


if (!msg) return 0;
/* Inicializa el puntero a los datos. */
ptr = (unsigned char *) dat;
/* Verifica si el nuevo campo puede entrar en el mensaje. */
msgsize = msg->endoffset;
msgsize += sizeof(modplcpp_ftype);
msgsize += sizeof(unsigned char);
if ((type == MODPLCPP_CHARTYPE) || (type == MODPLCPP_UINT8TYPE))
msgsize += count * sizeof(unsigned char);
else if (type == MODPLCPP_SINT8TYPE)
msgsize += count * sizeof(char);
else if ((type == MODPLCPP_SINT16TYPE) || (type == MODPLCPP_UINT16TYPE))
msgsize += count * sizeof(unsigned short int);
else if ((type == MODPLCPP_SINT32TYPE) || (type == MODPLCPP_UINT32TYPE))
msgsize += count * sizeof(unsigned long int);
else if (type == MODPLCPP_FLOATTYPE)
msgsize += count * sizeof(float);
else
return 0;
if (msgsize > ((modplcpp_hd *) (msg->pphd))->payloadsize) return 0;
/* Agrega el tipo de dato. */
*(msg->dat + msg->endoffset) = type;
msg->endoffset += sizeof(modplcpp_ftype);
/* Agrega la cantidad de datos. */
*(msg->dat + msg->endoffset) = count;
msg->endoffset += sizeof(unsigned char);
/* Agrega datos tipo caracter o entero de 8 bits sin signo. */
if ((type == MODPLCPP_CHARTYPE) || (type == MODPLCPP_UINT8TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(unsigned char);
msg->endoffset += sizeof(unsigned char);
}

322

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Agrega datos tipo entero de 8 bits con signo. */
else if (type == MODPLCPP_SINT8TYPE)
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(char);
msg->endoffset += sizeof(char);
}
}
/* Agrega datos tipo entero de 16 bits. */
else if ((type == MODPLCPP_SINT16TYPE) || (type == MODPLCPP_UINT16TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset + 0) = *(ptr + 1);
*(msg->dat + msg->endoffset + 1) = *(ptr + 0);
ptr += sizeof(unsigned short int);
msg->endoffset += sizeof(unsigned short int);
}
}
/* Agrega datos tipo entero de 32 bits. */
else if ((type == MODPLCPP_SINT32TYPE) || (type == MODPLCPP_UINT32TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset + 0) = *(ptr + 3);
*(msg->dat + msg->endoffset + 1) = *(ptr + 2);
*(msg->dat + msg->endoffset + 2) = *(ptr + 1);
*(msg->dat + msg->endoffset + 3) = *(ptr + 0);
ptr += sizeof(unsigned long int);
msg->endoffset += sizeof(unsigned long int);
}
}
/* Agrega datos tipo punto flotante. */
else if (type == MODPLCPP_FLOATTYPE)
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(float);
msg->endoffset += sizeof(float);
}
}
/* xito. */
return 1;
}
/*
Funcin modplcpp_sendmsg:
Enva un mensaje por medio de la capa de presentacin.
*/
int modplcpp_sendmsg(modplcpp_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Enva un mensaje. */
if (modplcsp_send(((modplcpp_hd *) (msg->pphd))->modsphd, msg->grpid,
msg->mtype, msg->dat, msg->endoffset) == msg->endoffset)
return 1;
return 0;
}
/*
Funcin modplcpp_receivemsg:
Recibe un mensaje por medio de la capa de presentacin.
*/
int modplcpp_receivemsg(modplcpp_hd *hd, modplcpp_msg *msg)

FernandoArielBeunza79156

323

Tesis de Grado en Ingeniera Informtica


{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Asigna memoria para almacenar el contenido del mensaje. */
msg->dat = (unsigned char *)
malloc(hd->payloadsize * sizeof(unsigned char));
if (!msg->dat) return 0;
/* Espera la llegada de un mensaje. */
while(!modplcpp_poll(hd));
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
if (msg)
{
msg->grpid = hd->buffer.grpid;
msg->startoffset = hd->buffer.startoffset;
msg->endoffset = hd->buffer.endoffset;
msg->pphd = hd;
memcpy(msg->dat, hd->buffer.dat, hd->buffer.endoffset);
}
hd->buffer.endoffset = 0;
free(hd->buffer.dat);
/* xito. */
return 1;
}
/*
Funcin modplcpp_getfield:
Extrae un campo del mensaje.
*/
int modplcpp_getfield(modplcpp_msg *msg, modplcpp_ftype *type,
unsigned char *count, void *dat)
{
/* Variables. */
unsigned char c;
/* Contador. */
unsigned char *ptr;
/* Puntero a los datos. */

/* Verifica que el puntero al mensaje no sea nulo. */


if (!msg) return 0;
/* Inicializa el puntero a los datos. */
ptr = (unsigned char *) dat;
/* Extrae el tipo de dato. */
*type = *(msg->dat + msg->startoffset);
msg->startoffset += sizeof(modplcpp_ftype);
/* Extrae la cantidad de datos. */
c = *(msg->dat + msg->startoffset);
*count = c;
msg->startoffset += sizeof(unsigned char);
/* Agrega datos tipo caracter o entero de 8 bits. */
if ((*type == MODPLCPP_CHARTYPE) || (*type == MODPLCPP_SINT8TYPE) ||
(*type == MODPLCPP_UINT8TYPE))
{
while(c --)
{
*ptr = *(msg->dat + msg->startoffset);
ptr += sizeof(unsigned char);
msg->startoffset += sizeof(unsigned char);
}
return 1;
}

324

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Agrega datos tipo entero de 16 bits. */
if ((*type == MODPLCPP_SINT16TYPE) || (*type == MODPLCPP_UINT16TYPE))
{
while(c --)
{
*(ptr + 1) = *(msg->dat + msg->startoffset + 0);
*(ptr + 0) = *(msg->dat + msg->startoffset + 1);
ptr += sizeof(unsigned short int);
msg->startoffset += sizeof(unsigned short int);
}
return 1;
}
/* Agrega datos tipo entero de 32 bits. */
if ((*type == MODPLCPP_SINT32TYPE) || (*type == MODPLCPP_UINT32TYPE))
{
while(c --)
{
*(ptr + 3) = *(msg->dat + msg->startoffset + 0);
*(ptr + 2) = *(msg->dat + msg->startoffset + 1);
*(ptr + 1) = *(msg->dat + msg->startoffset + 2);
*(ptr + 0) = *(msg->dat + msg->startoffset + 3);
ptr += sizeof(unsigned long int);
msg->startoffset += sizeof(unsigned long int);
}
return 1;
}
/* Agrega datos tipo punto flotante. */
if (*type == MODPLCPP_FLOATTYPE)
{
while(c --)
{
*ptr = *(msg->dat + msg->startoffset);
ptr += sizeof(float);
msg->startoffset += sizeof(float);
}
return 1;
}
/* Tipo de dato desconocido. */
msg->startoffset -= sizeof(unsigned char);
msg->startoffset -= sizeof(modplcpp_ftype);
return 0;
}
/*
Funcin modplcpp_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return msg->grpid;
}
/*
Funcin modplcpp_destroymsg:
Destruye un mensaje.
*/
int modplcpp_destroymsg(modplcpp_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Elimina el contenido del mensaje. */
if (!msg->dat) return 0;
free(msg->dat);

FernandoArielBeunza79156

325

Tesis de Grado en Ingeniera Informtica


msg->dat = NULL;
return 1;
}
/*
Funcin modplcpp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcpp_notify(modplcpp_hd *hd, void (*func)(modplcpp_hd *,
modplcpp_msg *, void *), void *param)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Define un manejador de mensajes recibidos. */
hd->recfun = func;
hd->param = param;
return 1;
}
/*
Funcin modplcpp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcpp_poll(modplcpp_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Verifica la llegada de un nuevo mensaje. */
return (hd->buffer.endoffset != 0);
}
/*
Funcin modplcpp_status:
Devuelve el estado del modem PLC.
*/
int modplcpp_status(modplcpp_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Devuelve el estado del modem PLC. */
return modplcsp_status(hd->modsphd);
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcpp_procmsg__:
Procesa un mensaje recibido por medio de la capa de sesin.
*/
static void __modplcpp_procmsg__(modplcsp_hd *hd, modplcsp_grpid grpid,
const void *msg, size_t msgsize,
void *param)
{
/* Variables. */
modplcpp_hd *pphd;
/* Manejador de capa de
presentacin. */

/* Carga el manejador de capa de presentacin. */


pphd = (modplcpp_hd *) param;
/* Verifica si el buffer se encuentra lleno. */
if (pphd->buffer.endoffset != 0) return;
/* Reserva memoria para almacenar el mensaje recibido. */
pphd->buffer.dat =
(unsigned char *) malloc(msgsize * sizeof(unsigned char));

326

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (!pphd->buffer.dat) return;
/* Acepta el mensaje recibido. */
pphd->buffer.grpid = grpid;
pphd->buffer.startoffset = 0;
pphd->buffer.endoffset = msgsize;
pphd->buffer.pphd = pphd;
memcpy(pphd->buffer.dat, msg, msgsize);
/* Invoca a la funcin de atencin de recepcin de mensajes registrada. */
if (!pphd->recfun) return;
pphd->recfun(pphd, &(pphd->buffer), pphd->param);
pphd->buffer.endoffset = 0;
free(pphd->buffer.dat);
}

C.3.1.6. Archivo modplcap.h


/*
modplcap.h:
Declaracin de funciones referentes a la interfaz de la capa de aplicacin
del modem PLC.
*/

#if !defined(__MODPLCAP_H__)
#define __MODPLCAP_H__

/* Archivos includos necesarios. */


#include <windows.h>

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcap_grpid;
/* Identificador de mensaje. */
typedef unsigned short int modplcap_msgid;
/* Tipo de campo. */
typedef unsigned char modplcap_ftype;
/* Estructura del mensaje. */
typedef struct
{
modplcap_msgid msgid;
void *msg;
} modplcap_msg;
/* Manejador de capa de aplicacin. */
typedef struct
{
int msgflag;
modplcap_grpid grpid;

void *pphd;
void (*recfun)
(void *, modplcap_msg *, void *);
void *param;

modplcap_msg buffer;

FernandoArielBeunza79156

/* Identificador de mensaje. */
/* Puntero al mensaje. */

/* Indicador de mensaje en el
buffer. */
/* Identificador de grupo del
mensaje almacenado en el
buffer. */
/* Puntero al manejador de capa de
presentacin. */
/* Funcin manejadora de mensajes
recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
/* Puntero al buffer de campos

327

Tesis de Grado en Ingeniera Informtica


recibidos. */
} modplcap_hd;

/* Definicin de constantes. */
/* Tipos de datos. */
#define MODPLCAP_NULLTYPE
#define MODPLCAP_CHARTYPE
#define MODPLCAP_SINT8TYPE
#define MODPLCAP_UINT8TYPE
#define MODPLCAP_SINT16TYPE
#define MODPLCAP_UINT16TYPE
#define MODPLCAP_SINT32TYPE
#define MODPLCAP_UINT32TYPE
#define MODPLCAP_FLOATTYPE

0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08

/* Declaracin de funciones pblicas. */


#if !defined(__MODPLCAP_DLL__)
/*
Funcin modplcap_init:
Inicializa los recursos utilizados por la capa de aplicacin del modem PLC.
*/
static modplcap_hd * (*modplcap_init)(int);
/*
Funcin modplcap_release:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
static int (*modplcap_release)(modplcap_hd *);
/*
Funcin modplcap_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
static int (*modplcap_publish)(modplcap_hd *, modplcap_grpid);
/*
Funcin modplcap_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
static int (*modplcap_subscribe)(modplcap_hd *, modplcap_grpid);
/*
Funcin modplcap_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
static int (*modplcap_leave)(modplcap_hd *, modplcap_grpid);
/*
Funcin modplcap_newmsg:
Crea un nuevo mensaje.
*/
static int (*modplcap_newmsg)(modplcap_hd *, modplcap_msg *, modplcap_grpid,
modplcap_msgid);
/*
Funcin modplcap_copymsg:
Crea un copia de un mensaje.
*/
static int (*modplcap_copymsg)(modplcap_msg *, modplcap_msg *);
/*
Funcin modplcap_putfield:
Agrega un nuevo campo al mensaje.
*/
static int (*modplcap_putfield)(modplcap_msg *, modplcap_ftype, unsigned char,
const void *);

328

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcap_sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
static int (*modplcap_sendmsg)(modplcap_msg *);
/*
Funcin modplcap_receivemsg:
Recibe un mensaje por medio de la capa de aplicacin.
*/
static int (*modplcap_receivemsg)(modplcap_hd *, modplcap_msg *);
/*
Funcin modplcap_getfield:
Extrae un campo del mensaje.
*/
static int (*modplcap_getfield)(modplcap_msg *, modplcap_ftype *,
unsigned char *, void *);
/*
Funcin modplcap_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
static modplcap_grpid (*modplcap_getgrpid)(modplcap_msg *);
/*
Funcin modplcap_getmsgid:
Devuelve el identificador de mensaje.
*/
static modplcap_msgid (*modplcap_getmsgid)(modplcap_msg *);
/*
Funcin modplcap_destroymsg:
Destruye un mensaje.
*/
static int (*modplcap_destroymsg)(modplcap_msg *);
/*
Funcin modplcap_notify:
Define una funcin manejadora de mensajes recibidos.
*/
static int (*modplcap_notify)(modplcap_hd *, void (*func)(modplcap_hd *,
modplcap_msg *, void *), void *);
/*
Funcin modplcap_poll:
Verifica la llegada de un nuevo mensaje.
*/
static int (*modplcap_poll)(modplcap_hd *);
/*
Funcin modplcap_status:
Devuelve el estado del modem PLC.
*/
static int (*modplcap_status)(modplcap_hd *);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_loadlib:
Carga la bliblioteca dinmica referente a la capa de aplicacin del modem
PLC.
*/
static int modplcap_loadlib(void)
{
/* Variables. */
struct HINSTANCE__ *hlib;

FernandoArielBeunza79156

/* Manejador de biblioteca
dinmica. */

329

Tesis de Grado en Ingeniera Informtica


/* Carga la biblioteca. */
hlib = NULL;
modplcap_init = NULL;
modplcap_release = NULL;
modplcap_publish = NULL;
modplcap_subscribe = NULL;
modplcap_leave = NULL;
modplcap_newmsg = NULL;
modplcap_copymsg = NULL;
modplcap_putfield = NULL;
modplcap_sendmsg = NULL;
modplcap_receivemsg = NULL;
modplcap_getfield = NULL;
modplcap_getgrpid = NULL;
modplcap_getmsgid = NULL;
modplcap_destroymsg = NULL;
modplcap_notify = NULL;
modplcap_poll = NULL;
modplcap_status = NULL;
hlib = LoadLibrary("MODPLCAP");
if (!hlib) return 0;
modplcap_init = (modplcap_hd * (*)(int))
GetProcAddress(hlib, "modplcap_init");
modplcap_release = (int (*)(modplcap_hd *))
GetProcAddress(hlib, "modplcap_release");
modplcap_publish = (int (*)(modplcap_hd *, modplcap_grpid))
GetProcAddress(hlib, "modplcap_publish");
modplcap_subscribe = (int (*)(modplcap_hd *, modplcap_grpid))
GetProcAddress(hlib, "modplcap_subscribe");
modplcap_leave = (int (*)(modplcap_hd *, modplcap_grpid))
GetProcAddress(hlib, "modplcap_leave");
modplcap_newmsg = (int (*)(modplcap_hd *, modplcap_msg *, modplcap_grpid,
modplcap_msgid))
GetProcAddress(hlib, "modplcap_newmsg");
modplcap_copymsg = (int (*)(modplcap_msg *, modplcap_msg *))
GetProcAddress(hlib, "modplcap_copymsg");
modplcap_putfield = (int (*)(modplcap_msg *, modplcap_ftype, unsigned char,
const void *))
GetProcAddress(hlib, "modplcap_putfield");
modplcap_sendmsg = (int (*)(modplcap_msg *))
GetProcAddress(hlib, "modplcap_sendmsg");
modplcap_receivemsg = (int (*)(modplcap_hd *, modplcap_msg *))
GetProcAddress(hlib, "modplcap_receivemsg");
modplcap_getfield = (int (*)(modplcap_msg *, modplcap_ftype *,
unsigned char *, void *))
GetProcAddress(hlib, "modplcap_getfield");
modplcap_getgrpid = (modplcap_grpid (*)(modplcap_msg *))
GetProcAddress(hlib, "modplcap_getgrpid");
modplcap_getmsgid = (modplcap_msgid (*)(modplcap_msg *))
GetProcAddress(hlib, "modplcap_getmsgid");
modplcap_destroymsg = (int (*)(modplcap_msg *))
GetProcAddress(hlib, "modplcap_destroymsg");
modplcap_notify = (int (*)(modplcap_hd *, void (*func)(modplcap_hd *,
modplcap_msg *, void *), void *))
GetProcAddress(hlib, "modplcap_notify");
modplcap_poll = (int (*)(modplcap_hd *))
GetProcAddress(hlib, "modplcap_poll");
modplcap_status = (int (*)(modplcap_hd *))
GetProcAddress(hlib, "modplcap_status");
/* Verifica que todas las funciones de la biblioteca se hayan cargado. */
if ((!modplcap_init) || (!modplcap_release) || (!modplcap_publish) ||
(!modplcap_subscribe) || (!modplcap_leave) || (!modplcap_newmsg) ||
(!modplcap_copymsg) || (!modplcap_putfield) || (!modplcap_sendmsg) ||
(!modplcap_receivemsg) || (!modplcap_getfield) ||
(!modplcap_getgrpid) || (!modplcap_getmsgid) ||
(!modplcap_destroymsg) || (!modplcap_notify) || (!modplcap_poll) ||
(!modplcap_status))
return 0;
/* xito. */

330

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return 1;
}
#endif

#endif

C.3.1.7. Archivo modplcap.c


/*
modplcap.c:
Implementacin de funciones referentes a la capa de aplicacin del modem
PLC.
*/

/* Archivos includos necesarios. */


#define __MODPLCAP_DLL__
#include "config.h"
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "modplcpp.h"
#include "modplcap.h"

/* Declaracin de funciones pblicas. */


modplcap_hd *modplcap_init(int);
int modplcap_release(modplcap_hd *);
int modplcap_publish(modplcap_hd *, modplcap_grpid);
int modplcap_subscribe(modplcap_hd *, modplcap_grpid);
int modplcap_leave(modplcap_hd *, modplcap_grpid);
int modplcap_newmsg(modplcap_hd *, modplcap_msg *, modplcap_grpid,
modplcap_msgid);
int modplcap_putfield(modplcap_msg *, modplcap_ftype, unsigned char,
const void *);
int modplcap_sendmsg(modplcap_msg *);
int modplcap_receivemsg(modplcap_hd *, modplcap_msg *);
int modplcap_getfield(modplcap_msg *, modplcap_ftype *, unsigned char *,
void *);
modplcap_grpid modplcap_getgrpid(modplcap_msg *);
modplcap_msgid modplcap_getmsgid(modplcap_msg *);
int modplcap_destroymsg(modplcap_msg *);
int modplcap_notify(modplcap_hd *, void (*func)(modplcap_hd *, modplcap_msg *,
void *), void *);
int modplcap_poll(modplcap_hd *);
int modplcap_status(modplcap_hd *);

/* Declaracin de funciones privadas. */


static void __modplcap_procmsg__(modplcpp_hd *, modplcpp_msg *, void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_init:
Inicializa los recursos utilizados por la capa de aplicacin del modem PLC.
*/
modplcap_hd *modplcap_init(int sid)
{
/* Variables. */
modplcap_hd *handle;

/* Manejador de capa de
aplicacin. */

/* Crea un nuevo manejador de capa de aplicacin. */


handle = (modplcap_hd *) malloc(sizeof(modplcap_hd));

FernandoArielBeunza79156

331

Tesis de Grado en Ingeniera Informtica


if (!handle) return NULL;
/* Inicializa el manejador de capa de aplicacin. */
while(1)
{
/* Inicializa el manejador de capa de presentancin. */
handle->pphd = modplcpp_init(sid);
if (!handle->pphd) break;
/* Define un manejador de mensajes recibidos por la capa de
presentacin. */
if (!modplcpp_notify((modplcpp_hd *) handle->pphd,
__modplcap_procmsg__, handle))
break;
/* Inicializa el buffer. */
handle->msgflag = 0;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de aplicacin. */
modplcpp_release((modplcpp_hd *) handle->pphd);
free(handle);
return NULL;
}
/*
Funcin modplcap_release:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
int modplcap_release(modplcap_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modplcpp_notify((modplcpp_hd *) hd->pphd, NULL, NULL);
/* Libera la interfaz con la capa de presentacin. */
modplcpp_release((modplcpp_hd *) hd->pphd);
/* Libera los recursos utilizados por la capa de aplicacin. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcap_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modplcap_publish(modplcap_hd *hd, modplcap_grpid grpid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
return modplcpp_publish((modplcpp_hd *) hd->pphd, grpid);
}
/*
Funcin modplcap_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.

332

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/
int modplcap_subscribe(modplcap_hd *hd, modplcap_grpid grpid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
return modplcpp_subscribe((modplcpp_hd *) hd->pphd, grpid);
}
/*
Funcin modplcap_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcap_leave(modplcap_hd *hd, modplcap_grpid grpid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
return modplcpp_leave((modplcpp_hd *) hd->pphd, grpid);
}
/*
Funcin modplcap_newmsg:
Crea un nuevo mensaje.
*/
int modplcap_newmsg(modplcap_hd *hd, modplcap_msg *msg, modplcap_grpid grpid,
modplcap_msgid msgid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Inicializa el mensaje. */
msg->msgid = msgid;
msg->msg = malloc(sizeof(modplcpp_msg));
if (!msg->msg) return 0;
while(1)
{
if (msgid & 0x8000)
{
if (!modplcpp_newmsg((modplcpp_hd *) hd->pphd,
(modplcpp_msg *) (msg->msg), grpid, MODPLCPP_NOSECMSG))
break;
}
else
{
if (!modplcpp_newmsg((modplcpp_hd *) hd->pphd,
(modplcpp_msg *) (msg->msg), grpid, MODPLCPP_SECMSG))
break;
}
if (!modplcpp_putfield((modplcpp_msg *) (msg->msg),
MODPLCPP_UINT16TYPE, 1, &msgid))
break;
return 1;
}
free(msg->msg);
msg->msg = NULL;
return 0;
}
/*
Funcin modplcap_copymsg:
Crea un copia de un mensaje.
*/
int modplcap_copymsg(modplcap_msg *dest, modplcap_msg *src)
{

FernandoArielBeunza79156

333

Tesis de Grado en Ingeniera Informtica


/* Verifica que el puntero al mensaje original no sea nulo. */
if (!src) return 0;
/* Verifica que el puntero a la copia del mensaje no sea nulo. */
if (!dest) return 0;
/* Copia el mensaje. */
dest->msgid = src->msgid;
return modplcpp_copymsg((modplcpp_msg *) (dest->msg),
(modplcpp_msg *) (src->msg));
}
/*
Funcin modplcap_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcap_putfield(modplcap_msg *msg, modplcap_ftype type,
unsigned char count, const void *dat)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Agrega un nuevo campo al mensaje. */
return modplcpp_putfield((modplcpp_msg *) (msg->msg), type, count, dat);
}
/*
Funcin modplcap_sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
int modplcap_sendmsg(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Enva un mensaje. */
return modplcpp_sendmsg((modplcpp_msg *) (msg->msg));
}
/*
Funcin modplcap_receivemsg:
Recibe un mensaje por medio de la capa de aplicacin.
*/
int modplcap_receivemsg(modplcap_hd *hd, modplcap_msg *msg)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Espera la llegada de un mensaje. */
while(!modplcap_poll(hd));
/* Recibe un mensaje. */
if (msg)
{
msg->msgid = hd->buffer.msgid;
msg->msg = malloc(sizeof(modplcpp_msg));
if (!msg->msg) return 0;
memcpy((modplcpp_msg *) (msg->msg), (modplcpp_msg *) (hd->buffer.msg),
sizeof(modplcpp_msg));
}
modplcpp_destroymsg(hd->buffer.msg);
free(hd->buffer.msg);
hd->msgflag = 0;
return 1;
}
/*
Funcin modplcap_getfield:
Extrae un campo del mensaje.
*/
int modplcap_getfield(modplcap_msg *msg, modplcap_ftype *type,

334

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


unsigned char *count, void *dat)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Extrae un campo del mensaje. */
return modplcpp_getfield((modplcpp_msg *) (msg->msg), type, count, dat);
}
/*
Funcin modplcap_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcap_grpid modplcap_getgrpid(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return ((modplcpp_msg *) (msg->msg))->grpid;
}
/*
Funcin modplcap_getmsgid:
Devuelve el identificador de mensaje.
*/
modplcap_msgid modplcap_getmsgid(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return msg->msgid;
}
/*
Funcin modplcap_destroymsg:
Destruye un mensaje.
*/
int modplcap_destroymsg(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Destruye el mensaje. */
free(msg->msg);
msg->msg = NULL;
return 1;
}
/*
Funcin modplcap_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcap_notify(modplcap_hd *hd, void (*func)(modplcap_hd *,
modplcap_msg *, void *), void *param)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Define un manejador de mensajes recibidos. */
hd->recfun = func;
hd->param = param;
return 1;
}
/*
Funcin modplcap_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcap_poll(modplcap_hd *hd)

FernandoArielBeunza79156

335

Tesis de Grado en Ingeniera Informtica


{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Verifica la llegada de un nuevo mensaje. */
return (hd->msgflag != 0);
}
/*
Funcin modplcap_status:
Devuelve el estado del modem PLC.
*/
int modplcap_status(modplcap_hd *hd)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Devuelve el estado del modem PLC. */
return modplcpp_status(hd->pphd);
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcap_procmsg__:
Procesa un mensaje recibido por medio de la capa de presentacin.
*/
static void __modplcap_procmsg__(modplcpp_hd *hd, modplcpp_msg *msg, void *param)
{
/* Variables. */
modplcpp_ftype type;
/* Tipo de campo. */
modplcap_msgid msgid;
/* Identificador de mensaje. */
unsigned char count;
/* Contador. */
modplcap_hd *aphd;
/* Manejador de capa de
aplicacin. */

/* Carga el manejador de capa de aplicacin. */


aphd = (modplcap_hd *) param;
/* Verifica si el buffer se encuentra lleno. */
if (aphd->msgflag) return;
/*
if
if
if

Recibe el mensaje. */
(!modplcpp_getfield(msg, &type, &count, &msgid)) return;
(type != MODPLCPP_UINT16TYPE) return;
(count != 1) return;

/* Acepta el mensaje recibido. */


aphd->buffer.msgid = msgid;
aphd->buffer.msg = malloc(sizeof(modplcpp_msg));
if (!aphd->buffer.msg) return;
if (!modplcpp_copymsg((modplcpp_msg *) aphd->buffer.msg, msg)) return;
aphd->msgflag = 1;
/* Invoca a la funcin de atencin de recepcin de mensajes registrada. */
if (!aphd->recfun) return;
aphd->recfun(aphd, &(aphd->buffer), aphd->param);
modplcpp_destroymsg(aphd->buffer.msg);
free(aphd->buffer.msg);
aphd->msgflag = 0;
}

336

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.3.2. Interfaz capa de enlace modplcdl.dll


En esta seccin se detalla el cdigo fuente de la biblioteca que implementa la interfaz con la
capa de enlace del modem PLC, que se compone de los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin de la biblioteca


dinmica que implementa la capa de enlace del modem PLC que no pueden ser
modificados en tiempo de ejecucin.

Archivo modplcdl.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa de enlace. Dichas primitivas brindan un conjunto de funcionalidades
que permiten la comunicacin con la capa de enlace implementada en el modem PLC por
medio del driver del mismo.

Archivo modplcdl.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcdl.h.

C.3.2.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz con el driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa de enlace. */
#define MODDRVDL_CLOSE
0x00
#define MODDRVDL_OPEN
0x01
#define MODDRVDL_SEND
0x02
#define MODDRVDL_RECEIVE
0x03
#define MODDRVDL_POLL
0x04
#define MODDRVDL_GETADDRESS
0x05
#define MODDRVDL_ADDLOGADDRESS
0x06
#define MODDRVDL_DELLOGADDRESS
0x07
#define MODDRVDL_GETPHYADDRESS
0x08
#define MODDRVDL_STATUS
0x09
#define MODDRVDL_GETPAYLOADSIZE
0x0a

#endif

C.3.2.2. Archivo modplcdl.h


/*
modplcdl.h:
Declaracin de funciones referentes a la interfaz de la capa de enlace del
modem PLC.
*/

#if !defined(__MODPLCDL_H__)
#define __MODPLCDL_H__

FernandoArielBeunza79156

337

Tesis de Grado en Ingeniera Informtica

/* Archivos includos necesarios. */


#include <windows.h>

/* Definicin de tipos. */
/* Direccin fsica del modem PLC. */
typedef unsigned char modplcdl_phyaddr[8];
/* Direccin lgica del modem PLC. */
typedef unsigned long int modplcdl_logaddr;
/* Manejador de interfaz con la capa de enlace del modem PLC. */
typedef struct
{
HANDLE hq;
/* Manejador de cola de
mensajes. */
HANDLE hm;
/* Semforo de exclusin mtua. */
unsigned char sid;
/* Identificador de interfaz de
comunicacin por puerto
serie. */
unsigned long int conncounter;
/* Contador de conexiones
abiertas. */
} modplcdl_hd;
/* Manejador de conexin por medio de la capa de enlace del modem PLC. */
typedef struct
{
HANDLE hq;
/* Manejador de cola de
mensajes. */
HANDLE detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
modplcdl_hd *dlhd;
/* Manejador de interfaz con la
capa de enlance del modem
PLC. */
void (*recfun)
(void *, modplcdl_phyaddr, void *,
size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} modplcdlconn_hd;

/* Declaracin de funciones pblicas. */


#if !defined(__MODPLCDL_DLL__)
/*
Funcin modplcdl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
static modplcdl_hd * (*modplcdl_init)(int);
/*
Funcin modplcdl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
static int (*modplcdl_release)(modplcdl_hd *);
/*
Funcin modplcdl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
static modplcdlconn_hd * (*modplcdl_open)(modplcdl_hd *, unsigned char,
unsigned char);

338

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcdl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
static int (*modplcdl_close)(modplcdlconn_hd *);
/*
Funcin modplcdl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
static size_t (*modplcdl_send)(modplcdlconn_hd *, modplcdl_phyaddr,
unsigned char, const void *, size_t);
/*
Funcin modplcdl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
static size_t (*modplcdl_receive)(modplcdlconn_hd *, modplcdl_phyaddr, void *,
size_t);
/*
Funcin modplcdl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
static int (*modplcdl_notify)(modplcdlconn_hd *, void (*func)(void *,
modplcdl_phyaddr, void *, size_t, void *),
void *);
/*
Funcin modplcdl_poll:
Verifica la recepcin de un mensaje.
*/
static int (*modplcdl_poll)(modplcdlconn_hd *);
/*
Funcin modplcdl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
static int (*modplcdl_getaddress)(modplcdl_hd *, unsigned char,
modplcdl_phyaddr);
/*
Funcin modplcdl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
static int (*modplcdl_addlogaddress)(modplcdl_hd *, unsigned char,
unsigned char, modplcdl_logaddr);
/*
Funcin modplcdl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
static int (*modplcdl_dellogaddress)(modplcdl_hd *, unsigned char,
unsigned char, modplcdl_logaddr);
/*
Funcin modplcdl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa de
enlace del modem PLC.
*/
static int (*modplcdl_getphyaddress)(modplcdl_hd *hd, unsigned char,
unsigned char, modplcdl_logaddr,
modplcdl_phyaddr);
/*
Funcin modplcdl_status:
Devuelve el estado del modem PLC.
*/
static int (*modplcdl_status)(modplcdl_hd *);
/*

FernandoArielBeunza79156

339

Tesis de Grado en Ingeniera Informtica


Funcin modplcdl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de enlace del modem PLC.
*/
static size_t (*modplcdl_getpayloadsize)(modplcdl_hd *, unsigned char);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcdl_loadlib:
Carga la bliblioteca dinmica referente a la capa de enlace del modem PLC.
*/
static int modplcdl_loadlib(void)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca
dinmica. */

/* Carga la biblioteca. */
hlib = NULL;
modplcdl_init = NULL;
modplcdl_release = NULL;
modplcdl_open = NULL;
modplcdl_close = NULL;
modplcdl_send = NULL;
modplcdl_receive = NULL;
modplcdl_notify = NULL;
modplcdl_poll = NULL;
modplcdl_getaddress = NULL;
modplcdl_addlogaddress = NULL;
modplcdl_dellogaddress = NULL;
modplcdl_getphyaddress = NULL;
modplcdl_status = NULL;
modplcdl_getpayloadsize = NULL;
hlib = LoadLibrary("MODPLCDL");
if (!hlib) return 0;
modplcdl_init = (modplcdl_hd * (*)(int))
GetProcAddress(hlib, "modplcdl_init");
modplcdl_release = (int (*)(modplcdl_hd *))
GetProcAddress(hlib, "modplcdl_release");
modplcdl_open = (modplcdlconn_hd * (*)(modplcdl_hd *, unsigned char,
unsigned char))
GetProcAddress(hlib, "modplcdl_open");
modplcdl_close = (int (*)(modplcdlconn_hd *))
GetProcAddress(hlib, "modplcdl_close");
modplcdl_send = (size_t (*)(modplcdlconn_hd *, modplcdl_phyaddr,
unsigned char, const void *, size_t))
GetProcAddress(hlib, "modplcdl_send");
modplcdl_receive = (size_t (*)(modplcdlconn_hd *, modplcdl_phyaddr, void *,
size_t))
GetProcAddress(hlib, "modplcdl_receive");
modplcdl_notify = (int (*)(modplcdlconn_hd *, void (*func)(void *,
modplcdl_phyaddr, void *, size_t, void *),
void *))
GetProcAddress(hlib, "modplcdl_notify");
modplcdl_poll = (int (*)(modplcdlconn_hd *))
GetProcAddress(hlib, "modplcdl_poll");
modplcdl_getaddress = (int (*)(modplcdl_hd *, unsigned char,
modplcdl_phyaddr))
GetProcAddress(hlib, "modplcdl_getaddress");
modplcdl_addlogaddress = (int (*)(modplcdl_hd *, unsigned char,
unsigned char, modplcdl_logaddr))
GetProcAddress(hlib, "modplcdl_addlogaddress");
modplcdl_dellogaddress = (int (*)(modplcdl_hd *, unsigned char,
unsigned char, modplcdl_logaddr))
GetProcAddress(hlib, "modplcdl_dellogaddress");
modplcdl_getphyaddress = (int (*)(modplcdl_hd *hd, unsigned char,
unsigned char, modplcdl_logaddr,
modplcdl_phyaddr))

340

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


GetProcAddress(hlib, "modplcdl_getphyaddress");
modplcdl_status = (int (*)(modplcdl_hd *))
GetProcAddress(hlib, "modplcdl_status");
modplcdl_getpayloadsize = (size_t (*)(modplcdl_hd *, unsigned char))
GetProcAddress(hlib, "modplcdl_getpayloadsize");
/* Verifica que todas las funciones de la biblioteca se hayan cargado. */
if ((!modplcdl_init) || (!modplcdl_release) || (!modplcdl_open) ||
(!modplcdl_close) || (!modplcdl_send) || (!modplcdl_receive) ||
(!modplcdl_notify) || (!modplcdl_poll) || (!modplcdl_getaddress) ||
(!modplcdl_addlogaddress) || (!modplcdl_dellogaddress) ||
(!modplcdl_getphyaddress) || (!modplcdl_status) ||
(!modplcdl_getpayloadsize))
return 0;
/* xito. */
return 1;
}
#endif

#endif

C.3.2.3. Archivo modplcdl.c


/*
modplcdl.c:
Implementacin de funciones referentes a la interfaz de la capa de enlace
del modem PLC.
*/

/* Archivos includos necesarios. */


#define __MODPLCDL_DLL__
#include "config.h"
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "modplcdl.h"

/* Declaracin de funciones pblicas. */


modplcdl_hd *modplcdl_init(int);
int modplcdl_release(modplcdl_hd *);
modplcdlconn_hd *modplcdl_open(modplcdl_hd *, unsigned char, unsigned char);
int modplcdl_release(modplcdl_hd *);
size_t modplcdl_send(modplcdlconn_hd *, modplcdl_phyaddr, unsigned char,
const void *, size_t);
size_t modplcdl_receive(modplcdlconn_hd *, modplcdl_phyaddr, void *, size_t);
int modplcdl_notify(modplcdlconn_hd *, void (*func)(void *, modplcdl_phyaddr,
void *, size_t, void *), void *);
int modplcdl_poll(modplcdlconn_hd *);
int modplcdl_getaddress(modplcdl_hd *, unsigned char, modplcdl_phyaddr);
int modplcdl_addlogaddress(modplcdl_hd *, unsigned char, unsigned char,
modplcdl_logaddr);
int modplcdl_dellogaddress(modplcdl_hd *, unsigned char, unsigned char,
modplcdl_logaddr);
int modplcdl_getphyaddress(modplcdl_hd *hd, unsigned char, unsigned char,
modplcdl_logaddr, modplcdl_phyaddr);
int modplcdl_status(modplcdl_hd *);
size_t modplcdl_getpayloadsize(modplcdl_hd *, unsigned char);

/* Declaracin de funciones privadas. */


static DWORD WINAPI __modplcdl_detectproc__(LPVOID);
static int __modplcdl_sendrecv__(HANDLE, void *, size_t, const void *, size_t);

FernandoArielBeunza79156

341

Tesis de Grado en Ingeniera Informtica


/* Implementacin de funciones pblicas. */
/*
Funcin modplcdl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
modplcdl_hd *modplcdl_init(int sid)
{
/* Variables. */
int layer;
int result;
modplcdl_hd *handle;
char qname[256];

/* Capa a la que se quiere


accerder. */
/* Resultado de la solicitud. */
/* Manejador de interfaz con la
capa de enlace del modem PLC. */
/* Nombre de la cola de
mensajes. */

/* Crea un nuevo manejador de interfaz con la capa de enlace del modem


PLC. */
handle = (modplcdl_hd *) malloc(sizeof(modplcdl_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de enlace del modem
PLC. */
while(1)
{
/* Abre una conexin con la cola de mensajes del driver del modem
PLC. */
sprintf(qname, "\\\\.\\pipe\\modemplc%i", sid);
handle->hq = CreateFile(qname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle->hq == INVALID_HANDLE_VALUE) break;
/* Inicializa semforo de exclusin mtua. */
handle->hm = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->hm == INVALID_HANDLE_VALUE) break;
/* Solicita acceder a la capa de enlace del modem PLC. */
layer = 2;
if (!__modplcdl_sendrecv__(handle->hq, &result, sizeof(result), &layer,
sizeof(layer)))
break;
if (!result) break;
/* Almacena la interfaz de comunicacin por puerto serie. */
handle->sid = sid;
/* Inicializa el contador de conexiones abiertas. */
handle->conncounter = 0;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de enlace del modem
PLC. */
CloseHandle(handle->hm);
CloseHandle(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcdl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int modplcdl_release(modplcdl_hd *hd)
{
/* Variables. */

342

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int op;
int result;

/* Identificador de operacin. */
/* Resultado de la solicitud. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return 0;
/* Verifica que no existan conexiones abiertas. */
if (hd->conncounter) return 0;
/* Solicita el cierre de la conexin. */
op = MODDRVDL_CLOSE;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Libera los recursos utilizados por la interfaz con la capa de enlace del
modem PLC. */
CloseHandle(hd->hq);
CloseHandle(hd->hm);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcdl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
modplcdlconn_hd *modplcdl_open(modplcdl_hd *hd, unsigned char iface,
unsigned char prot)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int layer;
/* Capa a la que se quiere
accerder. */
int result;
/* Resultado de la solicitud. */
size_t payloadsize;
/* Cantidad de bytes que puede
contener un mensaje. */
modplcdlconn_hd *handle;
/* Manejador de conexin de la capa
de enlace del modem PLC. */
char qname[256];
/* Nombre de la cola de
mensajes. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return NULL;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Crea un nuevo manejador de conexin por medio de la capa de enlace del
modem PLC. */
handle = (modplcdlconn_hd *) malloc(sizeof(modplcdlconn_hd));
if (!handle)
{
ReleaseSemaphore(hd->hm, 1, NULL);
return NULL;
}
/* Inicializa el manejador de conexin. */
while(1)
{
/* Carga el manejador de interfaz con la capa de enlace del modem
PLC. */
handle->dlhd = hd;

FernandoArielBeunza79156

343

Tesis de Grado en Ingeniera Informtica


/* Abre una conexin con la cola de mensajes del driver del modem
PLC. */
sprintf(qname, "\\\\.\\pipe\\modemplc%i", hd->sid);
handle->hq = CreateFile(qname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle->hq == INVALID_HANDLE_VALUE) break;
/* Solicita acceder a la capa de enlace del modem PLC. */
layer = 2;
if (!__modplcdl_sendrecv__(handle->hq, &result, sizeof(result), &layer,
sizeof(layer)))
break;
if (!result) break;
/* Solicita abrir una conexin. */
op = MODDRVDL_OPEN;
if (!__modplcdl_sendrecv__(handle->hq, NULL, 0, &op, sizeof(op)))
break;
if (!__modplcdl_sendrecv__(handle->hq, NULL, 0, &iface, sizeof(iface)))
break;
if (!__modplcdl_sendrecv__(handle->hq, &result, sizeof(result), &prot,
sizeof(prot)))
break;
if (!result) break;
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
op = MODDRVDL_GETPAYLOADSIZE;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, &payloadsize, sizeof(payloadsize),
&iface, sizeof(iface)))
break;
if (!payloadsize) break;
handle->payloadsize = payloadsize;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Actualiza el nmero de conexiones. */
handle->dlhd->conncounter ++;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el manejador creado. */
return handle;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* No se pudo abrir la conexin. */
CloseHandle(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcdl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplcdl_close(modplcdlconn_hd *hd)
{
/* Variables. */
int op;
int result;

344

/* Identificador de operacin. */
/* Resultado de la solicitud. */

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modplcdl_notify(hd, NULL, NULL);
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->dlhd->hm, INFINITE);
/* Solicita el cierre de la conexin. */
op = MODDRVDL_CLOSE;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Actualiza el nmero de conexiones. */
hd->dlhd->conncounter --;
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* Libera los recursos utilizados por la conexin por medio de la capa de
enlace del modem PLC. */
CloseHandle(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcdl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplcdl_send(modplcdlconn_hd *hd, modplcdl_phyaddr addr,
unsigned char prio, const void *msg, size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->dlhd->hm, INFINITE);
/* Enva un mensaje. */
while(1)
{
/* Solicita el envo de un mensaje. */
op = MODDRVDL_SEND;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva la direccin destinataria. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, addr,
sizeof(modplcdl_phyaddr)))
break;
/* Enva la prioridad del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prio, sizeof(prio)))
break;
/* Enva el tamao del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &msgsize, sizeof(msgsize)))
break;

FernandoArielBeunza79156

345

Tesis de Grado en Ingeniera Informtica


/* Enva el mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, &msgsize, sizeof(msgsize), msg,
msgsize))
break;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* Devuelve la cantidad de bytes enviados. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* No se pudo realizar el envo. */
return 0;
}
/*
Funcin modplcdl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplcdl_receive(modplcdlconn_hd *hd, modplcdl_phyaddr addr, void *msg,
size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->dlhd->hm, INFINITE);
/* Recibe
while(1)
{
/*
op
if

un mensaje. */

Solicita la recepcin de un mensaje. */


= MODDRVDL_RECEIVE;
(!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;

/* Enva la cantidad de bytes que se solicita recibir del mensaje. */


if (!__modplcdl_sendrecv__(hd->hq, &msgsize, sizeof(msgsize), &msgsize,
sizeof(msgsize)))
break;
if (!msgsize) break;
/* Recibe la direccin de origen del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, addr, sizeof(modplcdl_phyaddr),
NULL, 0))
break;
/* Recibe el mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, msg, msgsize, NULL, 0)) break;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* Devuelve la cantidad de bytes enviados. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* No se pudo realizar la recepcin. */

346

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return 0;
}
/*
Funcin modplcdl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcdl_notify(modplcdlconn_hd *hd, void (*func)(void *, modplcdl_phyaddr,
void *, size_t, void *), void *param)
{
/* Variables. */
DWORD tid;
/* Identificador de hilo. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
WaitForSingleObject(hd->dlhd->hm, INFINITE);
hd->recfun = func;
hd->param = param;
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora definida
previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
WaitForSingleObject(hd->dlhd->hm, INFINITE);
hd->recfun = NULL;
hd->param = param;
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
WaitForSingleObject(hd->detectthread, INFINITE);
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
WaitForSingleObject(hd->dlhd->hm, INFINITE);
hd->recfun = func;
hd->param = param;
hd->detectthread = CreateThread(NULL, 0, __modplcdl_detectproc__, hd,
0, &tid);
if (hd->detectthread == INVALID_HANDLE_VALUE)
{
hd->recfun = NULL;
hd->param = NULL;
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
return 0;
}
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modplcdl_poll:

FernandoArielBeunza79156

347

Tesis de Grado en Ingeniera Informtica


Verifica la recepcin de un mensaje.
*/
int modplcdl_poll(modplcdlconn_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->dlhd->hm, INFINITE);
/* Solicita verificar la recepcin de un mensaje. */
op = MODDRVDL_POLL;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplcdl_getaddress(modplcdl_hd *hd, unsigned char iface,
modplcdl_phyaddr addr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene la direccin fsica del modem PLC. */
result = 0;
while(1)
{
/* Solicita la direccin fsica del modem PLC. */
op = MODDRVDL_GETADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identifcador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &iface,
sizeof(iface)))
break;
if (!result) break;
/* Recibe la direccin fsica. */
if (!__modplcdl_sendrecv__(hd->hq, addr, sizeof(modplcdl_phyaddr),
NULL, 0))
result = 0;
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);

348

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplcdl_addlogaddress(modplcdl_hd *hd, unsigned char iface,
unsigned char prot, modplcdl_logaddr addr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Agrega una direccin lgica. */
result = 0;
while(1)
{
/* Solicita agregar una direccin lgica. */
op = MODDRVDL_ADDLOGADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &iface, sizeof(iface)))
break;
/* Enva el identificador de protocolo. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prot, sizeof(prot)))
break;
/* Enva la direccin lgica. */
__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &addr,
sizeof(addr));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplcdl_dellogaddress(modplcdl_hd *hd, unsigned char iface,
unsigned char prot, modplcdl_logaddr addr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);

FernandoArielBeunza79156

349

Tesis de Grado en Ingeniera Informtica


/* Elimina una direccin lgica. */
result = 0;
while(1)
{
/* Solicita la eliminacin de una direccin lgica. */
op = MODDRVDL_DELLOGADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &iface, sizeof(iface)))
break;
/* Enva el identificador de protocolo. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prot, sizeof(prot)))
break;
/* Enva la direccin lgica. */
__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &addr,
sizeof(addr));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa de
enlace del modem PLC.
*/
int modplcdl_getphyaddress(modplcdl_hd *hd, unsigned char iface,
unsigned char prot, modplcdl_logaddr laddr,
modplcdl_phyaddr paddr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene la direccin fsica asociada a la direccin lgica. */
result = 0;
while(1)
{
/* Solicita la direccin fsica. */
op = MODDRVDL_GETPHYADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &iface, sizeof(iface)))
break;
/* Enva el identificador de protocolo. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prot, sizeof(prot)))
break;
/* Enva la direccin lgica. */
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &laddr,
sizeof(laddr)))
break;

350

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (!result) break;
/* Recibe la direccin fsica. */
__modplcdl_sendrecv__(hd->hq, paddr, sizeof(modplcdl_phyaddr), NULL,
0);
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_status:
Devuelve el estado del modem PLC.
*/
int modplcdl_status(modplcdl_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene el estado del modem PLC. */
op = MODDRVDL_STATUS;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el estado del modem PLC. */
return result;
}
/*
Funcin modplcdl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de enlace del modem PLC.
*/
size_t modplcdl_getpayloadsize(modplcdl_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Operacin. */
size_t payloadsize;
/* Cantidad de bytes que puede
contener un mensaje. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
payloadsize = 0;
while(1)
{
/* Solicita la cantidad mxima de bytes que puede contener un

FernandoArielBeunza79156

351

Tesis de Grado en Ingeniera Informtica


mensaje. */
op = MODDRVDL_GETPAYLOADSIZE;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op))) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
__modplcdl_sendrecv__(hd->hq, &payloadsize, sizeof(payloadsize),
&iface, sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad mxima de bytes que puede contener un mensaje. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcdl_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser ledo.
*/
static DWORD WINAPI __modplcdl_detectproc__(LPVOID param)
{
/* Variables. */
int op;
int result;
int captureflag;
size_t msgsize;
modplcdl_phyaddr addr;
modplcdlconn_hd *hd;

void (*func)
(void *, modplcdl_phyaddr, void *,
size_t, void *);
unsigned char *msg;

/* Identificador de operacin. */
/* Resultado de la operacin. */
/* Indicador de captura de un
mensaje. */
/* Tamao del mensaje. */
/* Direccin de origen. */
/* Manejador de conexin por medio
de la capa de enlace del modem
PLC. */

/* Funcin manejadora de mensajes


recibidos. */
/* Puntero al mensaje recibido. */

/* Carga el manejador de interfaz con la capa de enlace del modem PLC. */


hd = (modplcdlconn_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
WaitForSingleObject(hd->dlhd->hm, INFINITE);
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
op = MODDRVDL_POLL;
if (__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
captureflag = result;
/* Recibe el mensaje. */
while(captureflag)
{
/* Solicita la recepcin de un mensaje. */
op = MODDRVDL_RECEIVE;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva la cantidad de bytes que se solicita recibir del

352

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


mensaje. */
msgsize = hd->payloadsize;
if (!__modplcdl_sendrecv__(hd->hq, &msgsize, sizeof(msgsize),
&msgsize, sizeof(msgsize)))
break;
if (!msgsize) break;
/* Recibe la direccin de origen del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, addr, sizeof(modplcdl_phyaddr),
NULL, 0))
break;
/* Recibe el mensaje. */
msg = (unsigned char *) malloc(msgsize * sizeof(unsigned char));
if (!msg)
{
captureflag = 0;
break;
}
__modplcdl_sendrecv__(hd->hq, msg, msgsize, NULL, 0);
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
/* Verifica si se ha detectado la recepcin de un mensaje para invocar
al manejador de mensajes recibidos. */
if (captureflag)
{
func(hd, addr, msg, msgsize, hd->param);
free(msg);
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
ReleaseSemaphore(hd->dlhd->hm, 1, NULL);
return 0;
}
/*
Funcin __modplcdl_sendrecv__:
Intercambia datos con el driver del modem PLC.
*/
static int __modplcdl_sendrecv__(HANDLE hq, void *outdata, size_t outsize,
const void *indata, size_t insize)
{
/* Variables. */
size_t last;
/* Cantidad de bytes enviados o
recibidos. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Verifica que el manejador de cola de mensajes exista. */


if (hq == INVALID_HANDLE_VALUE) return 0;
/* Enva la operacin. */
sent = 0;
while((indata) && (sent < insize))
{
if (!WriteFile(hq, indata, insize, &last, NULL)) return 0;
sent += last;
}
/* Recibe la respuesta. */
received = 0;
while((outdata) && (received < outsize))
{
if (!ReadFile(hq, outdata, outsize, &last, NULL)) return 0;

FernandoArielBeunza79156

353

Tesis de Grado en Ingeniera Informtica


received += last;
}
/* xito. */
return 1;
}

C.3.3. Interfaz capa fsica modplcphy.dll


En esta seccin se detalla el cdigo fuente de la biblioteca que implementa la interfaz con la
capa fsica del modem PLC, que se compone de los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin de la biblioteca


dinmica que implementa la interfaz con la capa fsica del modem PLC que no pueden ser
modificados en tiempo de ejecucin.

Archivo modplcphy.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa fsica. Dichas primitivas brindan un conjunto de funcionalidades que
permiten la comunicacin con la capa fsica implementada en el modem PLC por medio
del driver del mismo.

Archivo modplcphy.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcphy.h.

C.3.3.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz con el driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa fsica. */
#define MODDRVPHY_RELEASE
0x00
#define MODDRVPHY_SNDFRAME
0x01
#define MODDRVPHY_CAPFRAME
0x02
#define MODDRVPHY_GETFRAME
0x03
#define MODDRVPHY_POLL
0x04
#define MODDRVPHY_RSDFRAME
0x05
#define MODDRVPHY_CLRBUFFER
0x06
#define MODDRVPHY_SENSECHANNEL
0x07
#define MODDRVPHY_GENSIGNAL
0x08
#define MODDRVPHY_TSTRECEIVE
0x09
#define MODDRVPHY_STATUS
0x0a
#define MODDRVPHY_GETPAYLOADSIZE
0x0b

#endif

354

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.3.3.2. Archivo modplcphy.h


/*
modplcphy.h:
Declaracin de funciones referentes a la interfaz de la capa fsica del
modem PLC.
*/

#if !defined(__MODPLCPHY_H__)
#define __MODPLCPHY_H__

/* Archivos includos necesarios. */


#include <windows.h>

/* Definicin de tipos. */
/* Manejador de interfaz con la capa fsica del modem PLC. */
typedef struct
{
HANDLE hq;
/* Manejador de cola de
mensajes. */
HANDLE hm;
/* Semforo de exclusin mtua. */
struct
{
DWORD threadid;
/* Identificador de hilo de
deteccin. */
HANDLE detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
void (*recfun)(void *, void *);
/* Funcin manejadora de tramas
capturadas. */
void *param;
/* Parmetros para la funcin
manejadora de tramas
recibidas. */
} iface[256];
/* Tabla de interfaces fsicas. */
} modplcphy_hd;

/* Definicin de constantes. */
/* Tipos de seales. */
#define MODPLCPHY_NOISESIGNAL
#define MODPLCPHY_TESTSIGNAL1
#define MODPLCPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Declaracin de funciones pblicas. */


#if !defined(__MODPLCPHY_DLL__)
/*
Funcin modplcphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
static modplcphy_hd * (*modplcphy_init)(int);
/*
Funcin modplcphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
static int (*modplcphy_release)(modplcphy_hd *);
/*
Funcin modplcphy_sndframe:
Enva una trama.
*/
static size_t (*modplcphy_sndframe)(modplcphy_hd *, unsigned char,
const void *, size_t);

FernandoArielBeunza79156

355

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcphy_capframe:
Captura una trama.
*/
static int (*modplcphy_capframe)(modplcphy_hd *, unsigned char, size_t);
/*
Funcin modplcphy_getframe:
Obtiene una trama capturada previamente.
*/
static size_t (*modplcphy_getframe)(modplcphy_hd *, unsigned char, void *,
size_t);
/*
Funcin modplcphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
static int (*modplcphy_notify)(modplcphy_hd *, unsigned char,
void (*func)(modplcphy_hd *, void *), void *);
/*
Funcin modplcphy_poll:
Verifica la captura de una trama.
*/
static int (*modplcphy_poll)(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_rsdframe:
Reenva una trama.
*/
static int (*modplcphy_rsdframe)(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
static int (*modplcphy_clrbuffer)(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
static int (*modplcphy_sensechannel)(modplcphy_hd *, unsigned char,
unsigned char, long int);
/*
Funcin modplcphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
static int (*modplcphy_gensignal)(modplcphy_hd *, unsigned char, int);
/*
Funcin modplcphy_tstreceive:
Realiza una prueba de recepcin.
*/
static int (*modplcphy_tstreceive)(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_status:
Devuelve el estado del modem PLC.
*/
static int (*modplcphy_status)(modplcphy_hd *);
/*
Funcin modplcphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
static size_t (*modplcphy_getpayloadsize)(modplcphy_hd *, unsigned char);

356

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Implementacin de funciones pblicas. */
/*
Funcin modplcphy_loadlib:
Carga la bliblioteca dinmica referente a la capa fsica del modem PLC.
*/
static int modplcphy_loadlib(void)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca
dinmica. */

/* Carga la biblioteca. */
hlib = NULL;
modplcphy_init = NULL;
modplcphy_release = NULL;
modplcphy_sndframe = NULL;
modplcphy_capframe = NULL;
modplcphy_getframe = NULL;
modplcphy_notify = NULL;
modplcphy_poll = NULL;
modplcphy_rsdframe = NULL;
modplcphy_clrbuffer = NULL;
modplcphy_sensechannel = NULL;
modplcphy_gensignal = NULL;
modplcphy_tstreceive = NULL;
modplcphy_status = NULL;
modplcphy_getpayloadsize = NULL;
hlib = LoadLibrary("MODPLCPHY");
if (!hlib) return 0;
modplcphy_init = (modplcphy_hd * (*)(int))
GetProcAddress(hlib, "modplcphy_init");
modplcphy_release = (int (*)(modplcphy_hd *))
GetProcAddress(hlib, "modplcphy_release");
modplcphy_sndframe = (size_t (*)(modplcphy_hd *, unsigned char,
const void *, size_t))
GetProcAddress(hlib, "modplcphy_sndframe");
modplcphy_capframe = (int (*)(modplcphy_hd *, unsigned char, size_t))
GetProcAddress(hlib, "modplcphy_capframe");
modplcphy_getframe = (size_t (*)(modplcphy_hd *, unsigned char, void *,
size_t))
GetProcAddress(hlib, "modplcphy_getframe");
modplcphy_notify = (int (*)(modplcphy_hd *, unsigned char,
void (*func)(modplcphy_hd *, void *), void *))
GetProcAddress(hlib, "modplcphy_notify");
modplcphy_poll = (int (*)(modplcphy_hd *, unsigned char))
GetProcAddress(hlib, "modplcphy_poll");
modplcphy_rsdframe = (int (*)(modplcphy_hd *, unsigned char))
GetProcAddress(hlib, "modplcphy_rsdframe");
modplcphy_clrbuffer = (int (*)(modplcphy_hd *, unsigned char))
GetProcAddress(hlib, "modplcphy_clrbuffer");
modplcphy_sensechannel = (int (*)(modplcphy_hd *, unsigned char,
unsigned char, long int))
GetProcAddress(hlib, "modplcphy_sensechannel");
modplcphy_gensignal = (int (*)(modplcphy_hd *, unsigned char, int))
GetProcAddress(hlib, "modplcphy_gensignal");
modplcphy_tstreceive = (int (*)(modplcphy_hd *, unsigned char))
GetProcAddress(hlib, "modplcphy_tstreceive");
modplcphy_status = (int (*)(modplcphy_hd *))
GetProcAddress(hlib, "modplcphy_status");
modplcphy_getpayloadsize = (size_t (*)(modplcphy_hd *, unsigned char))
GetProcAddress(hlib,
"modplcphy_getpayloadsize");
/* Verifica que todas las funciones de la biblioteca se hayan cargado. */
if ((!modplcphy_init) || (!modplcphy_release) || (!modplcphy_sndframe) ||
(!modplcphy_capframe) || (!modplcphy_getframe) ||
(!modplcphy_notify) || (!modplcphy_poll) || (!modplcphy_rsdframe) ||
(!modplcphy_clrbuffer) || (!modplcphy_sensechannel) ||
(!modplcphy_gensignal) || (!modplcphy_tstreceive) ||

FernandoArielBeunza79156

357

Tesis de Grado en Ingeniera Informtica


(!modplcphy_status) || (!modplcphy_getpayloadsize))
return 0;
/* xito. */
return 1;
}
#endif

#endif

C.3.3.3. Archivo modplcphy.c


/*
modplcphy.c:
Implementacin de funciones referentes a la interfaz de la capa fsica del
modem PLC.
*/

/* Archivos includos necesarios. */


#define __MODPLCPHY_DLL__
#include "config.h"
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "modplcphy.h"

/* Declaracin de funciones pblicas. */


modplcphy_hd *__modplcphy_init__(int);
int modplcphy_release(modplcphy_hd *);
size_t modplcphy_sndframe(modplcphy_hd *, unsigned char, const void *, size_t);
int modplcphy_capframe(modplcphy_hd *, unsigned char, size_t);
size_t modplcphy_getframe(modplcphy_hd *, unsigned char, void *, size_t);
int modplcphy_notify(modplcphy_hd *, unsigned char,
void (*func)(modplcphy_hd *, void *), void *);
int modplcphy_poll(modplcphy_hd *, unsigned char);
int modplcphy_rsdframe(modplcphy_hd *, unsigned char);
int modplcphy_clrbuffer(modplcphy_hd *, unsigned char);
int modplcphy_sensechannel(modplcphy_hd *, unsigned char, unsigned char,
long int);
int modplcphy_gensignal(modplcphy_hd *, unsigned char, int);
int modplcphy_tstreceive(modplcphy_hd *, unsigned char);
int modplcphy_status(modplcphy_hd *);
size_t modplcphy_getpayloadsize(modplcphy_hd *, unsigned char);

/* Declaracin de funciones privadas. */


static DWORD WINAPI __modplcphy_detectproc__(LPVOID);
static int __modplcphy_sendrecv__(modplcphy_hd *, void *, size_t, const void *,
size_t);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
modplcphy_hd *modplcphy_init(int sid)
{
/* Variables. */
int layer;
int result;
short int iface;

358

/* Capa a la que se quiere


accerder. */
/* Resultado de la solicitud. */
/* Identificadores de interfaces

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


modplcphy_hd *handle;
char qname[256];

fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Nombre de la cola de
mensajes. */

/* Crea un nuevo manejador de interfaz con la capa fsica del modem PLC. */
handle = (modplcphy_hd *) malloc(sizeof(modplcphy_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa fsica del modem PLC. */
while(1)
{
/* Abre una conexin con la cola de mensajes del driver del modem
PLC. */
sprintf(qname, "\\\\.\\pipe\\modemplc%i", sid);
handle->hq = CreateFile(qname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle->hq == INVALID_HANDLE_VALUE) break;
/* Inicializa el manejador de tramas capturadas de cada una de las
interfaces fsicas. */
for(iface = 0; iface < 256; iface ++)
{
handle->iface[iface].recfun = NULL;
handle->iface[iface].param = NULL;
}
/* Inicializa semforo de exclusin mtua. */
handle->hm = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->hm == INVALID_HANDLE_VALUE) break;
/* Solicita acceder a la capa fsica del modem PLC. */
layer = 1;
if (!__modplcphy_sendrecv__(handle, &result, sizeof(result), &layer,
sizeof(layer)))
break;
if (!result) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa fsica del modem PLC. */
CloseHandle(handle->hm);
CloseHandle(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modplcphy_release(modplcphy_hd *hd)
{
/* Variables. */
int op;
int result;
short int iface;

/* Operacin. */
/* Resultado de la operacin. */
/* Identificadores de interfaces
fsicas. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Libera el manejador de captura de tramas. */
for(iface = 0; iface < 256; iface ++)
modplcphy_notify(hd, (unsigned char) (iface & 0x00ff), NULL, NULL);

FernandoArielBeunza79156

359

Tesis de Grado en Ingeniera Informtica


/* Solicita la finalizacin del acceso a la capa fsica del modem PLC. */
op = MODDRVPHY_RELEASE;
if (!__modplcphy_sendrecv__(hd, &result, sizeof(result), &op, sizeof(op)))
return 0;
if (!result) return 0;
/* Libera los recursos utilizados por la interfaz con la capa fsica del
modem PLC. */
CloseHandle(hd->hm);
CloseHandle(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcphy_sndframe:
Enva una trama.
*/
size_t modplcphy_sndframe(modplcphy_hd *hd, unsigned char iface,
const void *frame, size_t framesize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Enva una trama. */
while(1)
{
/* Solicita el envo de una trama. */
op = MODDRVPHY_SNDFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface, sizeof(iface))) break;
/* Enva el tamao de la trama. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &framesize,
sizeof(framesize)))
break;
/* Enva la trama. */
if (!__modplcphy_sendrecv__(hd, &framesize, sizeof(framesize), frame,
framesize))
break;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad de bytes enviados. */
return framesize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* No se pudo realizar el envo. */
return 0;
}
/*

360

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin modplcphy_capframe:
Captura una trama.
*/
int modplcphy_capframe(modplcphy_hd *hd, unsigned char iface, size_t framesize)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Solicita la captura una trama. */
result = 0;
while(1)
{
/* Solicita la captura de una trama. */
op = MODDRVPHY_CAPFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface, sizeof(iface))) break;
/* Enva el tamao de la trama. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &framesize,
sizeof(framesize));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modplcphy_getframe(modplcphy_hd *hd, unsigned char iface, void *frame,
size_t framesize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene una trama capturada previamente. */
while(1)
{
/* Solicita la leer una trama. */
op = MODDRVPHY_GETFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface, sizeof(iface))) break;
/* Enva el tamao de la trama y obtiene la trama. */
if (!__modplcphy_sendrecv__(hd, frame, framesize, &framesize,

FernandoArielBeunza79156

361

Tesis de Grado en Ingeniera Informtica


sizeof(framesize)))
break;
/* Obtiene el tamao de la trama leda. */
if (!__modplcphy_sendrecv__(hd, &framesize, sizeof(framesize), NULL,
0))
break;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad de bytes ledos. */
return framesize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* No se pudo obtener la trama capturada. */
return 0;
}
/*
Funcin modplcphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
int modplcphy_notify(modplcphy_hd *hd, unsigned char iface,
void (*func)(modplcphy_hd *, void *), void *param)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->iface[iface].recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->iface[iface].recfun))
{
WaitForSingleObject(hd->hm, INFINITE);
hd->iface[iface].recfun = func;
hd->iface[iface].param = param;
ReleaseSemaphore(hd->hm, 1, NULL);
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora definida
previamente se elimina esta ltima. */
if ((!func) && (hd->iface[iface].recfun))
{
WaitForSingleObject(hd->hm, INFINITE);
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = param;
ReleaseSemaphore(hd->hm, 1, NULL);
WaitForSingleObject(hd->iface[iface].detectthread, INFINITE);
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->iface[iface].recfun))
{
WaitForSingleObject(hd->hm, INFINITE);
hd->iface[iface].recfun = func;
hd->iface[iface].param = param;
hd->iface[iface].detectthread =
CreateThread(NULL, 0, __modplcphy_detectproc__, hd, 0,
&(hd->iface[iface].threadid));

362

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (hd->iface[iface].detectthread == INVALID_HANDLE_VALUE)
{
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = NULL;
ReleaseSemaphore(hd->hm, 1, NULL);
return 0;
}
ReleaseSemaphore(hd->hm, 1, NULL);
return 1;
}
/* No se pudo definir la funcin manejadora de tramas capturadas. */
return 0;
}
/*
Funcin modplcphy_poll:
Verifica la captura de una trama.
*/
int modplcphy_poll(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Verifica la captura de una trama. */
result = 0;
while(1)
{
/* Solicita verificar la captura de una trama. */
op = MODDRVPHY_POLL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcphy_rsdframe:
Reenva una trama.
*/
int modplcphy_rsdframe(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);

FernandoArielBeunza79156

363

Tesis de Grado en Ingeniera Informtica


/* Reenva una trama. */
result = 0;
while(1)
{
/* Solicita reenviar una trama. */
op = MODDRVPHY_RSDFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado del reenvo de la trama. */
return result;
}
/*
Funcin modplcphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modplcphy_clrbuffer(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Limpia el buffer de captura de tramas. */
result = 0;
while(1)
{
/* Solicita limpiar el buffer de captura de tramas. */
op = MODDRVPHY_CLRBUFFER;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la limpieza del buffer. */
return result;
}
/*
Funcin modplcphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int modplcphy_sensechannel(modplcphy_hd *hd, unsigned char iface,
unsigned char level, long int waittime)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

364

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Solicita el sensado del canal de comunicacin. */
result = 0;
while(1)
{
/* Solicita el sensado del estado del canal de comunicacin. */
op = MODDRVPHY_SENSECHANNEL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface, sizeof(iface))) break;
/* Enva el nivel de seal. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &level, sizeof(level))) break;
/* Enva el tiempo de espera. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &waittime,
sizeof(waittime));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado del sensado del estado del canal de
comunicacin. */
return result;
}
/*
Funcin modplcphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplcphy_gensignal(modplcphy_hd *hd, unsigned char iface, int sig)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Solicita la generacin de la seal especificada. */
result = 0;
while(1)
{
/* Solicita la generacin de una seal. */
op = MODDRVPHY_GENSIGNAL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface, sizeof(iface))) break;
/* Enva el tipo de seal. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &sig, sizeof(sig));
break;
}

FernandoArielBeunza79156

365

Tesis de Grado en Ingeniera Informtica


/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modplcphy_tstreceive(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Realiza una prueba de recepcin. */
result = 0;
while(1)
{
/* Solicita realizar una prueba de recepcin. */
op = MODDRVPHY_TSTRECEIVE;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve el resultado de la prueba de recepcin. */
return result;
}
/*
Funcin modplcphy_status:
Devuelve el estado del modem PLC.
*/
int modplcphy_status(modplcphy_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Obtiene el estado del modem PLC. */
op = MODDRVPHY_STATUS;
if (!__modplcphy_sendrecv__(hd, &result, sizeof(result), &op, sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);

366

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Devuelve el estado del modem PLC. */
return result;
}
/*
Funcin modplcphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplcphy_getpayloadsize(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Operacin. */
size_t payloadsize;
/* Cantidad de bytes que puede
contener una trama. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem PLC. */
WaitForSingleObject(hd->hm, INFINITE);
payloadsize = 0;
while(1)
{
/* Obtiene la cantidad mxima de bytes que puede contener una trama. */
op = MODDRVPHY_GETPAYLOADSIZE;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &payloadsize, sizeof(payloadsize), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Devuelve la cantidad mxima de bytes que puede contener una trama. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcphy_detectproc__:
Verifica la existencia de una trama capturada disponible para ser leda.
*/
static DWORD WINAPI __modplcphy_detectproc__(LPVOID param)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int captureflag;
/* Indicador de captura de una
trama. */
short int i;
/* Contador. */
unsigned char iface;
/* Identificadores de interfaces
fsicas. */
modplcphy_hd *hd;
/* Manejador de interfaz con la
capa fsica del modem PLC. */
void (*func)(void *, void *);
/* Manejador de captura de
tramas. */

/* Carga el manejador de interfaz con la capa fsica del modem PLC. */


hd = (modplcphy_hd *) param;
/* Obtiene el identificador de interface fsica asociado al hilo de

FernandoArielBeunza79156

367

Tesis de Grado en Ingeniera Informtica


deteccin de recepcin. */
iface = 0;
WaitForSingleObject(hd->hm, INFINITE);
for(i = 0; i < 256; i++)
{
if (hd->iface[i].threadid != GetCurrentThreadId()) continue;
iface = (unsigned char) (i & 0x00ff);
break;
}
ReleaseSemaphore(hd->hm, 1, NULL);
if (i > 255) return 0;
/* Verifica la existencia de una trama capturada. */
while(1)
{
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
WaitForSingleObject(hd->hm, INFINITE);
/* Verifica la captura de una trama. */
func = hd->iface[iface].recfun;
if (!func) break;
captureflag = 0;
while(1)
{
/* Solicita verificar la captura de una trama. */
op = MODDRVPHY_POLL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op))) break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &captureflag, sizeof(captureflag),
&iface, sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
ReleaseSemaphore(hd->hm, 1, NULL);
/* Verifica si se ha detectado la captura de una trama para invocar al
manejador de trama capturadas. */
if (captureflag) func(hd, hd->iface[iface].param);
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
ReleaseSemaphore(hd->hm, 1, NULL);
return 0;
}
/*
Funcin __modplcphy_sendrecv__:
Intercambia datos con el driver del modem PLC.
*/
static int __modplcphy_sendrecv__(modplcphy_hd *hd, void *outdata,
size_t outsize, const void *indata,
size_t insize)
{
/* Variables. */
size_t last;
/* Cantidad de bytes enviados o
recibidos. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Enva la operacin. */
sent = 0;
while((indata) && (sent < insize))

368

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
if (!WriteFile(hd->hq, indata, insize, &last, NULL)) return 0;
sent += last;
}
/* Recibe la respuesta. */
received = 0;
while((outdata) && (received < outsize))
{
if (!ReadFile(hd->hq, outdata, outsize, &last, NULL)) return 0;
received += last;
}
/* xito. */
return 1;
}

C.3.4. Driver del Modem PLC modem_driver.exe


En esta seccin se detalla el cdigo fuente del driver del modem PLC, que se compone de los
siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin del driver del
del modem PLC que no pueden ser modificados en tiempo de ejecucin.

Archivo serial.h: en este archivo se declaran primitivas con funcionalidades referentes a


la comunicacin por puerto serie.

Archivo serial.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo serial.h.

Archivo modplc.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa fsica, de enlace y de sesin. Dichas primitivas brindan un conjunto de
funcionalidades que permiten la comunicacin con las capas mencionadas implementadas
en el modem PLC.

Archivo modplc.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo modplc.h.

Archivo modsp.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa de sesin. Dichas primitivas brindan un conjunto de funcionalidades que
permiten la comunicacin con las capa de sesin implementada en el modem PLC.

Archivo modsp.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo modsp.h.

Archivo moddl.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa de enlace. Dichas primitivas brindan un conjunto de funcionalidades que
permiten la comunicacin con las capa de enlace implementada en el modem PLC.

Archivo moddl.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo moddl.h.

FernandoArielBeunza79156

369

Tesis de Grado en Ingeniera Informtica

Archivo modphy.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa fsica. Dichas primitivas brindan un conjunto de funcionalidades que permiten
la comunicacin con las capa fsica implementada en el modem PLC.

Archivo modphy.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo modphy.h.

Archivo moddrv.h: en este archivo se declaran las primitivas correspondientes al driver


del modem PLC. Dichas primitivas brindan un conjunto de funcionalidades que permite a
las interfaces mencionadas anteriormente comunicarse con el modem PLC.

Archivo moddrv.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo moddrv.h.

Archivo modem_driver.c: en este archivo se encuentra implementada la inicializacin de


la ejecucin del driver del modem PLC.

C.3.4.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz del modem PLC. */


/* Tipos de prompt utilizados. */
#define MODPLC_INITPROMPT
#define MODPLC_LAYPROMPT
#define MODPLC_NORMPROMPT
#define MODPLC_PARAMPROMPT

'#'
'?'
'$'
'>'

/* Tipos de reset. */
#define MODPLC_NORMRESET
#define MODPLC_PARAMRESET

'0'
'$'

/* Cdigo de operaciones de la capa fsica. */


#define MODPLCPHY_RESET
#define MODPLCPHY_SNDFRAME
#define MODPLCPHY_CAPFRAME
#define MODPLCPHY_GETFRAME
#define MODPLCPHY_POLL
#define MODPLCPHY_RSDFRAME
#define MODPLCPHY_CLRBUFFER
#define MODPLCPHY_SENSECHANNEL
#define MODPLCPHY_GENSIGNAL
#define MODPLCPHY_TSTRECEIVE
#define MODPLCPHY_GETPAYLOADSIZE

MODPLC_NORMRESET
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
'a'

/* Tipos de seal. */
#define MODPLCPHY_NOISESIGNAL
#define MODPLCPHY_TESTSIGNAL1
#define MODPLCPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Cdigo de operaciones de la capa de enlace. */


#define MODPLCDL_RESET

MODPLC_NORMRESET

370

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#define
#define
#define
#define
#define
#define
#define
#define
#define
#define

MODPLCDL_OPEN
MODPLCDL_CLOSE
MODPLCDL_SEND
MODPLCDL_RECEIVE
MODPLCDL_POLL
MODPLCDL_GETADDRESS
MODPLCDL_ADDLOGADDRESS
MODPLCDL_DELLOGADDRESS
MODPLCDL_GETPHYADDRESS
MODPLCDL_GETPAYLOADSIZE

/* Cdigo de operaciones de la capa de sesin. */


#define MODPLCSP_RESET
#define MODPLCSP_PUBLISH
#define MODPLCSP_SUBSCRIBE
#define MODPLCSP_LEAVE
#define MODPLCSP_SEND
#define MODPLCSP_RECEIVE
#define MODPLCSP_POLL
#define MODPLCSP_GETPAYLOADSIZE

'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
'a'

MODPLC_NORMRESET
'1'
'2'
'3'
'4'
'5'
'6'
'7'

/* Driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa fsica. */
#define MODDRVPHY_RELEASE
0x00
#define MODDRVPHY_SNDFRAME
0x01
#define MODDRVPHY_CAPFRAME
0x02
#define MODDRVPHY_GETFRAME
0x03
#define MODDRVPHY_POLL
0x04
#define MODDRVPHY_RSDFRAME
0x05
#define MODDRVPHY_CLRBUFFER
0x06
#define MODDRVPHY_SENSECHANNEL
0x07
#define MODDRVPHY_GENSIGNAL
0x08
#define MODDRVPHY_TSTRECEIVE
0x09
#define MODDRVPHY_STATUS
0x0a
#define MODDRVPHY_GETPAYLOADSIZE
0x0b
/* Cdigos de operaciones de la interfaz de la capa de enlace. */
#define MODDRVDL_CLOSE
0x00
#define MODDRVDL_OPEN
0x01
#define MODDRVDL_SEND
0x02
#define MODDRVDL_RECEIVE
0x03
#define MODDRVDL_POLL
0x04
#define MODDRVDL_GETADDRESS
0x05
#define MODDRVDL_ADDLOGADDRESS
0x06
#define MODDRVDL_DELLOGADDRESS
0x07
#define MODDRVDL_GETPHYADDRESS
0x08
#define MODDRVDL_STATUS
0x09
#define MODDRVDL_GETPAYLOADSIZE
0x0a
/* Cdigos de operaciones de la interfaz de la capa de sesin. */
#define MODDRVSP_RELEASE
0x00
#define MODDRVSP_PUBLISH
0x01
#define MODDRVSP_SUBSCRIBE
0x02
#define MODDRVSP_LEAVE
0x03
#define MODDRVSP_SEND
0x04
#define MODDRVSP_RECEIVE
0x05
#define MODDRVSP_POLL
0x06
#define MODDRVSP_STATUS
0x07
#define MODDRVSP_GETPAYLOADSIZE
0x08

/* Interfaz con el modem PLC. */


/* Tamao del buffer. */
#define MODPLC_BUFFERSIZE

4096

/* Cantidad de bytes de una lnea por envo. */


#define MODPLC_FRAGMENTLINESIZE

FernandoArielBeunza79156

371

Tesis de Grado en Ingeniera Informtica


#endif

C.3.4.2. Archivo serial.h


/*
serial.h:
Declaracin de funciones referentes a la interfaz de comunicacin por
puerto serie.
*/

#if !defined(__SERIAL_H__)
#define __SERIAL_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <windows.h>

/* Definicin de tipos. */
/* Manejador de interfaz de comunicacin por puerto serie. */
typedef struct
{
HANDLE serialhd;
/* Manejador de interfaz de puerto
serie. */
HANDLE stopsem;
/* Semforo de finalizacin de
recepcin. */
HANDLE readersem;
/* Semforo lector del buffer de
recepcin. */
HANDLE writersem;
/* Semforo escritor del buffer de
recepcin. */
HANDLE recvthread;
/* Manejador de hilo receptor. */
int stopflag;
/* Indicador de fin de
recepcin. */
size_t size;
/* Tanao del buffer de
recepcin. */
size_t received;
/* Cantidad de bytes recibidos sin
leer. */
char *buffer;
/* Puntero al buffer de
recepcin. */
} serial_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin serial_init:
Inicializa la interfaz de comunicacin por puerto serie.
*/
serial_hd *serial_init(int, size_t);
/*
Funcin serial_release:
Libera los recursos utilizdos por la interfaz de comunicacin por puerto
serie.
*/
int serial_release(serial_hd *);
/*
Funcin serial_send:
Enva un mensaje a travs de la interfaz de comunicacin por puerto serie.
*/
size_t serial_send(serial_hd *, const void *, size_t);
/*

372

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin serial_receive:
Recibe un mensaje a por medio de la interfaz de comunicacin por puerto
serie.
*/
size_t serial_receive(serial_hd *, void *, size_t);
/*
Funcin serial_poll:
Devuelve si hay un mensaje a la espera de ser recibido.
*/
int serial_poll(serial_hd *);

#endif

C.3.4.3. Archivo serial.c


/*
serial.c:
Implementacin de funciones referentes a la interfaz de comunicacin por
puerto serie.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "serial.h"

/* Declaracin de funciones privadas. */


static DWORD WINAPI __serial_recvproc__(LPVOID);

/* Implementacin de funciones pblicas. */


/*
Funcin serial_init:
Inicializa la interfaz de comunicacin por puerto serie.
*/
serial_hd *serial_init(int id, size_t buffsize)
{
/* Variables. */
DWORD tid;
DCB icfg;

COMMTIMEOUTS cto;
serial_hd *handle;
char iname[256];

/* Identificador de hilo. */
/* Configuracin de la interfaz de
comunicacin por puerto
serie. */
/* Configuracin de los tiempos de
espera. */
/* Manejador de la interfaz. */
/* Nombre de la interfaz. */

/* Verifica la validez del identificador de la interfaz de comunicacin por


puerto serie. */
if (id < 1) return 0;
/* Crea un nuevo manejador de interfaz de comunicacin por puerto serie. */
handle = (serial_hd *) malloc(sizeof(serial_hd));
if (!handle) return NULL;
/* Inicializa el buffer de recepcin. */
handle->buffer = (char *) malloc(buffsize);
if (!handle->buffer)
{
free(handle);

FernandoArielBeunza79156

373

Tesis de Grado en Ingeniera Informtica


return NULL;
}
handle->received = 0;
handle->size = buffsize;
/* Inicializa la interfaz de comunicacin por puerto serie. */
while(1)
{
/* Abre la interfaz de comunicacin por puerto serie. */
if (id < 9)
sprintf(iname, "COM%i", id);
else
sprintf(iname, "\\\\.\\COM%i", id);
handle->serialhd = CreateFile(iname, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (handle->serialhd == INVALID_HANDLE_VALUE) break;
/* Configura la interfaz de comunicacin por puerto serie. */
icfg.DCBlength = sizeof(DCB);
if (!GetCommState(handle->serialhd, &icfg)) break;
icfg.BaudRate = CBR_57600;
icfg.ByteSize = 8;
icfg.Parity = NOPARITY;
icfg.fParity = FALSE;
icfg.StopBits = ONESTOPBIT;
if (!SetCommState(handle->serialhd, &icfg)) break;
/* Configura los tiempos de espera de la interfaz de comunicacin por
puerto serie. */
if (!GetCommTimeouts(handle->serialhd, &cto)) break;
cto.ReadIntervalTimeout = 5;
cto.WriteTotalTimeoutConstant = 5000;
if (!SetCommTimeouts(handle->serialhd, &cto)) break;
/* Limpia los buffers de la interfaz de comunicacin por puerto
serie. */
if (!PurgeComm(handle->serialhd, PURGE_TXABORT | PURGE_TXCLEAR |
PURGE_RXABORT | PURGE_RXCLEAR))
break;
/* Inicializa semforos. */
handle->stopflag = 0;
handle->stopsem = CreateSemaphore(NULL, 0, 1, NULL);
if (handle->stopsem == INVALID_HANDLE_VALUE) break;
handle->readersem = CreateSemaphore(NULL, 0, 1, NULL);
if (handle->readersem == INVALID_HANDLE_VALUE) break;
handle->writersem = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->writersem == INVALID_HANDLE_VALUE) break;
/* Inicializa el hilo de recepcin. */
handle->recvthread = CreateThread(NULL, 0, __serial_recvproc__, handle,
0, &tid);
if (handle->recvthread == INVALID_HANDLE_VALUE) break;
/* Devuelve el manejador de la interfaz de comunicacin por puerto
serie. */
return handle;
}
/* No se pudo inicializar la interfaz de comunicacin por puerto serie. */
CloseHandle(handle->writersem);
CloseHandle(handle->readersem);
CloseHandle(handle->stopsem);
CloseHandle(handle->serialhd);
free(handle->buffer);
free(handle);
return NULL;
}

374

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin serial_release:
Libera los recursos utilizdos por la interfaz de comunicacin por puerto
serie.
*/
int serial_release(serial_hd *hd)
{
/* Verifica la validez del manejador de la interfaz de comunicacin por
puerto serie. */
if (!hd) return 0;
/* Detiene la ejecucin del hilo de recepcin. */
ReleaseSemaphore(hd->writersem, 1, NULL);
ReleaseSemaphore(hd->stopsem, 1, NULL);
WaitForSingleObject(hd->recvthread, INFINITE);
/* Libera los recursos utilizados por la interfaz de comunicacin por
puerto serie. */
CloseHandle(hd->writersem);
CloseHandle(hd->readersem);
CloseHandle(hd->stopsem);
CloseHandle(hd->serialhd);
free(hd->buffer);
free(hd);
/* xito. */
return 1;
}
/*
Funcin serial_send:
Enva un mensaje a travs de la interfaz de comunicacin por puerto serie.
*/
size_t serial_send(serial_hd *hd, const void *msg, size_t msgsize)
{
/* Variables. */
int result;
/* Resultado de la espera. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t lastsend;
/* Cantidad de bytes envados en el
ltimo envo. */
OVERLAPPED ovl;
/* Manejador de comunicacin
asincrnica. */
unsigned char *ptr;
/* Puntero al mensaje. */

/* Verifica la validez del manejador de la interfaz de comunicacin por


puerto serie. */
if (!hd) return 0;
/* Enva los bytes especificados por medio de la interfaz de comunicacin
por puerto serie. */
sent = 0;
ptr = (unsigned char *) msg;
memset(&ovl, 0, sizeof(ovl));
while(msgsize && (!hd->stopflag))
{
/* Enva los bytes especificados. */
do
{
lastsend = 0;
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ovl.hEvent) break;
if (!WriteFile(hd->serialhd, ptr, msgsize, &lastsend, &ovl))
{
if (GetLastError() != ERROR_IO_PENDING)
break;
else
{
result = WaitForSingleObject(ovl.hEvent, INFINITE);
if (result == WAIT_OBJECT_0)

FernandoArielBeunza79156

375

Tesis de Grado en Ingeniera Informtica


{
if (!GetOverlappedResult(hd->serialhd, &ovl, &lastsend,
FALSE))
break;
}
else
break;
}
}
CloseHandle(ovl.hEvent);
} while(!lastsend);
/* Actualiza contadores y puntero a los bytes a bytes a enviar en base
a la cantidad de bytes enviados anteriormente. */
msgsize -= lastsend;
sent += lastsend;
ptr += lastsend;
}
/* Devuelve la cantidad de bytes enviados. */
return sent;
}
/*
Funcin serial_receive:
Recibe un mensaje por medio de la interfaz de comunicacin por puerto
serie.
*/
size_t serial_receive(serial_hd *hd, void *msg, size_t msgsize)
{
/* Variables. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Verifica la validez del manejador de la interfaz de comunicacin por


puerto serie. */
if (!hd) return 0;
/* Espera a que el buffer de recepcin tenga algn contenido. */
if (WaitForSingleObject(hd->readersem, INFINITE) != WAIT_OBJECT_0)
return 0;
/* Lee la cantidad especificada de bytes del buffer de recepcin. */
received = msgsize;
if (received > hd->received) received = hd->received;
memcpy(msg, hd->buffer, received);
/* Actualiza el buffer de recepcin. */
if (hd->received - received)
memcpy(hd->buffer, hd->buffer + received, hd->received - received);
hd->received -= received;
/* Si el buffer no se encuentra lleno habilita al hilo receptor. */
if (hd->received < hd->size) ReleaseSemaphore(hd->writersem, 1, NULL);
/* Devuelve la cantidad de bytes recibidos. */
return received;
}
/*
Funcin serial_poll:
Verifica la llegada de un nuevo mensaje.
*/
int serial_poll(serial_hd *hd)
{
/* Verifica la validez del manejador de la interfaz de comunicacin por
puerto serie. */
if (!hd) return 0;
/* Verifica si el buffer no se encuentra vaco. */
return (hd->received != 0);

376

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}

/* Implementacin de funciones privadas. */


/*
Funcin __serial_recvproc__:
Recibe datos por la interfaz de comunicacin por puerto serie y lo almacena
en el buffer de recepcin.
*/
static DWORD WINAPI __serial_recvproc__(LPVOID param)
{
/* Variables. */
int result;
size_t received;
OVERLAPPED ovl;
HANDLE waiters[2];
serial_hd *hd;

/* Resultado de la espera. */
/* Cantidad de bytes recibidos. */
/* Manejador de comunicacin
asincrnica. */
/* Manejadores en espera. */
/* Manejador de la interfaz por
puerto serie. */

/* Carga el manejador de comunicacin por puerto serie. */


hd = (serial_hd *) param;
/* Inicializa la comunicacin asincrnica. */
memset(&ovl, 0, sizeof(ovl));
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ovl.hEvent == INVALID_HANDLE_VALUE)
{
hd->stopflag = 1;
ExitThread(0);
return 0;
}
waiters[0] = hd->stopsem;
waiters[1] = ovl.hEvent;
/* Lee la interfaz de comunicacin por puerto serie. */
while(1)
{
/* Verifica si hay una peticin de finalizacin de ejecucin del hilo
receptor. */
if (WaitForSingleObject(hd->stopsem, 0) == WAIT_OBJECT_0) break;
/* Espera a que el buffer de recepcin deje de ser ledo. */
if (WaitForSingleObject(hd->writersem, INFINITE) != WAIT_OBJECT_0)
break;
/* Carga en el buffer los bytes recibidos. */
if (!ReadFile(hd->serialhd, hd->buffer + hd->received,
hd->size - hd->received, &received, &ovl))
{
if (GetLastError() != ERROR_IO_PENDING)
break;
else
{
result = WaitForMultipleObjects(2, waiters, FALSE, INFINITE);
if (result == WAIT_OBJECT_0)
{
CancelIo(hd->serialhd);
break;
}
else if (result == WAIT_OBJECT_0 + 1)
{
if (!GetOverlappedResult(hd->serialhd, &ovl, &hd->received,
FALSE))
break;
}
else
break;
}

FernandoArielBeunza79156

377

Tesis de Grado en Ingeniera Informtica


}
hd->received += received;
/* Habilita la lectura del buffer de recepcin. */
ReleaseSemaphore(hd->readersem, 1, NULL);
}
CloseHandle(ovl.hEvent);
/* Termina la ejecucin del hilo de recepcin. */
hd->stopflag = 1;
ExitThread(0);
return 0;
}

C.3.4.4. Archivo modplc.h


/*
modplc.h:
Declaracin de funciones referentes a la interfaz con el modem PLC.
*/

#if !defined(__MODPLC_H__)
#define __MODPLC_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Definicin de tipos. */
/* Direccin fsica del modem PLC. */
typedef unsigned char modplc_dlphyaddr[8];
/* Direccin lgica del modem PLC. */
typedef unsigned long int modplc_dllogaddr;
/* Identificador de grupo. */
typedef unsigned char modplc_spgrpid;
/* Manejador de interfaz con el modem PLC. */
typedef struct
{
serial_hd *serialhd;

int layer;
int status;
int debugmode;
} modplc_hd;

/* Manejador de interfaz de
comunicacin por puerto
serie. */
/* Capa del modem PLC utilizada. */
/* Estado del modem PLC. */
/* Indicador de modo depuracin. */

/* Definicin de constantes. */
/* Capas de acceso. */
#define MODPLC_PHYSICALLAYER
#define MODPLC_DATALINKLAYER
#define MODPLC_SESSIONLAYER

0x01
0x02
0x03

/* Tipos de seales. */
#define MODPLC_PHYNOISESIGNAL
#define MODPLC_PHYTESTSIGNAL1
#define MODPLC_PHYTESTSIGNAL2

0x01
0x02
0x03

/* Declaracin de funciones pblicas. */

378

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplc_init:
Inicializa los recursos utilizados por la interfaz con el modem PLC.
*/
modplc_hd *modplc_init(int, int, int);
/*
Funcin modplc_release:
Libera los recursos utilizados por la interfaz con el modem PLC.
*/
int modplc_release(modplc_hd *);
/*
Funcin modplc_status:
Devuelve el estado del modem PLC.
*/
int modplc_status(modplc_hd *);
/*
Funcin modplc_physndframe:
Enva una trama por medio de la capa fsica del modem PLC.
*/
size_t modplc_physndframe(modplc_hd *, unsigned char, const void *, size_t);
/*
Funcin modplc_phycapframe:
Captura una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phycapframe(modplc_hd *, unsigned char, size_t);
/*
Funcin modplc_phygetframe:
Obtiene una trama capturada previamente por medio de la capa fsica del
modem PLC.
*/
size_t modplc_phygetframe(modplc_hd *, unsigned char, void *, size_t);
/*
Funcin phy_poll:
Verifica la captura de una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phypoll(modplc_hd *, unsigned char);
/*
Funcin modplc_phyrsdframe:
Reenva una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phyrsdframe(modplc_hd *, unsigned char);
/*
Funcin modplc_phyclrbuffer:
Limpia el buffer de captura de tramas de la capa fsica del modem PLC.
*/
int modplc_phyclrbuffer(modplc_hd *, unsigned char);
/*
Funcin modplc_physensechannel:
Sensa el estado del canal de comunicacin por medio de la capa fsica del
modem PLC.
*/
int modplc_physensechannel(modplc_hd *, unsigned char, unsigned char,
long int);
/*
Funcin modplc_phygensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplc_phygensignal(modplc_hd *, unsigned char, int);
/*

FernandoArielBeunza79156

379

Tesis de Grado en Ingeniera Informtica


Funcin modplc_phytstreceive:
Realiza una prueba de recepcin de la capa fsica del modem PLC.
*/
int modplc_phytstreceive(modplc_hd *, unsigned char);
/*
Funcin modplc_phygetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplc_phygetpayloadsize(modplc_hd *, unsigned char);
/*
Funcin modplc_dlopen:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlopen(modplc_hd *, unsigned char, unsigned char);
/*
Funcin modplc_dlclose:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlclose(modplc_hd *, int);
/*
Funcin modplc_dlsend:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlsend(modplc_hd *, int, modplc_dlphyaddr, unsigned char,
const void *, size_t);
/*
Funcin modplc_dlreceive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlreceive(modplc_hd *, int, modplc_dlphyaddr, void *, size_t);
/*
Funcin modplc_dlpoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de enlace del
modem PLC.
*/
int modplc_dlpoll(modplc_hd *, int);
/*
Funcin modplc_dlgetaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplc_dlgetaddress(modplc_hd *, unsigned char, modplc_dlphyaddr);
/*
Funcin modplc_dladdlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dladdlogaddress(modplc_hd *, unsigned char, unsigned char,
modplc_dllogaddr);
/*
Funcin modplc_dldellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dldellogaddress(modplc_hd *, unsigned char, unsigned char,
modplc_dllogaddr);
/*
Funcin modplc_dlgetphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa de
enlace del modem PLC.
*/
int modplc_dlgetphyaddress(modplc_hd *, unsigned char, unsigned char,
modplc_dllogaddr, modplc_dlphyaddr);

380

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplc_dlgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de enlace del modem PLC.
*/
size_t modplc_dlgetpayloadsize(modplc_hd *, unsigned char);
/*
Funcin modplc_sppublish:
Registra el dispositivo como publicador del grupo de difusin especificado
de la capa de sesin del modem PLC.
*/
int modplc_sppublish(modplc_hd *, modplc_spgrpid);
/*
Funcin modplc_spsubscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado
de la capa de sesin del modem PLC.
*/
int modplc_spsubscribe(modplc_hd *, modplc_spgrpid);
/*
Funcin modplc_spleave:
Desvincula el dispositivo del grupo de difusin especificado de la capa de
sesin del modem PLC.
*/
int modplc_spleave(modplc_hd *, modplc_spgrpid);
/*
Funcin modplc_spsend:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spsend(modplc_hd *, modplc_spgrpid, int, const void *, size_t);
/*
Funcin modplc_spreceive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spreceive(modplc_hd *, modplc_spgrpid *, void *, size_t);
/*
Funcin modplc_sppoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de sesin del
modem PLC.
*/
int modplc_sppoll(modplc_hd *);
/*
Funcin modplc_spgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
size_t modplc_spgetpayloadsize(modplc_hd *);

#endif

C.3.4.5. Archivo modplc.c


/*
modplc.c:
Implementacin de funciones referentes a la interfaz con el modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"

FernandoArielBeunza79156

381

Tesis de Grado en Ingeniera Informtica


#include <stdio.h>
#include "serial.h"
#include "modplc.h"

/* Declaracin de funciones privadas. */


static char __modplc_sendcmdline__(modplc_hd *, const char *, char *, size_t);
static int __modplc_sendcmd__(modplc_hd *, char, const char *, void **,
const void *, const char *, void **, void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modplc_init:
Inicializa los recursos utilizados por la interfaz con el modem PLC.
*/
modplc_hd *modplc_init(int sid, int layer, int debugmode)
{
/* Variables. */
char prompt;
modplc_hd *handle;
char cmdline[MODPLC_BUFFERSIZE];
char respline[MODPLC_BUFFERSIZE];

/* Smbolo de la lnea de
comando. */
/* Manejador de interfaz con el
modem PLC. */
/* Lnea de comando. */
/* Lnea de respuesta de
comando. */

/* Crea un nuevo manejador de interfaz con el modem PLC. */


handle = (modplc_hd *) malloc(sizeof(modplc_hd));
if (!handle) return NULL;
/* Inicializa la interfaz de comunicacin por puerto serie. */
handle->serialhd = serial_init(sid, MODPLC_BUFFERSIZE);
if (!handle->serialhd)
{
free(handle);
return NULL;
}
/* Si es requerido establece el modo depuracin. */
handle->debugmode = 0;
if (debugmode) handle->debugmode = 1;
/* Inicializa la interfaz con el modem PLC. */
while(1)
{
/* Inicializa el modem PLC. */
*(cmdline + 0) = '\n';
*(cmdline + 1) = 0;
prompt = __modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE);
if (prompt == MODPLC_INITPROMPT)
sprintf(cmdline, "reset");
else if (prompt == MODPLC_LAYPROMPT)
{
*(cmdline + 0) = MODPLC_NORMRESET;
*(cmdline + 1) = 0;
}
else if (prompt == MODPLC_NORMPROMPT)
{
*(cmdline + 0) = MODPLC_NORMRESET;
*(cmdline + 1) = 0;
}
else if (prompt == MODPLC_PARAMPROMPT)
{
*(cmdline + 0) = MODPLC_PARAMRESET;
*(cmdline + 1) = 0;
}
else

382

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


break;
strcat(cmdline, "\n");
if (__modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_INITPROMPT)
break;
sprintf(cmdline, "init\n");
if (__modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_LAYPROMPT)
break;
/* Establece la capa a la cual se quiere acceder. */
handle->layer = layer;
if (handle->layer == MODPLC_PHYSICALLAYER)
*(cmdline + 0) = MODPLC_PHYSICALLAYER + '0';
else if (handle->layer == MODPLC_DATALINKLAYER)
*(cmdline + 0) = MODPLC_DATALINKLAYER + '0';
else if (handle->layer == MODPLC_SESSIONLAYER)
*(cmdline + 0) = MODPLC_SESSIONLAYER + '0';
else
break;
*(cmdline + 1) = '\n';
*(cmdline + 2) = 0;
if (__modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_NORMPROMPT)
break;
/* Modem PLC en estado activo. */
handle->status = 1;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con el modem PLC. */
modplc_release(handle);
return NULL;
}
/*
Funcin modplc_release:
Libera los recursos utilizados por la interfaz con el modem PLC.
*/
int modplc_release(modplc_hd *hd)
{
/* Verifica que el manejador de interfaz con el modem PLC exista. */
if (!hd) return 0;
/* Libera la interfaz de comunicacin por puerto serie. */
serial_release(hd->serialhd);
/* Libera los recursos utilizados por la interfaz con el modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplc_status:
Devuelve el estado del modem PLC.
*/
int modplc_status(modplc_hd *hd)
{
/* Verifica que el manejador de interfaz con el modem PLC exista. */
if (!hd) return 0;
/* Verifica que el modem PLC se encuentre activo. */
if (!hd->status) return 0;
if (__modplc_sendcmdline__(hd, "\n", NULL, MODPLC_BUFFERSIZE) ==
MODPLC_NORMPROMPT)

FernandoArielBeunza79156

383

Tesis de Grado en Ingeniera Informtica


return 1;
hd->status = 0;
return 0;
}
/*
Funcin modplc_physndframe:
Enva una trama por medio de la capa fsica del modem PLC.
*/
size_t modplc_physndframe(modplc_hd *hd, unsigned char iface,
const void *frame, size_t framesize)
{
/* Variables. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Enva una trama. */
inparam[0] = &iface;
inparam[1] = &framesize;
outparam[0] = &framesize;
if (__modplc_sendcmd__(hd, MODPLCPHY_SNDFRAME, "bs", inparam, frame,
outparam, NULL))
return framesize;
return 0;

"s",

}
/*
Funcin modplc_phycapframe:
Captura una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phycapframe(modplc_hd *hd, unsigned char iface, size_t framesize)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Captura una trama. */
inparam[0] = &iface;
inparam[1] = &framesize;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_CAPFRAME, "bs", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_phygetframe:
Obtiene una trama capturada previamente por medio de la capa fsica del
modem PLC.
*/
size_t modplc_phygetframe(modplc_hd *hd, unsigned char iface, void *frame,

384

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


size_t framesize)
{
/* Variables. */
void *inparam[2];
void *outparam[1];

/* Parmetros de entrada del


comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Obtiene una trama capturada. */
inparam[0] = &iface;
inparam[1] = &framesize;
outparam[0] = &framesize;
if (__modplc_sendcmd__(hd, MODPLCPHY_GETFRAME, "bs", inparam, NULL,
outparam, frame))
return framesize;
return 0;

"s",

}
/*
Funcin modplc_phypoll:
Verifica la captura de una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phypoll(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Verifica la captura de una trama. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_POLL, "b", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_phyrsdframe:
Reenva una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phyrsdframe(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;

FernandoArielBeunza79156

385

Tesis de Grado en Ingeniera Informtica


/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Reenva una trama. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_RSDFRAME, "b", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_phyclrbuffer:
Limpia el buffer de captura de tramas de la capa fsica del modem PLC.
*/
int modplc_phyclrbuffer(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Limpia el buffer de captura de tramas. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_CLRBUFFER, "b", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_physensechannel:
Sensa el estado del canal de comunicacin por medio de la capa fsica del
modem PLC.
*/
int modplc_physensechannel(modplc_hd *hd, unsigned char iface,
unsigned char level, long int waittime)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Sensa el estado del canal de comunicacin. */
inparam[0] = &iface;
inparam[1] = &level;
inparam[2] = &waittime;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_SENSECHANNEL, "bbl", inparam, NULL,
"b", outparam, NULL))
return (result == 1);

386

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return 0;
}
/*
Funcin modplc_phygensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplc_phygensignal(modplc_hd *hd, unsigned char iface, int sig)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Genera la seal especificada. */
inparam[0] = &iface;
inparam[1] = &sig;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_GENSIGNAL, "bb", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_phytstreceive:
Realiza una prueba de recepcin de la capa fsica del modem PLC.
*/
int modplc_phytstreceive(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Realiza una prueba de recepcin. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_TSTRECEIVE, "b", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_phygetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplc_phygetpayloadsize(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned short int payloadsize;
/* Cantidad mxima de bytes que

FernandoArielBeunza79156

387

Tesis de Grado en Ingeniera Informtica


void *inparam[1];
void *outparam[1];

puede contener una trama. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Devuelve la cantidad mxima de byes que puede contener una trama. */
inparam[0] = &iface;
outparam[0] = &payloadsize;
if (__modplc_sendcmd__(hd, MODPLCPHY_GETPAYLOADSIZE, "b", inparam, NULL,
"s", outparam, NULL))
return (size_t) payloadsize;
return 0;
}
/*
Funcin modplc_dlopen:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlopen(modplc_hd *hd, unsigned char iface, unsigned char prot)
{
/* Variables. */
unsigned short int handle;
/* Manejador de conexin. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Abre una conexin. */
inparam[0] = &iface;
inparam[1] = &prot;
outparam[0] = &handle;
if (__modplc_sendcmd__(hd, MODPLCDL_OPEN, "bb", inparam, NULL,
outparam, NULL))
return (int) handle;
return 0;

"s",

}
/*
Funcin modplc_dlclose:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlclose(modplc_hd *hd, int handle)
{
/* Variables. */
unsigned char result;
void *inparam[2];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;

388

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Cierra una conexin. */
inparam[0] = &handle;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCDL_CLOSE, "s", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_dlsend:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlsend(modplc_hd *hd, int handle, modplc_dlphyaddr addr,
unsigned char prio, const void *msg, size_t msgsize)
{
/* Variables. */
void *inparam[4];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Enva un mensaje. */
inparam[0] = &handle;
inparam[1] = addr;
inparam[2] = &prio;
inparam[3] = &msgsize;
outparam[0] = &msgsize;
if (__modplc_sendcmd__(hd, MODPLCDL_SEND, "sabs", inparam, msg,
outparam, NULL))
return msgsize;
return 0;

"s",

}
/*
Funcin modplc_dlreceive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlreceive(modplc_hd *hd, int handle, modplc_dlphyaddr addr,
void *msg, size_t msgsize)
{
/* Variables. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Recibe un mensaje. */
inparam[0] = &handle;
inparam[1] = &msgsize;
outparam[0] = addr;
outparam[1] = &msgsize;
if (__modplc_sendcmd__(hd, MODPLCDL_RECEIVE, "ss", inparam, NULL,
outparam, msg))
return msgsize;
return 0;

FernandoArielBeunza79156

"as",

389

Tesis de Grado en Ingeniera Informtica


}
/*
Funcin modplc_dlpoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de enlace del
modem PLC.
*/
int modplc_dlpoll(modplc_hd *hd, int handle)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Verifica la llegada de un nuevo mensaje. */
inparam[0] = &handle;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCDL_POLL, "s", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_dlgetaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplc_dlgetaddress(modplc_hd *hd, unsigned char iface,
modplc_dlphyaddr paddr)
{
/* Variables. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Devuelve la direccin fsica. */
inparam[0] = &iface;
outparam[0] = paddr;
return __modplc_sendcmd__(hd, MODPLCDL_GETADDRESS, "b", inparam, NULL,
"a", outparam, NULL);
}
/*
Funcin modplc_dladdlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dladdlogaddress(modplc_hd *hd, unsigned char iface,
unsigned char prot, modplc_dllogaddr laddr)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del

390

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Agrega una nueva direccin lgica. */
inparam[0] = &iface;
inparam[1] = &prot;
inparam[2] = &laddr;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCDL_ADDLOGADDRESS, "bbl", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_dldellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dldellogaddress(modplc_hd *hd, unsigned char iface,
unsigned char prot, modplc_dllogaddr laddr)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Elimina una direccin lgica. */
inparam[0] = &iface;
inparam[1] = &prot;
inparam[2] = &laddr;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCDL_DELLOGADDRESS, "bbl", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_dlgetphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa de
enlace del modem PLC.
*/
int modplc_dlgetphyaddress(modplc_hd *hd, unsigned char iface,
unsigned char prot, modplc_dllogaddr laddr,
modplc_dlphyaddr paddr)
{
/* Variables. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;

FernandoArielBeunza79156

391

Tesis de Grado en Ingeniera Informtica


/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Devuelve la direccin fsica asociada a la direccin lgica. */
inparam[0] = &iface;
inparam[1] = &prot;
inparam[2] = &laddr;
outparam[0] = paddr;
return __modplc_sendcmd__(hd, MODPLCDL_GETPHYADDRESS, "bbl", inparam,
NULL, "a", outparam, NULL);
}
/*
Funcin modplc_dlgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de enlace del modem PLC.
*/
size_t modplc_dlgetpayloadsize(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned short int payloadsize;
/* Cantidad mxima de bytes que
puede contener una trama. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Devuelve la cantidad mxima de byes que puede contener un mensaje. */
inparam[0] = &iface;
outparam[0] = &payloadsize;
if (__modplc_sendcmd__(hd, MODPLCDL_GETPAYLOADSIZE, "b", inparam, NULL,
"s", outparam, NULL))
return (size_t) payloadsize;
return 0;
}
/*
Funcin modplc_sppublish:
Registra el dispositivo como publicador del grupo de difusin especificado
de la capa de sesin del modem PLC.
*/
int modplc_sppublish(modplc_hd *hd, modplc_spgrpid grpid)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
inparam[0] = &grpid;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCSP_PUBLISH, "b", inparam, NULL,
outparam, NULL))
return (result == 1);

392

"b",

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return 0;
}
/*
Funcin modplc_spsubscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado
de la capa de sesin del modem PLC.
*/
int modplc_spsubscribe(modplc_hd *hd, modplc_spgrpid grpid)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
inparam[0] = &grpid;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCSP_SUBSCRIBE, "b", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_spleave:
Desvincula el dispositivo del grupo de difusin especificado de la capa de
sesin del modem PLC.
*/
int modplc_spleave(modplc_hd *hd, modplc_spgrpid grpid)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
inparam[0] = &grpid;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCSP_LEAVE, "b", inparam, NULL, "b",
outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_spsend:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spsend(modplc_hd *hd, modplc_spgrpid grpid, int nosec,
const void *msg, size_t msgsize)
{

FernandoArielBeunza79156

393

Tesis de Grado en Ingeniera Informtica


/* Variables. */
void *inparam[3];
void *outparam[1];

/* Parmetros de entrada del


comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Enva un mensaje. */
inparam[0] = &grpid;
inparam[1] = &nosec;
inparam[2] = &msgsize;
outparam[0] = &msgsize;
if (__modplc_sendcmd__(hd, MODPLCSP_SEND, "bbs", inparam, msg,
outparam, NULL))
return msgsize;
return 0;

"s",

}
/*
Funcin modplc_spreceive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spreceive(modplc_hd *hd, modplc_spgrpid *grpid, void *msg,
size_t msgsize)
{
/* Variables. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[2];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Recibe un mensaje. */
inparam[0] = &msgsize;
outparam[0] = grpid;
outparam[1] = &msgsize;
if (__modplc_sendcmd__(hd, MODPLCSP_RECEIVE, "s", inparam, NULL,
outparam, msg))
return msgsize;
return 0;

"bs",

}
/*
Funcin modplc_sppoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de sesin del
modem PLC.
*/
int modplc_sppoll(modplc_hd *hd)
{
/* Variables. */
unsigned char result;
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */

394

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Verifica la llegada de un nuevo mensaje. */
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCSP_POLL, "", NULL, NULL,
NULL))
return (result == 1);
return 0;

"b", outparam,

}
/*
Funcin modplc_spgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
size_t modplc_spgetpayloadsize(modplc_hd *hd)
{
/* Variables. */
unsigned short int payloadsize;
void *outparam[1];

/* Cantidad mxima de bytes que


puede contener una trama. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Devuelve la cantidad mxima de byes que puede contener un mensaje. */
outparam[0] = &payloadsize;
if (__modplc_sendcmd__(hd, MODPLCSP_GETPAYLOADSIZE, "", NULL, NULL, "s",
outparam, NULL))
return (size_t) payloadsize;
return 0;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplc_sendcmdline__:
Enva una lnea de comando por medio de la interfaz de comunicacin por
puerto serie.
*/
static char __modplc_sendcmdline__(modplc_hd *hd, const char *cmdline,
char *resp, size_t respsize)
{
/* Variables. */
size_t send;
/* Cantidad de bytes por envo. */
size_t size;
/* Tamao de la lnea de
respuesta. */
char *lastchar;
/* Pntero al ltimo caracter. */
char respline[MODPLC_BUFFERSIZE];
/* Respuesta a la lnea de
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Recibe la respuesta al comando. */
size = 0;
*respline = 0;
while(size < respsize)
{
/* Enva un fragmento de la lnea de comando. */
send = strlen(cmdline) - size;
if (send > MODPLC_FRAGMENTLINESIZE) send = MODPLC_FRAGMENTLINESIZE;
if (size < strlen(cmdline))
serial_send(hd->serialhd, cmdline + size, send);

FernandoArielBeunza79156

395

Tesis de Grado en Ingeniera Informtica


/* Recibe la respuesta. */
size += serial_receive(hd->serialhd, respline + size, respsize - size);
*(respline + size) = 0;
/* Verifica si se recibi el smbolo de la lnea de comando. */
lastchar = strchr(respline, MODPLC_INITPROMPT);
if (lastchar) break;
lastchar = strchr(respline, MODPLC_LAYPROMPT);
if (lastchar) break;
lastchar = strchr(respline, MODPLC_NORMPROMPT);
if (lastchar) break;
lastchar = strchr(respline, MODPLC_PARAMPROMPT);
if (lastchar) break;
if (size > respsize)
{
lastchar = respline + size - 1;
break;
}
}
/* Devuelve la respuesta al comando. */
if (resp) strcpy(resp, respline);
if (hd->debugmode && size)
{
printf("%s", respline);
fflush(stdout);
}
return *lastchar;
}
/*
Funcin __modplc_sendcmd__:
Enva un comando por medio de la interfaz de comunicacin por puerto serie
y devuelve su respuesta .
*/
static int __modplc_sendcmd__(modplc_hd *hd, char op, const char *infmt,
void **inparam, const void *inframe,
const char *outfmt, void **outparam,
void *outframe)
{
/* Variables. */
int param;
/* Nmero de parmetro. */
size_t i;
/* Contador. */
size_t j;
/* Contador. */
size_t framesize;
/* Tamao de la trama. */
unsigned char *ptrline;
/* Puntero a la lnea de
respuesta de comando. */
unsigned char *ptrparam;
/* Puntero al parmetro. */
unsigned char *ptrresp;
/* Puntero a la respuesta. */
unsigned char *ptrframe;
/* Puntero a la trama. */
unsigned char dat;
/* Dato. */
char hexval[3];
/* Valor hexadecimal. */
char cmdline[MODPLC_BUFFERSIZE];
/* Lnea de comando. */
char rline[MODPLC_BUFFERSIZE];
/* Lnea de respuesta de
comando. */
char respline[MODPLC_BUFFERSIZE];
/* Lnea de respuesta de
comando. */

/* Verifica que el modem PLC se encuentre en estado activo. */


modplc_status(hd);
if (!hd->status) return 0;
/* Enva el
param = 0;
*(cmdline +
*(cmdline +
*(cmdline +
while(infmt
{

396

comando y sus parmetros. */


0)
1)
2)
&&

= op;
= '\n';
= 0;
inparam)

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Enva el comando y un parmetro procesado. */
if (!infmt[param]) break;
if (__modplc_sendcmdline__(hd, cmdline, cmdline, MODPLC_BUFFERSIZE) !=
MODPLC_PARAMPROMPT)
return 0;
/* Procesa el siguiente parmetro a enviar. */
ptrparam = (unsigned char *) inparam[param];
if (infmt[param] == 'b')
sprintf(cmdline, "\\%02X\n", *((unsigned char *) inparam[param]));
else if (infmt[param] == 's')
sprintf(cmdline, "\\%02X\\%02X\n", ptrparam[1], ptrparam[0]);
else if (infmt[param] == 'l')
sprintf(cmdline, "\\%02X\\%02X\\%02X\\%02X\n",
ptrparam[3], ptrparam[2], ptrparam[1], ptrparam[0]);
else if (infmt[param] == 'a')
sprintf(cmdline,
"\\%02X\\%02X\\%02X\\%02X\\%02X\\%02X\\%02X\\%02X\n",
ptrparam[0], ptrparam[1], ptrparam[2], ptrparam[3],
ptrparam[4], ptrparam[5], ptrparam[6], ptrparam[7]);
param ++;
}
/* Si hay una trama que enviar se enva su contenido. */
if (inframe)
{
/* Espera para poder enviar la trama. */
if (__modplc_sendcmdline__(hd, cmdline, respline, MODPLC_BUFFERSIZE) !=
MODPLC_PARAMPROMPT)
return 0;
/* Enva la trama. */
*cmdline = 0;
ptrframe = (char *) inframe;
framesize = *((size_t *) inparam[param - 1]);
for(i = 0; i < framesize; )
{
dat = (unsigned char) *ptrframe;
if ((dat >= 0x20) && (dat <= 0x7e) && (dat != '\\') &&
(dat != MODPLC_INITPROMPT) && (dat != MODPLC_LAYPROMPT) &&
(dat != MODPLC_NORMPROMPT) && (dat != MODPLC_PARAMPROMPT))
sprintf(hexval, "%c", dat);
else
sprintf(hexval, "\\%02X", dat);
strcat(cmdline, hexval);
ptrframe ++;
i ++;
if ((i % 24) && (i < framesize)) continue;
strcat(cmdline, "\n");
if (__modplc_sendcmdline__(hd, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_PARAMPROMPT)
break;
*cmdline = 0;
}
}
/* Caso contrario se espera la respuesta al comando. */
else
{
if (__modplc_sendcmdline__(hd, cmdline, respline, MODPLC_BUFFERSIZE) !=
MODPLC_NORMPROMPT)
return 0;
}
/* Recibe los parmetros de respuesta. */
i = 0;
param = 0;
ptrresp = respline;
while(*ptrresp != MODPLC_NORMPROMPT)
{

FernandoArielBeunza79156

397

Tesis de Grado en Ingeniera Informtica


if (*ptrresp == '\r')
{
ptrresp ++;
continue;
}
else if (*ptrresp != '\n')
{
rline[i++] = *(ptrresp ++);
continue;
}
rline[i] = 0;
ptrresp ++;
i = 0;
if (!strlen(rline)) continue;
if (param < 1)
{
param ++;
continue;
}
if (!outfmt[param - 1])
{
ptrresp -= (strlen(rline) + 2);
break;
}
ptrline = rline;
ptrparam = (unsigned char *) outparam[param - 1];
if (outfmt[param - 1] == 'b')
{
if (*ptrline != '\\')
*ptrparam = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat);
*ptrparam = dat;
}
}
else if (outfmt[param - 1] == 's')
{
for(j = 0; j < 2; j++)
{
if (*ptrline != '\\')
*(ptrparam + 1 - j) = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat);
*(ptrparam + 1 - j) = dat;
}
}
}
else if (outfmt[param - 1] == 'l')
{
for(j = 0; j < 4; j++)
{
if (*ptrline != '\\')
*(ptrparam + 3 - j) = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat);
*(ptrparam + 3 - j) = dat;

398

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
}
}
else if (outfmt[param - 1] == 'a')
{
for(j = 0; j < 8; j++)
{
if (*ptrline != '\\')
*(ptrparam + j) = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat);
*(ptrparam + j) = dat;
}
}
}
param++;
}
/* Si hay una trama que recibir se recibe su contenido. */
if (outframe)
{
ptrframe = (char *) outframe;
framesize = *((size_t *) outparam[param - 2]);
for(j = 0; j < framesize; )
{
dat = *(ptrresp ++);
if ((dat == '\n') || (dat == '\r')) continue;
if (dat != '\\')
*ptrframe = dat;
else
{
hexval[0] = *(ptrresp ++);
hexval[1] = *(ptrresp ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat);
*ptrframe = dat;
}
ptrframe ++;
j ++;
}
}
/* xito. */
return 1;
}

C.3.4.6. Archivo modsp.h


/*
modsp.h:
Declaracin de funciones referentes a la interfaz de la capa de sesin del
modem PLC.
*/

#if !defined(__MODSP_H__)
#define __MODSP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modplc.h"

FernandoArielBeunza79156

399

Tesis de Grado en Ingeniera Informtica

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modsp_grpid;
/* Manejador de interfaz con la capa de sesin del modem PLC. */
typedef struct
{
HANDLE mutexsem;
/* Semforo de finalizacin de
deteccin de recepcin. */
HANDLE detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
modplc_hd *modplchd;
/* Manejador de interfaz con el
modem PLC. */
void (*recfun)
(void *, modsp_grpid, void *,
size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} modsp_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin modsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modsp_hd *modsp_init(int, int);
/*
Funcin modsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modsp_release(modsp_hd *);
/*
Funcin modsp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modsp_publish(modsp_hd *, modsp_grpid);
/*
Funcin modsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int modsp_subscribe(modsp_hd *, modsp_grpid);
/*
Funcin modsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modsp_leave(modsp_hd *, modsp_grpid);
/*
Funcin modsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_send(modsp_hd *, modsp_grpid, unsigned char, const void *,
size_t);
/*
Funcin modsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/

400

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


size_t modsp_receive(modsp_hd *, modsp_grpid *, void *, size_t);
/*
Funcin modsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modsp_notify(modsp_hd *, void (*func)(modsp_hd *, modsp_grpid, void *,
size_t, void *), void *);
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modsp_poll(modsp_hd *);
/*
Funcin modsp_status:
Devuelve el estado del modem PLC.
*/
int modsp_status(modsp_hd *);
/*
Funcin modsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
size_t modsp_getpayloadsize(modsp_hd *);

#endif

C.3.4.7. Archivo modsp.c


/*
modsp.c:
Implementacin de funciones referentes a la interfaz de la capa de sesin
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <windows.h>
#include <process.h>
#include "modplc.h"
#include "modsp.h"

/* Declaracin de funciones privadas. */


static DWORD WINAPI __modsp_detectproc__(LPVOID);

/* Implementacin de funciones pblicas. */


/*
Funcin modsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modsp_hd *modsp_init(int sid, int debugmode)
{
/* Variables. */
modsp_hd *handle;

/* Manejador de interfaz con la


capa de sesin del modem PLC. */

/* Crea un nuevo manejador de interfaz con la capa de sesin del modem


PLC. */
handle = (modsp_hd *) malloc(sizeof(modsp_hd));

FernandoArielBeunza79156

401

Tesis de Grado en Ingeniera Informtica


if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de sesin del modem
PLC. */
while(1)
{
/* Inicializa el manejador de interfaz con el modem PLC. */
handle->modplchd = modplc_init(sid, MODPLC_SESSIONLAYER, debugmode);
if (!handle->modplchd) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
handle->payloadsize = modplc_spgetpayloadsize(handle->modplchd);
if (!handle->payloadsize) break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Inicializa semforo. */
handle->mutexsem = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->mutexsem == INVALID_HANDLE_VALUE) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de sesin del modem
PLC. */
modplc_release(handle->modplchd);
free(handle);
return NULL;
}
/*
Funcin modsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modsp_release(modsp_hd *hd)
{
/* Verifica que el manejador de interfaz con la capa de sesin del modem
PLC exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modsp_notify(hd, NULL, NULL);
/* Libera la interfaz con el modem PLC. */
modplc_release(hd->modplchd);
/* Libera los recursos utilizados por la interfaz con la capa de sesin del
modem PLC. */
CloseHandle(hd->mutexsem);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modsp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int modsp_publish(modsp_hd *hd, modsp_grpid grpid)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */

402

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Registra el dispositivo como publicador. */
result = modplc_sppublish(hd->modplchd, grpid);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int modsp_subscribe(modsp_hd *hd, modsp_grpid grpid)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Registra el dispositivo como suscriptor. */
result = modplc_spsubscribe(hd->modplchd, grpid);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modsp_leave(modsp_hd *hd, modsp_grpid grpid)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Desvincula el dispositivo. */
result = modplc_spleave(hd->modplchd, grpid);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la desvinculacin del dispositivo. */
return result;
}
/*
Funcin modsp_send:

FernandoArielBeunza79156

403

Tesis de Grado en Ingeniera Informtica


Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_send(modsp_hd *hd, modsp_grpid grpid, unsigned char nosec,
const void *msg, size_t msgsize)
{
/* Verifica que el manejador de interfaz con la capa de sesin del modem
PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Enva un mensaje. */
msgsize = modplc_spsend(hd->modplchd, grpid, nosec, msg, msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad de bytes envados. */
return msgsize;
}
/*
Funcin modsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_receive(modsp_hd *hd, modsp_grpid *grpid, void *msg,
size_t msgsize)
{
/* Verifica que el manejador de interfaz con la capa de sesin del modem
PLC exista. */
if (!hd) return 0;
/* Espera la llegada de un mensaje. */
while(!modsp_poll(hd));
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Recibe un mensaje. */
msgsize = modplc_spreceive(hd->modplchd, grpid, msg, msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad de bytes recibidos. */
return msgsize;
}
/*
Funcin modsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modsp_notify(modsp_hd *hd, void (*func)(modsp_hd *, modsp_grpid, void *,
size_t, void *), void *param)
{
/* Variables. */
DWORD tid;
/* Identificador de hilo. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))

404

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
WaitForSingleObject(hd->mutexsem, INFINITE);
hd->recfun = func;
hd->param = param;
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora definida
previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
WaitForSingleObject(hd->mutexsem, INFINITE);
hd->recfun = NULL;
hd->param = param;
ReleaseSemaphore(hd->mutexsem, 1, NULL);
WaitForSingleObject(hd->detectthread, INFINITE);
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
WaitForSingleObject(hd->mutexsem, INFINITE);
hd->recfun = func;
hd->param = param;
hd->detectthread = CreateThread(NULL, 0, __modsp_detectproc__, hd, 0,
&tid);
if (hd->detectthread == INVALID_HANDLE_VALUE)
{
hd->recfun = NULL;
hd->param = NULL;
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 0;
}
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modsp_poll(modsp_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Verifica la recepcin de un mensaje. */
result = modplc_sppoll(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la verificacin de la recepcin de un
mensaje. */
return result;
}

FernandoArielBeunza79156

405

Tesis de Grado en Ingeniera Informtica


/*
Funcin modsp_status:
Devuelve el estado del modem PLC.
*/
int modsp_status(modsp_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene el estado del modem PLC. */
result = modplc_status(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del modem PLC. */
return result;
}
/*
Funcin modsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de sesin del modem PLC.
*/
size_t modsp_getpayloadsize(modsp_hd *hd)
{
/* Variables. */
size_t payloadsize;

/* Cantidad mxima de bytes que


puede contener un mensaje. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
payloadsize = modplc_spgetpayloadsize(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad mxima de bytes que puede contener un mensaje. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modsp_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser ledo.
*/
static DWORD WINAPI __modsp_detectproc__(LPVOID param)
{
/* Variables. */
int recvflag;
size_t msgsize;
modsp_grpid grpid;

406

/* Indicador de recepcin de un
mensaje. */
/* Tamao del mensaje recibido. */
/* Identificador de grupo. */

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


modsp_hd *hd;
void (*func)
(void *, modsp_grpid, void *,
size_t, void *);
char *msg;

/* Manejador de interfaz con la


capa de sesin del modem PLC. */

/* Manejador de mensajes
recibidos. */
/* Puntero al mensaje recibido. */

/* Carga el manejador de interfaz con la capa de sesin del modem PLC. */


hd = (modsp_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
recvflag = modplc_sppoll(hd->modplchd);
if (recvflag)
{
msg = (unsigned char *)
malloc(hd->payloadsize * sizeof(unsigned char));
if (msg)
msgsize = modplc_spreceive(hd->modplchd, &grpid, msg,
hd->payloadsize);
else
recvflag = 0;
}
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Verifica si se ha detectado la recepcin de un mensaje para invocar
a la funcin manejadora de mensajes recibidos. */
if (recvflag)
{
func(hd, grpid, msg, msgsize, hd->param);
free(msg);
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 0;
}

C.3.4.8. Archivo moddl.h


/*
moddl.h:
Declaracin de funciones referentes a la interfaz de la capa de enlace del
modem PLC.
*/

#if !defined(__MODDL_H__)
#define __MODDL_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modplc.h"

FernandoArielBeunza79156

407

Tesis de Grado en Ingeniera Informtica


/* Definicin de tipos. */
/* Direccin fsica del modem PLC. */
typedef unsigned char moddl_phyaddr[8];
/* Direccin lgica del modem PLC. */
typedef unsigned long int moddl_logaddr;
/* Manejador de interfaz con la capa de enlace del modem PLC. */
typedef struct
{
HANDLE mutexsem;
/* Semforo de finalizacin de
deteccin de recepcin. */
unsigned long int conncounter;
/* Contador de conexiones
abiertas. */
modplc_hd *modplchd;
/* Manejador de interfaz con el
modem PLC. */
} moddl_hd;
/* Manejador de conexin por medio de la capa de enlace del modem PLC. */
typedef struct
{
HANDLE detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
int handle;
/* Identificador de conexin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
unsigned char iface;
/* Identificador de intarfaz
fsica. */
moddl_hd *moddlhd;
/* Manejador de interfaz con la
capa de enlance del modem
PLC. */
void (*recfun)
(void *, moddl_phyaddr, void *,
size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} moddlconn_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin moddl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
moddl_hd *moddl_init(int, int);
/*
Funcin moddl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int moddl_release(moddl_hd *);
/*
Funcin moddl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
moddlconn_hd *moddl_open(moddl_hd *, unsigned char, unsigned char);
/*
Funcin moddl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int moddl_close(moddlconn_hd *);
/*
Funcin moddl_send:

408

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t moddl_send(moddlconn_hd *, moddl_phyaddr, unsigned char, const void *,
size_t);
/*
Funcin moddl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t moddl_receive(moddlconn_hd *, moddl_phyaddr, void *, size_t);
/*
Funcin moddl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int moddl_notify(moddlconn_hd *, void (*func)(moddlconn_hd *, moddl_phyaddr,
void *, size_t, void *), void *);
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int moddl_poll(moddlconn_hd *);
/*
Funcin moddl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int moddl_getaddress(moddl_hd *, unsigned char, moddl_phyaddr);
/*
Funcin moddl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlade del modem PLC.
*/
int moddl_addlogaddress(moddl_hd *, unsigned char, unsigned char,
moddl_logaddr);
/*
Funcin moddl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int moddl_dellogaddress(moddl_hd *, unsigned char, unsigned char,
moddl_logaddr);
/*
Funcin moddl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa de
enlace del modem PLC.
*/
int moddl_getphyaddress(moddl_hd *, unsigned char, unsigned char,
moddl_logaddr, moddl_phyaddr);
/*
Funcin moddl_status:
Devuelve el estado del modem PLC.
*/
int moddl_status(moddl_hd *);
/*
Funcin moddl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de enlace del modem PLC.
*/
size_t moddl_getpayloadsize(moddl_hd *, unsigned char);

#endif

FernandoArielBeunza79156

409

Tesis de Grado en Ingeniera Informtica

C.3.4.9. Archivo moddl.c


/*
moddl.c:
Implementacin de funciones referentes a la interfaz de la capa de enlace
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <windows.h>
#include <process.h>
#include "modplc.h"
#include "moddl.h"

/* Declaracin de funciones privadas. */


static DWORD WINAPI __moddl_detectproc__(LPVOID);

/* Implementacin de funciones pblicas. */


/*
Funcin moddl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
moddl_hd *moddl_init(int sid, int debugmode)
{
/* Variables. */
moddl_hd *handle;

/* Manejador de interfaz con la


capa de enlace del modem PLC. */

/* Crea un nuevo manejador de interfaz con la capa de enlace del modem


PLC. */
handle = (moddl_hd *) malloc(sizeof(moddl_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de enlace del modem
PLC. */
while(1)
{
/* Inicializa el manejador de interfaz con el modem PLC. */
handle->modplchd = modplc_init(sid, MODPLC_DATALINKLAYER, debugmode);
if (!handle->modplchd) break;
/* Inicializa el contador de conexiones abiertas. */
handle->conncounter = 0;
/* Inicializa semforo. */
handle->mutexsem = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->mutexsem == INVALID_HANDLE_VALUE) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de enlace del modem
PLC. */
modplc_release(handle->modplchd);
free(handle);
return NULL;
}
/*
Funcin moddl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int moddl_release(moddl_hd *hd)

410

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
/* Verifica que el manejador de interfaz con la capa de enlace del modem
PLC exista. */
if (!hd) return 0;
/* Verifica que no existan conexiones abiertas. */
if (hd->conncounter) return 0;
/* Libera la interfaz con el modem PLC. */
modplc_release(hd->modplchd);
/* Libera los recursos utilizados por la interfaz con la capa de enlace del
modem PLC. */
CloseHandle(hd->mutexsem);
free(hd);
/* xito. */
return 1;
}
/*
Funcin moddl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
moddlconn_hd *moddl_open(moddl_hd *hd, unsigned char iface, unsigned char prot)
{
/* Variables. */
moddlconn_hd *handle;
/* Manejador de conexin de la capa
de enlace del modem PLC. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return NULL;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Crea un nuevo manejador de conexin por medio de la capa de enlace del
modem PLC. */
handle = (moddlconn_hd *) malloc(sizeof(moddlconn_hd));
if (!handle)
{
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return NULL;
}
/* Inicializa el manejador de conexin. */
while(1)
{
/* Abre una conexin. */
handle->moddlhd = hd;
handle->iface = iface;
handle->handle = modplc_dlopen(hd->modplchd, handle->iface, prot);
if (!handle->handle) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
handle->payloadsize = modplc_dlgetpayloadsize(hd->modplchd, iface);
if (!handle->payloadsize) break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Actualiza el nmero de conexiones. */
handle->moddlhd->conncounter ++;
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);

FernandoArielBeunza79156

411

Tesis de Grado en Ingeniera Informtica


/* Devuelve el manejador creado. */
return handle;
}
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* No se pudo abrir la conexin. */
modplc_dlclose(hd->modplchd, handle->handle);
free(handle);
return NULL;
}
/*
Funcin moddl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int moddl_close(moddlconn_hd *hd)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
moddl_notify(hd, NULL, NULL);
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
/* Actualiza el nmero de conexiones. */
hd->moddlhd->conncounter --;
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
/* Libera los recursos utilizados por la conexin por medio de la capa de
enlace del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin moddl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t moddl_send(moddlconn_hd *hd, moddl_phyaddr addr, unsigned char prio,
const void *msg, size_t msgsize)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
/* Enva un mensaje. */
msgsize = modplc_dlsend(hd->moddlhd->modplchd, hd->handle, addr, prio, msg,
msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
/* Devuelve la cantidad de bytes recibidos. */
return msgsize;
}
/*
Funcin moddl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.

412

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/
size_t moddl_receive(moddlconn_hd *hd, moddl_phyaddr addr, void *msg,
size_t msgsize)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Espera la llegada de un mensaje. */
while(!moddl_poll(hd));
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
/* Recibe un mensaje. */
msgsize = modplc_dlreceive(hd->moddlhd->modplchd, hd->handle, addr, msg,
msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
/* Devuelve la cantidad de bytes recibidos. */
return msgsize;
}
/*
Funcin moddl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int moddl_notify(moddlconn_hd *hd, void (*func)(moddlconn_hd *, moddl_phyaddr,
void *, size_t, void *), void *param)
{
/* Variables. */
DWORD tid;
/* Identificador de hilo. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
hd->recfun = func;
hd->param = param;
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora definida
previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
hd->recfun = NULL;
hd->param = param;
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
WaitForSingleObject(hd->detectthread, INFINITE);
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{

FernandoArielBeunza79156

413

Tesis de Grado en Ingeniera Informtica


WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
hd->recfun = func;
hd->param = param;
hd->detectthread = CreateThread(NULL, 0, __moddl_detectproc__, hd, 0,
&tid);
if (hd->detectthread == INVALID_HANDLE_VALUE)
{
hd->recfun = NULL;
hd->param = NULL;
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
return 0;
}
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int moddl_poll(moddlconn_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
/* Verifica la recepcin de un mensaje. */
result = modplc_dlpoll(hd->moddlhd->modplchd, hd->handle);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
/* Devuelve el resultado de la verificacin de la recepcin de un
mensaje. */
return result;
}
/*
Funcin moddl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int moddl_getaddress(moddl_hd *hd, unsigned char iface, moddl_phyaddr addr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene la direccin fsica. */
result = modplc_dlgetaddress(hd->modplchd, iface, addr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);

414

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Devuelve el resultado de la bsqueda. */
return result;
}
/*
Funcin moddl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int moddl_addlogaddress(moddl_hd *hd, unsigned char iface, unsigned char prot,
moddl_logaddr addr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Agrega una nueva direccin lgica. */
result = modplc_dladdlogaddress(hd->modplchd, iface, prot, addr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del agregado de la direccin lgica. */
return result;
}
/*
Funcin moddl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int moddl_dellogaddress(moddl_hd *hd, unsigned char iface, unsigned char prot,
moddl_logaddr addr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Elimina una direccin lgica. */
result = modplc_dldellogaddress(hd->modplchd, iface, prot, addr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la eliminacin de la direccin lgica. */
return result;
}
/*
Funcin moddl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa de
enlace del modem PLC.
*/
int moddl_getphyaddress(moddl_hd *hd, unsigned char iface, unsigned char prot,
moddl_logaddr laddr, moddl_phyaddr paddr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

FernandoArielBeunza79156

415

Tesis de Grado en Ingeniera Informtica


/* Verifica que el manejador de interfaz con la capa de enlace del modem
PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene la direccin fsica asociada a la direccin lgica. */
result = modplc_dlgetphyaddress(hd->modplchd, iface, prot, laddr, paddr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la bsqueda. */
return result;
}
/*
Funcin moddl_status:
Devuelve el estado del modem PLC.
*/
int moddl_status(moddl_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene el estado del modem PLC. */
result = modplc_status(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del modem PLC. */
return result;
}
/*
Funcin moddl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de la
capa de enlace del modem PLC.
*/
size_t moddl_getpayloadsize(moddl_hd *hd, unsigned char iface)
{
/* Variables. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */

/* Verifica que el manejador de interfaz con la capa de enlace del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
payloadsize = modplc_dlgetpayloadsize(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad mxima de bytes que puede contener un mensaje. */

416

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __moddl_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser ledo.
*/
static DWORD WINAPI __moddl_detectproc__(LPVOID param)
{
/* Variables. */
int recvflag;
size_t msgsize;
moddl_phyaddr addr;
moddlconn_hd *hd;

void (*func)
(void *, moddl_phyaddr, void *,
size_t, void *);
char *msg;

/* Indicador de recepcin de un
mensaje. */
/* Tamao del mensaje recibido. */
/* Direccin fsica de origen del
mensaje. */
/* Manejador de conexin por medio
de la capa de enlace del modem
PLC. */

/* Manejador de mensajes
recibidos. */
/* Puntero al mensaje recibido. */

/* Carga el manejador de conexin por medio de la capa de enlace del modem


PLC. */
hd = (moddlconn_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
WaitForSingleObject(hd->moddlhd->mutexsem, INFINITE);
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
recvflag = modplc_dlpoll(hd->moddlhd->modplchd, hd->handle);
if (recvflag)
{
msg = (unsigned char *)
malloc(hd->payloadsize * sizeof(unsigned char));
if (msg)
msgsize = modplc_dlreceive(hd->moddlhd->modplchd, hd->handle,
addr, msg, hd->payloadsize);
else
recvflag = 0;
}
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
/* Verifica si se ha detectado la recepcin de un mensaje para invocar
a la funcin manejadora de mensajes recibidos. */
if (recvflag)
{
func(hd, addr, msg, msgsize, hd->param);
free(msg);
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
ReleaseSemaphore(hd->moddlhd->mutexsem, 1, NULL);
return 0;
}

FernandoArielBeunza79156

417

Tesis de Grado en Ingeniera Informtica

C.3.4.10. Archivo modphy.h


/*
modphy.h:
Declaracin de funciones referentes a la interfaz de la capa fsica del
modem PLC.
*/

#if !defined(__MODPHY_H__)
#define __MODPHY_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modplc.h"

/* Definicin de tipos. */
/* Manejador de interfaz con la capa fsica del modem PLC. */
typedef struct
{
HANDLE mutexsem;
/* Semforo de finalizacin de
deteccin de recepcin. */
modplc_hd *modplchd;
/* Manejador de interfaz con el
modem PLC. */
struct
{
DWORD threadid;
/* Identificador de hilo de
deteccin. */
HANDLE detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
void (*recfun)(void *, void *);
/* Funcin manejadora de tramas
capturadas. */
void *param;
/* Parmetros para la funcin
manejadora de tramas
recibidas. */
} iface[256];
/* Tabla de interfaces fsicas. */
} modphy_hd;

/* Definicin de constantes. */
/* Tipos de seales. */
#define MODPHY_NOISESIGNAL
#define MODPHY_TESTSIGNAL1
#define MODPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Declaracin de funciones pblicas. */


/*
Funcin modphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
modphy_hd *modphy_init(int, int);
/*
Funcin modphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modphy_release(modphy_hd *);
/*
Funcin modphy_sndframe:
Enva una trama.
*/
size_t modphy_sndframe(modphy_hd *, unsigned char, const void *, size_t);

418

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modphy_capframe:
Captura una trama.
*/
int modphy_capframe(modphy_hd *, unsigned char, size_t);
/*
Funcin modphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modphy_getframe(modphy_hd *, unsigned char, void *, size_t);
/*
Funcin modphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
int modphy_notify(modphy_hd *, unsigned char,
void (*func)(modphy_hd *, void *), void *);
/*
Funcin modphy_poll:
Verifica la captura de una trama.
*/
int modphy_poll(modphy_hd *, unsigned char);
/*
Funcin modphy_rsdframe:
Reenva una trama.
*/
int modphy_rsdframe(modphy_hd *, unsigned char);
/*
Funcin modphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modphy_clrbuffer(modphy_hd *, unsigned char);
/*
Funcin modphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int modphy_sensechannel(modphy_hd *, unsigned char, unsigned char, long int);
/*
Funcin modphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modphy_gensignal(modphy_hd *, unsigned char, int);
/*
Funcin modphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modphy_tstreceive(modphy_hd *, unsigned char);
/*
Funcin modphy_status:
Devuelve el estado del modem PLC.
*/
int modphy_status(modphy_hd *);
/*
Funcin modphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modphy_getpayloadsize(modphy_hd *, unsigned char);

#endif

FernandoArielBeunza79156

419

Tesis de Grado en Ingeniera Informtica

C.3.4.11. Archivo modphy.c


/*
modphy.c:
Implementacin de funciones referentes a la interfaz de la capa fsica del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <windows.h>
#include <process.h>
#include "modplc.h"
#include "modphy.h"

/* Declaracin de funciones privadas. */


static DWORD WINAPI __modphy_detectproc__(LPVOID);

/* Implementacin de funciones pblicas. */


/*
Funcin modphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
modphy_hd *modphy_init(int sid, int debugmode)
{
/* Variables. */
short int iface;
modphy_hd *handle;

/* Identificadores de interfaces
fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */

/* Crea un nuevo manejador de interfaz con la capa fsica del modem PLC. */
handle = (modphy_hd *) malloc(sizeof(modphy_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa fsica del modem PLC. */
while(1)
{
/* Inicializa el manejador de interfaz con el modem PLC. */
handle->modplchd = modplc_init(sid, MODPLC_PHYSICALLAYER, debugmode);
if (!handle->modplchd) break;
/* Inicializa el manejador de tramas capturadas de cada una de las
interfaces fsicas. */
for(iface = 0; iface < 256; iface ++)
{
handle->iface[iface].recfun = NULL;
handle->iface[iface].param = NULL;
}
/* Inicializa semforo. */
handle->mutexsem = CreateSemaphore(NULL, 1, 1, NULL);
if (handle->mutexsem == INVALID_HANDLE_VALUE) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa fsica del modem PLC. */
modplc_release(handle->modplchd);
free(handle);
return NULL;
}
/*

420

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin modphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modphy_release(modphy_hd *hd)
{
/* Variables. */
short int iface;

/* Identificadores de interfaces
fsicas. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Libera el manejador de captura de tramas. */
for(iface = 0; iface < 256; iface ++)
modphy_notify(hd, (unsigned char) (iface & 0x00ff), NULL, NULL);
/* Libera la interfaz con el modem PLC. */
modplc_release(hd->modplchd);
/* Libera los recursos utilizados por la interfaz con la capa fsica del
modem PLC. */
CloseHandle(hd->mutexsem);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modphy_sndframe:
Enva una trama.
*/
size_t modphy_sndframe(modphy_hd *hd, unsigned char iface, const void *frame,
size_t framesize)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Enva una trama. */
framesize = modplc_physndframe(hd->modplchd, iface, frame, framesize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad de bytes envados. */
return framesize;
}
/*
Funcin modphy_capframe:
Captura una trama.
*/
int modphy_capframe(modphy_hd *hd, unsigned char iface, size_t framesize)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);

FernandoArielBeunza79156

421

Tesis de Grado en Ingeniera Informtica


/* Captura una trama. */
result = modplc_phycapframe(hd->modplchd, iface, framesize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la solicitud de captura de una trama. */
return result;
}
/*
Funcin modphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modphy_getframe(modphy_hd *hd, unsigned char iface, void *frame,
size_t framesize)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene una trama capturada previamente. */
framesize = modplc_phygetframe(hd->modplchd, iface, frame, framesize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad de bytes recibidos. */
return framesize;
}
/*
Funcin modphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
int modphy_notify(modphy_hd *hd, unsigned char iface,
void (*func)(modphy_hd *, void *), void *param)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->iface[iface].recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->iface[iface].recfun))
{
WaitForSingleObject(hd->mutexsem, INFINITE);
hd->iface[iface].recfun = func;
hd->iface[iface].param = param;
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora definida
previamente se elimina esta ltima. */
if ((!func) && (hd->iface[iface].recfun))
{
WaitForSingleObject(hd->mutexsem, INFINITE);
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = param;
ReleaseSemaphore(hd->mutexsem, 1, NULL);
WaitForSingleObject(hd->iface[iface].detectthread, INFINITE);
return 1;
}

422

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->iface[iface].recfun))
{
WaitForSingleObject(hd->mutexsem, INFINITE);
hd->iface[iface].recfun = func;
hd->iface[iface].param = param;
hd->iface[iface].detectthread =
CreateThread(NULL, 0, __modphy_detectproc__, hd, 0,
&(hd->iface[iface].threadid));
if (hd->iface[iface].detectthread == INVALID_HANDLE_VALUE)
{
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = NULL;
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 0;
}
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 1;
}
/* No se pudo definir la funcin manejadora de tramas capturadas. */
return 0;
}
/*
Funcin modphy_poll:
Verifica la captura de una trama.
*/
int modphy_poll(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Verifica la captura de una trama. */
result = modplc_phypoll(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la verificacin de la captura de una trama. */
return result;
}
/*
Funcin modphy_rsdframe:
Reenva una trama.
*/
int modphy_rsdframe(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Reenva una trama. */

FernandoArielBeunza79156

423

Tesis de Grado en Ingeniera Informtica


result = modplc_phyrsdframe(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del reenvo de una trama. */
return result;
}
/*
Funcin modphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modphy_clrbuffer(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Limpia el buffer de captura de tramas. */
result = modplc_phyclrbuffer(hd->modplchd, iface);
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la limpieza del buffer de captura de tramas. */
return result;
}
/*
Funcin modphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int modphy_sensechannel(modphy_hd *hd, unsigned char iface,
unsigned char level, long int waittime)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Sensa el estado del canal de comunicacin. */
result = modplc_physensechannel(hd->modplchd, iface, level, waittime);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del sensado del canal de comunicacin. */
return result;
}
/*
Funcin modphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modphy_gensignal(modphy_hd *hd, unsigned char iface, int sig)
{
/* Variables. */

424

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Genera la seal especificada. */
result = modplc_phygensignal(hd->modplchd, iface, sig);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la generacin de la seal. */
return result;
}
/*
Funcin modphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modphy_tstreceive(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Realiza una prueba de recepcin. */
result = modplc_phytstreceive(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado de la prueba de recepcin. */
return result;
}
/*
Funcin modphy_status:
Devuelve el estado del modem PLC.
*/
int modphy_status(modphy_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene el estado del modem PLC. */
result = modplc_status(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve el resultado del modem PLC. */

FernandoArielBeunza79156

425

Tesis de Grado en Ingeniera Informtica


return result;
}
/*
Funcin modphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modphy_getpayloadsize(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener una trama. */

/* Verifica que el manejador de interfaz con la capa fsica del modem PLC
exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Obtiene la cantidad mxima de bytes que puede contener una trama. */
payloadsize = modplc_phygetpayloadsize(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Devuelve la cantidad mxima de bytes que puede contener una trama. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modphy_detectproc__:
Verifica la existencia de una trama capturada disponible para ser leda.
*/
static DWORD WINAPI __modphy_detectproc__(LPVOID param)
{
/* Variables. */
int captureflag;
short int i;
unsigned char iface;
modphy_hd *hd;
void (*func)(void *, void *);

/* Indicador de captura de una


trama. */
/* Contador. */
/* Identificadores de interfaces
fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Manejador de captura de
tramas. */

/* Carga el manejador de interfaz con la capa fsica del modem PLC. */


hd = (modphy_hd *) param;
/* Obtiene el identificador de interface fsica asociado al hilo de
deteccin de recepcin. */
iface = 0;
WaitForSingleObject(hd->mutexsem, INFINITE);
for(i = 0; i < 256; i++)
{
if (hd->iface[i].threadid != GetCurrentThreadId()) continue;
iface = (unsigned char) (i & 0x00ff);
break;
}
ReleaseSemaphore(hd->mutexsem, 1, NULL);
if (i > 255) return 0;
/* Verifica la existencia de una trama capturada. */
while(1)

426

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
WaitForSingleObject(hd->mutexsem, INFINITE);
/* Verifica la captura de una trama. */
func = hd->iface[iface].recfun;
if (!func) break;
captureflag = modplc_phypoll(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
/* Verifica si se ha detectado la captura de una trama para invocar al
manejador de trama capturadas. */
if (captureflag) func(hd, hd->iface[iface].param);
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
ReleaseSemaphore(hd->mutexsem, 1, NULL);
return 0;
}

C.3.4.12. Archivo modrv.h


/*
moddrv.h:
Declaracin de funciones referentes al driver del modem PLC.
*/

#if !defined(__MODDRV_H__)
#define __MODDRV_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modphy.h"
#include "moddl.h"
#include "modsp.h"

/* Definicin de tipos. */
/* Estructura del manejador del driver del modem PLC. */
typedef struct
{
int port;
int layer;
int debugmode;
int stopflag;

/*
/*
/*
/*

unsigned long int clients;


modsp_hd *sphd;

/*
/*

moddl_hd *dlhd;

/*

modphy_hd *phyhd;

/*

Identificador de puerto. */
Capa del modem PLC utilizada. */
Indicador de modo depuracin. */
Indicador de detencin de
ejecucin del driver del modem
PLC. */
Cantidad de clientes activos. */
Manejador de interfaz con la
capa de sesin del modem PLC. */
Manejador de interfaz con la
capa de enlace del modem PLC. */
Manejador de interfaz con la
capa fsica del modem PLC. */

} moddrv_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin moddrv_init:

FernandoArielBeunza79156

427

Tesis de Grado en Ingeniera Informtica


Inicializa los recursos utilizados por el driver del modem PLC.
*/
moddrv_hd *moddrv_init(int, int);
/*
Funcin moddrv_release:
Libera los recursos utilizados por el driver del modem PLC.
*/
int moddrv_release(moddrv_hd *);
/*
Funcin moddrv_run:
Ejecuta el driver del modem PLC.
*/
int moddrv_run(moddrv_hd *);
/*
Funcin moddrv_stop:
Detiene la ejecucin del driver del modem PLC.
*/
int moddrv_stop(moddrv_hd *);

#endif

C.3.4.13. Archivo moddrv.c


/*
moddrv.c:
Implementacin de funciones referentes al driver del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include "modphy.h"
#include "moddl.h"
#include "modsp.h"
#include "moddrv.h"

/* Definicin de tipos. */
/* Estructura de informacin compartida entre hilos de ejecucin. */
typedef struct
{
HANDLE hq;
/* Manejador
mensajes.
HANDLE hm;
/* Manejador
exclusin
moddrv_hd *hd;
/* Manejador
PLC. */
} __moddrv_shareinf__;

de cola de
*/
de semforo de
mutua. */
del driver del modem

/* Declaracin de funciones privadas. */


static DWORD WINAPI __moddrv_clientthread__(LPVOID);
static int __moddrv_phyclient__(moddrv_hd *, HANDLE, HANDLE);
static int __moddrv_dlclient__(moddrv_hd *, HANDLE, HANDLE);
static int __moddrv_spclient__(moddrv_hd *, HANDLE, HANDLE);
static int __moddrv_send__(HANDLE, const void *, size_t);
static int __moddrv_receive__(HANDLE, void *, size_t);

/* Implementacin de funciones pblicas. */


/*

428

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin moddrv_init:
Inicializa los recursos utilizados por el driver del modem PLC.
*/
moddrv_hd *moddrv_init(int sid, int debugmode)
{
/* Variables. */
moddrv_hd *handle;

/* Manejador del driver del modem


PLC. */

/* Crea un nuevo manejador del driver del modem PLC. */


handle = (moddrv_hd *) malloc(sizeof(moddrv_hd));
if (!handle) return NULL;
/* Inicializa el driver del modem PLC. */
handle->port = sid;
handle->layer = 0;
handle->clients = 0;
handle->debugmode = debugmode;
handle->stopflag = 0;
/* Devuelve el manejador creado. */
return handle;
}
/*
Funcin moddrv_release:
Libera los recursos utilizados por el driver del modem PLC.
*/
int moddrv_release(moddrv_hd *hd)
{
/* Verifica que el manejador del driver del modem PLC exista. */
if (!hd) return 0;
/* Libera los recursos utilizados el driver del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin moddrv_run:
Ejecuta el driver del modem PLC.
*/
int moddrv_run(moddrv_hd *hd)
{
/* Variables. */
DWORD tid;
HANDLE hq;
HANDLE hm;
HANDLE cthread;
char qname[256];
__moddrv_shareinf__

sinf;

/* Identificador de hilo. */
/* Manejador de cola de
mensajes. */
/* Manejador de semforo de
exclusin mutua. */
/* Manejador de hilo. */
/* Nombre de la cola de
mensajes. */
/* Informacin compartida. */

/* Verifica que el manejador del driver del modem PLC exista. */


if (!hd) return 0;
/* Inicializa semforo. */
hm = CreateSemaphore(NULL, 1, 1, NULL);
if (hm == INVALID_HANDLE_VALUE) return 0;
/* Procesa las solicitudes de los clientes. */
hd->layer = 0;
hd->clients = 0;
sprintf(qname, "\\\\.\\pipe\\modemplc%i", hd->port);
while(1)

FernandoArielBeunza79156

429

Tesis de Grado en Ingeniera Informtica


{
/* Crea una nueva cola de mensajes. */
hq = CreateNamedPipe(qname, PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE |
PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0,
0, 0);
if (hq == INVALID_HANDLE_VALUE) break;
/* Espera la conexin de un nuevo cliente. */
if (hd->stopflag) break;
ConnectNamedPipe(hq, NULL);
/* Crea un nuevo hilo para atender las solicitudes del nuevo
cliente. */
sinf.hd = hd;
sinf.hq = hq;
sinf.hm = hm;
cthread = CreateThread(NULL, 0, __moddrv_clientthread__, &sinf, 0,
&tid);
if (cthread == INVALID_HANDLE_VALUE) break;
}
/* Fin de ejecucin del driver del modem PLC. */
CloseHandle(hq);
CloseHandle(hm);
return 1;
}
/*
Funcin moddrv_stop:
Detiene la ejecucin del driver del modem PLC.
*/
int moddrv_stop(moddrv_hd *hd)
{
/* Variables. */
HANDLE hq;
int layer;
int result;
char qname[256];

/* Manejador de cola de
mensajes. */
/* Capa que se solicita
utilizar. */
/* Respuesta a la solicitud. */
/* Nombre de la cola de
mensajes. */

/* Verifica que el manejador del driver del modem PLC exista. */


if (!hd) return 0;
/* Abre una conexin con la cola de mensajes del driver del modem PLC. */
sprintf(qname, "\\\\.\\pipe\\modemplc%i", hd->port);
hq = CreateFile(qname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hq == INVALID_HANDLE_VALUE) return 0;
/* Solicita detener la ejecucin del driver del modem PLC. */
layer = 0;
result = 0;
if (__moddrv_send__(hq, &layer, sizeof(layer)))
{
if (__moddrv_receive__(hq, &result, sizeof(result)))
result = 1;
}
if (!result)
{
CloseHandle(hq);
return 0;
}
/* Cierra la conexin con al cola de mensajes del driver del modem PLC. */
CloseHandle(hq);
/* Abre una conexin con la cola de mensajes del driver del modem PLC. */
sprintf(qname, "\\\\.\\pipe\\modemplc%i", hd->port);

430

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


hq = CreateFile(qname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hq == INVALID_HANDLE_VALUE) return 1;
/* Cierra la conexin con al cola de mensajes del driver del modem PLC. */
CloseHandle(hq);
return 1;
}

/* Implementacin de funciones privadas. */


/*
Funcin __moddrv_clientthread__:
Atiene a los clientes del driver del modem PLC.
*/
static DWORD WINAPI __moddrv_clientthread__(LPVOID param)
{
/* Variables. */
HANDLE hq;
HANDLE hm;
int layer;
int result;
moddrv_hd *hd;
__moddrv_shareinf__ *sinf;

/* Manejador de cola de
mensajes. */
/* Manejador de semforo de
exclusin mutua. */
/* Capa que se solicita
utilizar. */
/* Respuesta a la solicitud. */
/* Manejador del driver del modem
PLC. */
/* Informacin compartida. */

/* Carga el manejador de cola de mensajes y el manejador del driver del


modem PLC. */
sinf = (__moddrv_shareinf__ *) param;
hq = sinf->hq;
hd = sinf->hd;
hm = sinf->hm;
/* Espera el permiso para poder acceder a los recursos del driver del modem
PLC. */
WaitForSingleObject(hm, INFINITE);
/* Recibe la capa a la cual el cliente quiere acceder. */
while(!__moddrv_receive__(hq, &layer, sizeof(layer)));
/* Verifica si se solicita detener la ejecucin del driver del modem PLC. */
if (!layer)
{
result = 1;
hd->stopflag = 1;
__moddrv_send__(hq, &result, sizeof(result));
ReleaseSemaphore(hm, 1, NULL);
CloseHandle(hq);
return 0;
}
/* Verifica si es vlida la solicitud. */
result = 0;
if ((layer >= 1) && (layer <= 3))
{
if (!hd->layer) hd->layer = layer;
if (hd->layer == layer) result = 1;
}
/* Verifica si es necesario inicializar alguna interfaz. */
if ((result) && (!hd->clients))
{
/* Inicializa la interfaz de la capa fsica del modem PLC. */
if (layer == 1)
{
hd->phyhd = modphy_init(hd->port, hd->debugmode);

FernandoArielBeunza79156

431

Tesis de Grado en Ingeniera Informtica


if (!hd->phyhd) result = 0;
}
/* Inicializa la interfaz de la capa de enlace del modem PLC. */
else if (layer == 2)
{
hd->dlhd = moddl_init(hd->port, hd->debugmode);
if (!hd->dlhd) result = 0;
}
/* Inicializa la interfaz de la capa de sesin del modem PLC. */
else if (layer == 3)
{
hd->sphd = modsp_init(hd->port, hd->debugmode);
if (!hd->sphd) result = 0;
}
}
/* Enva el resultado de la solicitud. */
__moddrv_send__(hq, &result, sizeof(result));
if (!result)
{
if (!hd->clients) hd->layer = 0;
ReleaseSemaphore(hm, 1, NULL);
CloseHandle(hq);
return 0;
}
/* Agrega un nuevo cliente. */
hd->clients ++;
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
ReleaseSemaphore(hm, 1, NULL);
/* Verifica si el cliente solicit acceder a la capa fsica. */
if (layer == 1)
__moddrv_phyclient__(hd, hq, hm);
/* Verifica si el cliente solicit acceder a la capa de enlace. */
else if (layer == 2)
__moddrv_dlclient__(hd, hq, hm);
/* Verifica si el cliente solicit acceder a la capa de aplicacin. */
else if (layer == 3)
__moddrv_spclient__(hd, hq, hm);
/* Espera el permiso para poder acceder a los recursos del driver del modem
PLC. */
WaitForSingleObject(hm, INFINITE);
/* Elimina un cliente. */
hd->clients --;
/* Verifica si es necesario liberar alguna interfaz. */
if (!hd->clients)
{
/* Libera la interfaz de la capa fsica del modem PLC. */
if (layer == 1)
modphy_release(hd->phyhd);
/* Libera la interfaz de la capa de enlace del modem PLC. */
else if (layer == 2)
moddl_release(hd->dlhd);
/* Libera la interfaz de la capa de sesin del modem PLC. */
else if (layer == 3)
modsp_release(hd->sphd);
/* No se esta utilizando ninguna capa. */
hd->layer = 0;
}
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
ReleaseSemaphore(hm, 1, NULL);

432

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Fin de ejecucin del hilo de deteccin de recepcin. */
CloseHandle(hq);
return 0;
}
/*
Funcin __moddrv_phyclient__:
Procesa las solicitudes de los clientes destinadas a la capa fsica del
modem PLC.
*/
static int __moddrv_phyclient__(moddrv_hd *hd, HANDLE hq, HANDLE hm)
{
/* Variables. */
int op;
/* Cdigo de operacin. */
int sig;
/* Tipo de seal. */
int result;
/* Respuesta a la solicitud. */
size_t size;
/* Cantidad de bytes. */
unsigned char iface;
/* Identificador de interfaz
fsica. */
unsigned char level;
/* Nivel de seal. */
long int waittime;
/* Tiempo de espera. */
unsigned char *frame;
/* Puntero a la trama recibida. */

/* Procesa solicitudes destinadas a la capa fsica del modem PLC. */


while(!hd->stopflag)
{
/* Recibe el cdigo de operacin. */
if (!__moddrv_receive__(hq, &op, sizeof(op))) continue;
/* Espera el permiso para poder acceder a los recursos del driver del
modem PLC. */
WaitForSingleObject(hm, INFINITE);
/* Solicita terminar la conexin. */
if (op == MODDRVPHY_RELEASE)
{
result = 1;
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
break;
}
/* Solicita el envo de una trama. */
else if (op == MODDRVPHY_SNDFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el tramao de la trama. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Recibe la trama. */
frame = (unsigned char *) malloc(size * sizeof(unsigned char));
if (!frame) continue;
if (!__moddrv_receive__(hq, frame, size))
{
free(frame);
continue;
}
/* Enva la trama. */
size = modphy_sndframe(hd->phyhd, iface, frame, size);
free(frame);
/* Enva la cantidad de bytes enviados. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicita la captura de una trama. */
else if (op == MODDRVPHY_CAPFRAME)
{
/* Recibe el identificador de interfaz fsica. */

FernandoArielBeunza79156

433

Tesis de Grado en Ingeniera Informtica


if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el tramao de la trama. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Catura una trama. */
result = modphy_capframe(hd->phyhd, iface, size);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la lectura de una trama capturada. */
else if (op == MODDRVPHY_GETFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el tamao de la trama. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Catura una trama. */
frame = (unsigned char *) malloc(size * sizeof(unsigned char));
if (!frame) continue;
size = modphy_getframe(hd->phyhd, iface, frame, size);
/* Enva la trama leda. */
if (!__moddrv_send__(hq, frame, size))
{
free(frame);
continue;
}
free(frame);
/* Enva la cantidad de bytes ledos. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicita la verificacin de la captura de una trama. */
else if (op == MODDRVPHY_POLL)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Verifica de la captura de una trama. */
result = modphy_poll(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita el reenvo de una trama. */
else if (op == MODDRVPHY_RSDFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Reenva una trama. */
result = modphy_rsdframe(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la limpieza del buffer de captura de tramas. */
else if (op == MODDRVPHY_CLRBUFFER)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Limpia el buffer de captura de tramas. */
result = modphy_clrbuffer(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;

434

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Solicita el sensado del canal de comunicacin. */
else if (op == MODDRVPHY_SENSECHANNEL)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el nivel de seal. */
if (!__moddrv_receive__(hq, &level, sizeof(level))) continue;
/* Recibe el tiempo de espera. */
if (!__moddrv_receive__(hq, &waittime, sizeof(waittime))) continue;
/* Sensa el estado del canal de comunicacin. */
result = modphy_sensechannel(hd->phyhd, iface, level, waittime);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la generacin de una seal. */
else if (op == MODDRVPHY_GENSIGNAL)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el tipo de seal. */
if (!__moddrv_receive__(hq, &sig, sizeof(sig))) continue;
/* Genera la seal solicitada. */
result = modphy_gensignal(hd->phyhd, iface, sig);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita realizar una prueba de recepcin. */
else if (op == MODDRVPHY_TSTRECEIVE)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Realiza la prueba de recepcin. */
result = modphy_tstreceive(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita verifica el estado del modem PLC. */
else if (op == MODDRVPHY_STATUS)
{
/* Verifica el estado del modem PLC. */
result = modphy_status(hd->phyhd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la cantidad mxima de bytes que puede contener una
trama. */
else if (op == MODDRVPHY_GETPAYLOADSIZE)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Obtiene la cantidad mxima de bytes que puede contener una
trama. */
size = modphy_getpayloadsize(hd->phyhd, iface);
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicitud desconocida. */
else
{
result = 0;

FernandoArielBeunza79156

435

Tesis de Grado en Ingeniera Informtica


if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
ReleaseSemaphore(hm, 1, NULL);
}
ReleaseSemaphore(hm, 1, NULL);
return 0;
}
/*
Funcin __moddrv_dlclient__:
Procesa las solicitudes de los clientes destinadas a la capa de enlace del
modem PLC.
*/
static int __moddrv_dlclient__(moddrv_hd *hd, HANDLE hq, HANDLE hm)
{
/* Variables. */
int op;
/* Cdigo de operacin. */
int result;
/* Respuesta a la solicitud. */
unsigned char prot;
/* Identificador de protocolo. */
unsigned char prio;
/* Prioridad del mensaje. */
unsigned char iface;
/* Identificador de interfaz
fsica. */
size_t size;
/* Cantidad de bytes. */
moddlconn_hd *dlconnhd;
/* Manejador de conexin por medio
de la capa de enlace del modem
PLC. */
moddl_logaddr laddr;
/* Direccin lgica. */
moddl_phyaddr paddr;
/* Direccin fsica. */
unsigned char *msg;
/* Puntero al mensaje recibido. */

/* Procesa solicitudes destinadas a la capa de enlace del modem PLC. */


dlconnhd = NULL;
while(!hd->stopflag)
{
/* Recibe el cdigo de operacin. */
if (!__moddrv_receive__(hq, &op, sizeof(op))) continue;
/* Espera el permiso para poder acceder a los recursos del driver del
modem PLC. */
WaitForSingleObject(hm, INFINITE);
/* Solicita cerrar la conexin. */
if (op == MODDRVDL_CLOSE)
{
result = 0;
if (moddl_close(dlconnhd)) result = 1;
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
break;
}
/* Solicita abrir la conexin. */
else if (op == MODDRVDL_OPEN)
{
/* Abre la conexin si no fue abierta anteriormente. */
result = 0;
if (!dlconnhd)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot))) continue;
/* Abre la conexin. */
dlconnhd = moddl_open(hd->dlhd, iface, prot);
if (dlconnhd) result = 1;
}

436

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Devuelve el resultado de la operacin. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita enviar un mensaje. */
else if (op == MODDRVDL_SEND)
{
/* Enva un mensaje. */
size = 0;
if (dlconnhd)
{
/* Recibe la direccin destinataria. */
if (!__moddrv_receive__(hq, paddr, sizeof(paddr))) continue;
/* Recibe la prioridad del mensaje. */
if (!__moddrv_receive__(hq, &prio, sizeof(prio))) continue;
/* Recibe el tamao del mensaje. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Recibe el mensaje. */
msg = (unsigned char *) malloc(size * sizeof(unsigned char));
if (!msg) continue;
if (!__moddrv_receive__(hq, msg, size))
{
free(msg);
continue;
}
/* Enva el mensaje. */
size = moddl_send(dlconnhd, paddr, prio, msg, size);
free(msg);
}
/* Devuelve la cantidad de bytes enviados. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicita recibir un mensaje. */
else if (op == MODDRVDL_RECEIVE)
{
/* Recibe un mensaje. */
size = 0;
msg = NULL;
if (dlconnhd)
{
/* Recibe el tamao del mensaje. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Recibe el mensaje. */
msg = (unsigned char *) malloc(size * sizeof(unsigned char));
if (!msg) continue;
size = moddl_receive(dlconnhd, paddr, msg, size);
}
/* Devuelve la cantidad de bytes recibidos. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
{
if (msg) free(msg);
continue;
}
if (!size)
{
free(msg);
continue;
}
/* Enva la direccin de origen del mensaje. */
if (!__moddrv_send__(hq, paddr, sizeof(paddr)))
{
free(msg);
continue;
}

FernandoArielBeunza79156

437

Tesis de Grado en Ingeniera Informtica


/* Enva la direccin de origen del mensaje. */
if (!__moddrv_send__(hq, msg, size))
{
free(msg);
continue;
}
free(msg);
}
/* Solicita la verificacin de un mensaje. */
else if (op == MODDRVDL_POLL)
{
/* Verifica de la recepcin de un mensaje. */
result = 0;
if (dlconnhd) result = moddl_poll(dlconnhd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la direccin fsica del modem PLC. */
else if (op == MODDRVDL_GETADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Obtiene la direccin fsica. */
result = moddl_getaddress(hd->dlhd, iface, paddr);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
if (!result) continue;
/* Enva la direccin fsica solicitada. */
if (!__moddrv_send__(hq, paddr, sizeof(paddr))) continue;
}
/* Solicita agregar una nueva direccin lgica. */
else if (op == MODDRVDL_ADDLOGADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot))) continue;
/* Recibe la direccin lgica. */
if (!__moddrv_receive__(hq, &laddr, sizeof(laddr))) continue;
/* Agrega la direccin lgica. */
result = moddl_addlogaddress(hd->dlhd, iface, prot, laddr);
/* Devuelve el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita eliminar una direccin lgica. */
else if (op == MODDRVDL_DELLOGADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot))) continue;
/* Recibe la direccin lgica. */
if (!__moddrv_receive__(hq, &laddr, sizeof(laddr))) continue;
/* Elimina la direccin lgica. */
result = moddl_dellogaddress(hd->dlhd, iface, prot, laddr);
/* Devuelve el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}

438

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Solicita obtener la direccin fsica asociada a la direccin
lgica. */
else if (op == MODDRVDL_GETPHYADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot))) continue;
/* Recibe la direccin lgica. */
if (!__moddrv_receive__(hq, &laddr, sizeof(laddr))) continue;
/* Obtiene la direccin lgica. */
result = moddl_getphyaddress(hd->dlhd, iface, prot, laddr, paddr);
/* Devuelve el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
if (!result) continue;
/* Enva la direccin fsica. */
if (!__moddrv_send__(hq, paddr, sizeof(paddr))) continue;
}
/* Solicita verifica el estado del modem PLC. */
else if (op == MODDRVDL_STATUS)
{
/* Verifica el estado del modem PLC. */
result = moddl_status(hd->dlhd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
else if (op == MODDRVDL_GETPAYLOADSIZE)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface))) continue;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
size = moddl_getpayloadsize(hd->dlhd, iface);
/* Devuelve la cantidad mxima de bytes que puede contener un
mensaje. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicitud desconocida. */
else
{
result = 0;
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
ReleaseSemaphore(hm, 1, NULL);
}
ReleaseSemaphore(hm, 1, NULL);
return 0;
}
/*
Funcin __moddrv_spclient__:
Procesa las solicitudes de los clientes destinadas a la capa de sesin del
modem PLC.
*/
static int __moddrv_spclient__(moddrv_hd *hd, HANDLE hq, HANDLE hm)
{
/* Variables. */
int op;
/* Cdigo de operacin. */

FernandoArielBeunza79156

439

Tesis de Grado en Ingeniera Informtica


int result;
size_t size;
modsp_grpid grpid;
unsigned char nosec;
unsigned char *msg;

/*
/*
/*
/*

Respuesta a la solicitud. */
Cantidad de bytes. */
Identificador de grupo. */
Indicador de mensaje fuera de
secuencia. */
/* Puntero al mensaje recibido. */

/* Procesa solicitudes destinadas a la capa de aplicacin del modem PLC. */


while(!hd->stopflag)
{
/* Recibe el cdigo de operacin. */
if (!__moddrv_receive__(hq, &op, sizeof(op))) continue;
/* Espera el permiso para poder acceder a los recursos del driver del
modem PLC. */
WaitForSingleObject(hm, INFINITE);
/* Solicita terminar la conexin. */
if (op == MODDRVSP_RELEASE)
{
result = 1;
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
break;
}
/* Solicita el registro del dispositivo como publicador. */
else if (op == MODDRVSP_PUBLISH)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid))) continue;
/* Registra el dispositivo como publicador. */
result = modsp_publish(hd->sphd, grpid);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita el registro del dispositivo como suscriptor. */
else if (op == MODDRVSP_SUBSCRIBE)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid))) continue;
/* Registra el dispositivo como suscriptor. */
result = modsp_subscribe(hd->sphd, grpid);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la desvinculacin del dispositivo a un grupo de
difusin. */
else if (op == MODDRVSP_LEAVE)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid))) continue;
/* Desvincula el dispositivo de un grupo de difusin. */
result = modsp_leave(hd->sphd, grpid);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita el envo de un mensaje. */
else if (op == MODDRVSP_SEND)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid))) continue;
/* Recibe el indicador de mensaje fuera de secuencia. */
if (!__moddrv_receive__(hq, &nosec, sizeof(nosec))) continue;

440

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Recibe el tamao del mensaje. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Enva el mensaje solicitado. */
while(1)
{
/* Recibe el mensaje. */
msg = (unsigned char *) malloc(size * sizeof(unsigned char));
if (!msg)
{
size = 0;
break;
}
if (!__moddrv_receive__(hq, msg, size))
{
size = 0;
break;
}
/* Enva el mensaje. */
size = modsp_send(hd->sphd, grpid, nosec, msg, size);
break;
}
/* Enva la cantidad de bytes enviados. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicita la recepcin de un mensaje. */
else if (op == MODDRVSP_RECEIVE)
{
/* Recibe la cantidad de bytes que se desea recibir del mensaje. */
if (!__moddrv_receive__(hq, &size, sizeof(size))) continue;
/* Recibe el mensaje. */
msg = (unsigned char *) malloc(size * sizeof(unsigned char));
if (msg)
size = modsp_receive(hd->sphd, &grpid, msg, size);
else
size = 0;
/* Enva la cantidad de bytes recibidos. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
if (!size) continue;
/* Enva el indentificador del grupo de difusin por el cual se
recibi el mensaje. */
if (!__moddrv_send__(hq, &grpid, sizeof(grpid)))
{
free(msg);
continue;
}
/* Enva el mensaje recibido. */
if (!__moddrv_send__(hq, msg, size))
{
free(msg);
continue;
}
free(msg);
}
/* Solicita la verificacin de la recepcin de un mensaje. */
else if (op == MODDRVSP_POLL)
{
/* Verifica de la recepcin de un mensaje. */
result = modsp_poll(hd->sphd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita verifica el estado del modem PLC. */
else if (op == MODDRVSP_STATUS)

FernandoArielBeunza79156

441

Tesis de Grado en Ingeniera Informtica


{
/* Verifica el estado del modem PLC. */
result = modsp_status(hd->sphd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
else if (op == MODDRVSP_GETPAYLOADSIZE)
{
size = modsp_getpayloadsize(hd->sphd);
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicitud desconocida. */
else
{
result = 0;
if (!__moddrv_send__(hq, &result, sizeof(result))) continue;
}
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
ReleaseSemaphore(hm, 1, NULL);
}
ReleaseSemaphore(hm, 1, NULL);
return 0;
}
/*
Funcin __moddrv_send__:
Enva datos por medio de la cola de mensajes.
*/
static int __moddrv_send__(HANDLE hq, const void *stream, size_t size)
{
/* Variables. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t lastsent;
/* Cantidad de bytes enviados en el
ltimo envo. */
/* Enva los datos. */
sent = 0;
while((stream) && (sent < size))
{
if (!WriteFile(hq, stream, size, &lastsent, NULL)) return 0;
sent += lastsent;
}
return 1;
}
/*
Funcin __moddrv_receive__:
Enva datos por medio de la cola de mensajes.
*/
static int __moddrv_receive__(HANDLE hq, void *stream, size_t size)
{
/* Variables. */
size_t received;
/* Cantidad de bytes recibidos. */
size_t lastreceive;
/* Cantidad de bytes recibidos en
la ltima recepcin. */
/* Enva los datos. */
received = 0;
while((stream) && (received < size))
{
if (!ReadFile(hq, stream, size, &lastreceive, NULL)) return 0;
received += lastreceive;
}
return 1;
}

442

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.3.4.14. Archivo modem_driver.c


/*
modplc_driver.c:
Implementacin de funcin principal del driver del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include "moddrv.h"

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port;
int debug;
moddrv_hd *hd;
char *option;

/* Puerto serie utilizado. */


/* Modo depuracin. */
/* Manejador del driver del modem
PLC. */
/* Opcin especificada. */

/* Carga los parmentros */


if (argc < 3) return -1;
port = atoi(argv[1]);
debug = 0;
if (argc > 3)
{
option = strlwr(strdup(argv[3]));
if (!strcmp(option, "debug")) debug = 1;
}
option = strlwr(strdup(argv[2]));
/* Inicializa el driver del modem PLC. */
hd = moddrv_init(port, debug);
if (!hd) return 0;
/* Evala la opcin solicitada. */
while(1)
{
/* Activa el driver. */
if (!strcmp(option, "start"))
moddrv_run(hd);
/* Desactiva el driver. */
else if (!strcmp(option, "stop"))
moddrv_stop(hd);
break;
}
/* Libera los recursos del driver del modem PLC. */
moddrv_release(hd);
return 0;
}

FernandoArielBeunza79156

443

Tesis de Grado en Ingeniera Informtica

C.4. Especificacin del cdigo fuente de las


bibliotecas de uso del modem PLC (plataforma
Linux)
El cdigo fuente que conforma las bibliotecas de uso del modem PLC, se encuentra
organizado en los siguientes componentes:

Interfaz capa de aplicacin.

Intefaz capa de enlace.

Interfaz capa fsica.

Driver del modem PLC.

C.4.1. Interfaz capa de aplicacin modplcap.so


En esta seccin se detalla el cdigo fuente de la biblioteca que implementa la capa de
aplicacin del modem PLC, que se compone de los siguientes archivos:

444

Archivo config.h: en este archivo se definen parmetros de configuracin de la biblioteca


dinmica que implementa la capa de aplicacin del modem PLC que no pueden ser
modificados en tiempo de ejecucin.

Archivo modplcap.h: en este archivo se declaran primitivas con funcionalidades


referentes a la capa de aplicacin del modem PLC.

Archivo modplcap.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcap.h.

Archivo modplcpp.h: en este archivo se declaran las primitivas correspondientes al


manejo de la capa de presentacin. Dichas primitivas brindan la capacidad de trabajar con
estructuras de datos independientes de la plataforma.

Archivo modplcpp.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcpp.h.

Archivo modplcsp.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa de sesin. Dichas primitivas brindan un conjunto de funcionalidades
que permiten la comunicacin con la capa de sesin implementada en el modem PLC por
medio del driver del mismo.

Archivo modplcsp.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcsp.h.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.4.1.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz con el driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa de sesin. */
#define MODDRVSP_RELEASE
0x00
#define MODDRVSP_PUBLISH
0x01
#define MODDRVSP_SUBSCRIBE
0x02
#define MODDRVSP_LEAVE
0x03
#define MODDRVSP_SEND
0x04
#define MODDRVSP_RECEIVE
0x05
#define MODDRVSP_POLL
0x06
#define MODDRVSP_STATUS
0x07
#define MODDRVSP_GETPAYLOADSIZE
0x08

#endif

C.4.1.2. Archivo modplcsp.h


/*
modplcsp.h:
Declaracin de funciones referentes a la interfaz de la capa de sesin
del modem PLC.
*/

#if !defined(__MODPLCSP_H__)
#define __MODPLCSP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <pthread.h>

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcsp_grpid;
/* Manejador de interfaz con la capa de sesin del modem PLC. */
typedef struct
{
int hq;
/* Manejador de cola de
mensajes. */
pthread_mutex_t hm;
/* Semforo de exclusin mtua. */
pthread_t detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
void (*recfun)
(void *, modplcsp_grpid,
void *, size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes

FernandoArielBeunza79156

445

Tesis de Grado en Ingeniera Informtica


recibidos. */
} modplcsp_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin modplcsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modplcsp_hd *modplcsp_init(int);
/*
Funcin modplcsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modplcsp_release(modplcsp_hd *);
/*
Funcin modplcsp_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modplcsp_publish(modplcsp_hd *, modplcsp_grpid);
/*
Funcin modplcsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modplcsp_subscribe(modplcsp_hd *, modplcsp_grpid);
/*
Funcin modplcsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcsp_leave(modplcsp_hd *, modplcsp_grpid);
/*
Funcin modplcsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_send(modplcsp_hd *, modplcsp_grpid, unsigned char,
const void *, size_t);
/*
Funcin modplcsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_receive(modplcsp_hd *, modplcsp_grpid *, void *, size_t);
/*
Funcin modplcsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcsp_notify(modplcsp_hd *, void (*func)(modplcsp_hd *, modplcsp_grpid,
void *, size_t, void *), void *);
/*
Funcin modplcsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcsp_poll(modplcsp_hd *);
/*
Funcin modplcsp_status:
Devuelve el estado del modem PLC.
*/
int modplcsp_status(modplcsp_hd *);
/*

446

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin modplcsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de sesin del modem PLC.
*/
size_t modplcsp_getpayloadsize(modplcsp_hd *);

#endif

C.4.1.3. Archivo modplcsp.c


/*
modplcsp.c:
Implementacin de funciones referentes a la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include "modplcsp.h"

/* Declaracin de funciones privadas. */


static void *__modplcsp_detectproc__(void *);
static int __modplcsp_sendrecv__(int, void *, size_t, const void *, size_t);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modplcsp_hd *modplcsp_init(int sid)
{
/* Variables. */
int op;
int layer;
int result;
size_t payloadsize;
modplcsp_hd *handle;
struct sockaddr_un servaddr;

/* Identificador de operacion. */
/* Capa a la que se quiere
accerder. */
/* Resultado de la solicitud. */
/* Cantidad mxima de bytes que
puede contener un mensaje. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */
/* Direccin del servidor. */

/* Crea un nuevo manejador de interfaz con la capa de sesin del modem


PLC. */
handle = (modplcsp_hd *) malloc(sizeof(modplcsp_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de sesin del modem
PLC. */
while(1)
{
/* Abre una conexin con la cola de mensajes del driver del
modem PLC. */
handle->hq = socket(AF_LOCAL, SOCK_STREAM, 0);

FernandoArielBeunza79156

447

Tesis de Grado en Ingeniera Informtica


if (handle->hq < 0) break;
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
sprintf(servaddr.sun_path, "/tmp/modemplc%i.str", sid);
if (connect(handle->hq, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0)
break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Inicializa semforo de exclusin mtua. */
if (pthread_mutex_init(&(handle->hm), NULL)) break;
if (pthread_mutex_unlock(&(handle->hm))) break;
/* Solicita acceder a la capa de sesin del modem PLC. */
layer = 3;
if (!__modplcsp_sendrecv__(handle->hq, &result, sizeof(result),
&layer, sizeof(layer)))
break;
if (!result) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
op = MODDRVSP_GETPAYLOADSIZE;
if (!__modplcsp_sendrecv__(handle->hq, &payloadsize,
sizeof(payloadsize), &op, sizeof(op)))
break;
if (!payloadsize) break;
handle->payloadsize = payloadsize;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa sesin del modem
PLC. */
pthread_mutex_destroy(&(handle->hm));
close(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modplcsp_release(modplcsp_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del modem


PLC exista. */
if (!hd) return 0;
/* Libera la funcin manejadora de mensajes recibidos. */
modplcsp_notify(hd, NULL, NULL);
/* Solicita la finalizacin del acceso a la capa de sesin del modem
PLC. */
op = MODDRVSP_RELEASE;
if (!__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Libera los recursos utilizados por el semforo de exclusin mtua. */

448

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (pthread_mutex_destroy(&(hd->hm))) return 0;
/* Libera los recursos utilizados por la interfaz con la capa de sesin
del modem PLC. */
close(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcsp_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modplcsp_publish(modplcsp_hd *hd, modplcsp_grpid grpid)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Solicita el registro del dispositivo como publicador. */
result = 0;
while(1)
{
/* Solicita el registro del dispositivo. */
op = MODDRVSP_PUBLISH;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de grupo. */
__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &grpid,
sizeof(grpid));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modplcsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modplcsp_subscribe(modplcsp_hd *hd, modplcsp_grpid grpid)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem

FernandoArielBeunza79156

449

Tesis de Grado en Ingeniera Informtica


PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Solicita el registro del dispositivo como suscriptor. */
result = 0;
while(1)
{
/* Solicita el registro del dispositivo. */
op = MODDRVSP_SUBSCRIBE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de grupo. */
__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &grpid,
sizeof(grpid));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modplcsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcsp_leave(modplcsp_hd *hd, modplcsp_grpid grpid)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Solicita desvincular el dispositivo de un grupo de difusin. */
result = 0;
while(1)
{
/* Solicita desvincular el dispositivo. */
op = MODDRVSP_LEAVE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de grupo. */
__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &grpid,
sizeof(grpid));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la desvinculacin del dispositivo. */
return result;
}
/*
Funcin modplcsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.

450

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/
size_t modplcsp_send(modplcsp_hd *hd, modplcsp_grpid grpid,
unsigned char nosec, const void *msg, size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Enva un mensaje. */
while(1)
{
/* Solicita el envo de un mensaje. */
op = MODDRVSP_SEND;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de grupo. */
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &grpid,
sizeof(grpid)))
break;
/* Enva el identificador de mensaje fuera de secuencia. */
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &nosec,
sizeof(nosec)))
break;
/* Enva el tamao del mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &msgsize,
sizeof(msgsize)))
break;
/* Enva el mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &msgsize, sizeof(msgsize),
msg, msgsize))
break;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->hm))) break;
/* Devuelve la cantidad de bytes enviados. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
pthread_mutex_unlock(&(hd->hm));
/* No se pudo realizar el envo. */
return 0;
}
/*
Funcin modplcsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplcsp_receive(modplcsp_hd *hd, modplcsp_grpid *grpid, void *msg,
size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

FernandoArielBeunza79156

451

Tesis de Grado en Ingeniera Informtica


/* Verifica que el manejador de interfaz con la capa de sesin del
modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene un mensaje recibido. */
while(1)
{
/* Solicita recibir un mensaje. */
op = MODDRVSP_RECEIVE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva la cantidad de bytes que se quieren recibir del
mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &msgsize, sizeof(msgsize),
&msgsize, sizeof(msgsize)))
break;
if (!msgsize) break;
/* Obtiene el identificador de grupo por el cual se recibi el
mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &grpid, sizeof(grpid), NULL,
0))
break;
/* Recibe el mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, msg, msgsize, NULL, 0))
break;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->hm))) break;
/* Devuelve la cantidad de bytes ledos. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
pthread_mutex_unlock(&(hd->hm));
/* No se pudo recibir el mensaje. */
return 0;
}
/*
Funcin modplcsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcsp_notify(modplcsp_hd *hd, void (*func)(modplcsp_hd *,
modplcsp_grpid, void *, size_t, void *), void *param)
{
/* Verifica que el manejador de interfaz con la capa de sesin del
modem PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->hm))) return 0;
hd->recfun = (void (*)(void *, modplcsp_grpid, void *, size_t,
void *)) func;

452

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


hd->param = param;
if (pthread_mutex_unlock(&(hd->hm))) return 0;
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora
definida previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->hm))) return 0;
hd->recfun = NULL;
hd->param = param;
if (pthread_mutex_unlock(&(hd->hm))) return 0;
if (pthread_join(hd->detectthread, NULL)) return 0;
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
if (pthread_mutex_lock(&(hd->hm))) return 0;
hd->recfun = (void (*)(void *, modplcsp_grpid, void *, size_t,
void *)) func;
hd->param = param;
if (pthread_create(&(hd->detectthread), NULL,
__modplcsp_detectproc__, hd))
{
hd->recfun = NULL;
hd->param = NULL;
pthread_mutex_unlock(&(hd->hm));
return 0;
}
if (pthread_mutex_unlock(&(hd->hm))) return 0;
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modplcsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcsp_poll(modplcsp_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Solicita verificar la recepcin de un mensaje. */
op = MODDRVSP_POLL;
if (!__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;

FernandoArielBeunza79156

453

Tesis de Grado en Ingeniera Informtica


/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcsp_status:
Devuelve el estado del modem PLC.
*/
int modplcsp_status(modplcsp_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene el estado del modem PLC. */
op = MODDRVSP_STATUS;
if (!__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el estado del modem PLC. */
return result;
}
/*
Funcin modplcsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de sesin del modem PLC.
*/
size_t modplcsp_getpayloadsize(modplcsp_hd *hd)
{
/* Variables. */
int op;
size_t payloadsize;

/* Identificador de operacin. */
/* Cantidad de bytes que puede
contener un mensaje. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene la cantidad mxima de bytes que puede contener un mensaje. */
op = MODDRVSP_GETPAYLOADSIZE;
if (!__modplcsp_sendrecv__(hd->hq, &payloadsize, sizeof(payloadsize),
&op, sizeof(op)))
payloadsize = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener un
mensaje. */
return payloadsize;

454

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Implementacin de funciones privadas. */
/*
Funcin __modplcsp_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser
ledo.
*/
static void *__modplcsp_detectproc__(void *param)
{
/* Variables. */
int op;
int result;
int captureflag;
size_t msgsize;
modplcsp_grpid grpid;
modplcsp_hd *hd;
void (*func)(void *,
modplcsp_grpid, void *,
size_t, void *);
unsigned char *msg;

/* Identificador de operacin. */
/* Resultado de la operacin. */
/* Indicador de recepcin de un
mensaje. */
/* Tamao del mensaje. */
/* Identificador de grupo. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */

/* Funcin manejadora de mensajes


recibidos. */
/* Puntero al mensaje. */

/* Carga el manejador de interfaz con la capa de sesin del modem


PLC. */
hd = (modplcsp_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_lock(&(hd->hm))) continue;
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
op = MODDRVSP_POLL;
if (__modplcsp_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
captureflag = result;
/* Recibe el mensaje. */
while(captureflag)
{
/* Solicita la recepcin de un mensaje. */
op = MODDRVSP_RECEIVE;
if (!__modplcsp_sendrecv__(hd->hq, NULL, 0, &op,
sizeof(op)))
break;
/* Enva la cantidad de bytes que se solicita recibir
del mensaje. */
msgsize = hd->payloadsize;
if (!__modplcsp_sendrecv__(hd->hq, &msgsize,
sizeof(msgsize), &msgsize, sizeof(msgsize)))
break;
if (!msgsize) break;
/* Recibe la direccin de origen del mensaje. */
if (!__modplcsp_sendrecv__(hd->hq, &grpid,
sizeof(grpid), NULL, 0))
break;
/* Recibe el mensaje. */
msg = (unsigned char *)
malloc(msgsize * sizeof(unsigned char));

FernandoArielBeunza79156

455

Tesis de Grado en Ingeniera Informtica


if (!msg)
{
captureflag = 0;
break;
}
__modplcsp_sendrecv__(hd->hq, msg, msgsize, NULL, 0);
break;
}
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
pthread_mutex_unlock(&(hd->hm));
/* Verifica si se ha detectado la recepcin de un mensaje para
invocar a la funcin manejadora de mensajes recibidos. */
if (captureflag)
{
func(hd, grpid, msg, msgsize, hd->param);
free(msg);
captureflag = 0;
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
pthread_mutex_unlock(&(hd->hm));
return 0;
}
/*
Funcin __modplcsp_sendrecv__:
Intercambia datos con el driver del modem PLC.
*/
static int __modplcsp_sendrecv__(int hq, void *outdata, size_t outsize,
const void *indata, size_t insize)
{
/* Variables. */
size_t last;
/* Cantidad de bytes enviados o
recibidos. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Enva la operacin. */
sent = 0;
while((indata) && (sent < insize))
{
last = write(hq, indata + sent, insize - sent);
sent += last;
}
/* Recibe la respuesta. */
received = 0;
while((outdata) && (received < outsize))
{
last = read(hq, outdata + received, outsize - received);
received += last;
}
/* xito. */
return 1;
}

C.4.1.4. Archivo modplcpp.h


/*
modplcpp.h:
Declaracin de funciones referentes a la capa de presentacin del modem
PLC.

456

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/

#if !defined(__MODPLCPP_H__)
#define __MODPLCPP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modplcsp.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcpp_grpid;
/* Tipo de mensaje. */
typedef unsigned char modplcpp_mtype;
/* Tipo de campo. */
typedef unsigned char modplcpp_ftype;
/* Estructura del mensaje. */
typedef struct
{
unsigned short int startoffset;
unsigned short int endoffset;
modplcpp_grpid grpid;
modplcpp_mtype mtype;
void *pphd;
unsigned char *dat;

/*
/*
/*
/*
/*

Comienzo del mensaje. */


Fin del mensaje. */
Identificador de grupo. */
Tipo de mensaje. */
Manejador de capa de
presentacin. */
/* Puntero al contenido del
mensaje. */

} modplcpp_msg;
/* Manejador de capa de presentacin. */
typedef struct
{
size_t payloadsize;
modplcpp_grpid grpid;

modplcsp_hd *modsphd;
void (*recfun)
(void *, modplcpp_msg *,
void *);
void *param;

modplcpp_msg buffer;

/* Cantidad mxima de bytes que


puede contener un mensaje. */
/* Identificador de grupo del
mensaje almacenado en el
buffer. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
/* Puntero al buffer de campos
recibidos. */

} modplcpp_hd;

/* Definicin de constantes. */
/* Tipo de mensaje. */
#define MODPLCPP_SECMSG
#define MODPLCPP_NOSECMSG

0x00
0x01

/* Tipos de datos. */
#define MODPLCPP_NULLTYPE
#define MODPLCPP_CHARTYPE
#define MODPLCPP_SINT8TYPE
#define MODPLCPP_UINT8TYPE
#define MODPLCPP_SINT16TYPE
#define MODPLCPP_UINT16TYPE

0x00
0x01
0x02
0x03
0x04
0x05

FernandoArielBeunza79156

457

Tesis de Grado en Ingeniera Informtica


#define MODPLCPP_SINT32TYPE
#define MODPLCPP_UINT32TYPE
#define MODPLCPP_FLOATTYPE

0x06
0x07
0x08

/* Declaracin de funciones pblicas. */


/*
Funcin modplcpp_init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/
modplcpp_hd *modplcpp_init(int);
/*
Funcin modplcpp_release:
Libera los recursos utilizados por la capa de presentacin del modem
PLC.
*/
int modplcpp_release(modplcpp_hd *);
/*
Funcin modplcpp_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modplcpp_publish(modplcpp_hd *, modplcpp_grpid);
/*
Funcin modplcpp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modplcpp_subscribe(modplcpp_hd *, modplcpp_grpid);
/*
Funcin modplcpp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcpp_leave(modplcpp_hd *, modplcpp_grpid);
/*
Funcin modplcpp_newmsg:
Crea un nuevo mensaje.
*/
int modplcpp_newmsg(modplcpp_hd *, modplcpp_msg *, modplcpp_grpid,
modplcpp_mtype);
/*
Funcin modplcpp_copymsg:
Crea un copia de un mensaje.
*/
int modplcpp_copymsg(modplcpp_msg *, modplcpp_msg *);
/*
Funcin modplcpp_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcpp_putfield(modplcpp_msg *, modplcpp_ftype, unsigned char,
const void *);
/*
Funcin modplcpp_sendmsg:
Enva un mensaje por medio de la capa de presentacin.
*/
int modplcpp_sendmsg(modplcpp_msg *);
/*
Funcin modplcpp_receivemsg:
Recibe un mensaje por medio de la capa de presentacin.
*/

458

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int modplcpp_receivemsg(modplcpp_hd *, modplcpp_msg *);
/*
Funcin modplcpp_getfield:
Extrae un campo del mensaje.
*/
int modplcpp_getfield(modplcpp_msg *, modplcpp_ftype *, unsigned char *,
void *);
/*
Funcin modplcpp_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *);
/*
Funcin modplcpp_destroymsg:
Destruye un mensaje.
*/
int modplcpp_destroymsg(modplcpp_msg *);
/*
Funcin modplcpp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcpp_notify(modplcpp_hd *, void (*func)(modplcpp_hd *, modplcpp_msg *,
void *), void *);
/*
Funcin modplcpp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcpp_poll(modplcpp_hd *);
/*
Funcin modplcpp_status:
Devuelve el estado del modem PLC.
*/
int modplcpp_status(modplcpp_hd *);

#endif

C.4.1.5. Archivo modplcpp.c


/*
modplcpp.c:
Implementacin de funciones referentes a la capa de presentacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "modplcsp.h"
#include "modplcpp.h"

/* Declaracin de funciones privadas. */


static void __modplcpp_procmsg__(modplcsp_hd *, modplcsp_grpid, void *, size_t,
void *);

/* Implementacin de funciones pblicas. */


/*

FernandoArielBeunza79156

459

Tesis de Grado en Ingeniera Informtica


Funcin modplcpp_init:
Inicializa los recursos utilizado por la capa de presentacin del modem
PLC.
*/
modplcpp_hd *modplcpp_init(int sid)
{
/* Variables. */
modplcpp_hd *handle;

/* Manejador de capa de
presentacin. */

/* Crea un nuevo manejador de capa de presentacin. */


handle = (modplcpp_hd *) malloc(sizeof(modplcpp_hd));
if (!handle) return NULL;
/* Inicializa el manejador de capa de presentacin. */
while(1)
{
/* Inicializa el manejador de interfaz con la capa de sesin
del modem PLC. */
handle->modsphd = modplcsp_init(sid);
if (!handle->modsphd) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
handle->payloadsize = modplcsp_getpayloadsize(handle->modsphd);
if (!handle->payloadsize) break;
/* Define un manejador de mensajes recibidos por la capa de
sesin. */
if (!modplcsp_notify(handle->modsphd, __modplcpp_procmsg__,
handle))
break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de presentacin. */
modplcsp_release(handle->modsphd);
free(handle);
return NULL;
}
/*
Funcin modplcpp_release:
Libera los recursos utilizados por la capa de presentacin del modem
PLC.
*/
int modplcpp_release(modplcpp_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modplcsp_notify(hd->modsphd, NULL, NULL);
/* Libera la interfaz con la capa de sesin del modem PLC. */
modplcsp_release(hd->modsphd);
/* Libera los recursos utilizados por la capa de presentacin. */
free(hd);
/* xito. */
return 1;
}

460

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcpp_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modplcpp_publish(modplcpp_hd *hd, modplcpp_grpid grpid)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
return modplcsp_publish(hd->modsphd, grpid);
}
/*
Funcin modplcpp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modplcpp_subscribe(modplcpp_hd *hd, modplcpp_grpid grpid)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
return modplcsp_subscribe(hd->modsphd, grpid);
}
/*
Funcin modplcpp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcpp_leave(modplcpp_hd *hd, modplcpp_grpid grpid)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
return modplcsp_leave(hd->modsphd, grpid);
}
/*
Funcin modplcpp_newmsg:
Crea un nuevo mensaje.
*/
int modplcpp_newmsg(modplcpp_hd *hd, modplcpp_msg *msg, modplcpp_grpid grpid,
modplcpp_mtype mtype)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Asigna memoria para almacenar el contenido del mensaje. */
msg->dat = (unsigned char *)
malloc(hd->payloadsize * sizeof(unsigned char));
if (!msg->dat) return 0;
/* Inicializa el mensaje. */
msg->startoffset = 0;
msg->endoffset = 0;
msg->grpid = grpid;
msg->mtype = mtype;
msg->pphd = hd;
return 1;
}
/*

FernandoArielBeunza79156

461

Tesis de Grado en Ingeniera Informtica


Funcin modplcpp_copymsg:
Crea un copia de un mensaje.
*/
int modplcpp_copymsg(modplcpp_msg *dest, modplcpp_msg *src)
{
/* Verifica que el puntero al mensaje original no sea nulo. */
if (!src) return 0;
/* Verifica que el puntero a la copia del mensaje no sea nulo. */
if (!dest) return 0;
/* Asigna memoria para almacenar el contenido del mensaje. */
dest->dat = (unsigned char *)
malloc(((modplcpp_hd *) src->pphd)->payloadsize *
sizeof(unsigned char));
if (!dest->dat) return 0;
/* Inicializa la copia del mensaje. */
dest->startoffset = src->startoffset;
dest->endoffset = src->endoffset;
dest->grpid = src->grpid;
dest->mtype = src->mtype;
dest->pphd = src->pphd;
memcpy(dest->dat, src->dat, src->endoffset);
return 1;
}
/*
Funcin modplcpp_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcpp_putfield(modplcpp_msg *msg, modplcpp_ftype type,
unsigned char count, const void *dat)
{
/* Variables. */
unsigned char *ptr;
/* Puntero a los datos. */
size_t msgsize;
/* Tamao del mensaje. */

/* Verifica que el puntero al mensaje no sea nulo. */


if (!msg) return 0;
/* Inicializa el puntero a los datos. */
ptr = (unsigned char *) dat;
/* Verifica si el nuevo campo puede entrar en el mensaje. */
msgsize = msg->endoffset;
msgsize += sizeof(modplcpp_ftype);
msgsize += sizeof(unsigned char);
if ((type == MODPLCPP_CHARTYPE) || (type == MODPLCPP_UINT8TYPE))
msgsize += count * sizeof(unsigned char);
else if (type == MODPLCPP_SINT8TYPE)
msgsize += count * sizeof(char);
else if ((type == MODPLCPP_SINT16TYPE) ||
(type == MODPLCPP_UINT16TYPE))
msgsize += count * sizeof(unsigned short int);
else if ((type == MODPLCPP_SINT32TYPE) ||
(type == MODPLCPP_UINT32TYPE))
msgsize += count * sizeof(unsigned long int);
else if (type == MODPLCPP_FLOATTYPE)
msgsize += count * sizeof(float);
else
return 0;
if (msgsize > ((modplcpp_hd *) (msg->pphd))->payloadsize) return 0;
/* Agrega el tipo de dato. */
*(msg->dat + msg->endoffset) = type;
msg->endoffset += sizeof(modplcpp_ftype);
/* Agrega la cantidad de datos. */
*(msg->dat + msg->endoffset) = count;

462

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


msg->endoffset += sizeof(unsigned char);
/* Agrega datos tipo caracter o entero de 8 bits sin signo. */
if ((type == MODPLCPP_CHARTYPE) || (type == MODPLCPP_UINT8TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(unsigned char);
msg->endoffset += sizeof(unsigned char);
}
}
/* Agrega datos tipo entero de 8 bits con signo. */
else if (type == MODPLCPP_SINT8TYPE)
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(char);
msg->endoffset += sizeof(char);
}
}
/* Agrega datos tipo entero de 16 bits. */
else if ((type == MODPLCPP_SINT16TYPE) ||
(type == MODPLCPP_UINT16TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset + 0) = *(ptr + 1);
*(msg->dat + msg->endoffset + 1) = *(ptr + 0);
ptr += sizeof(unsigned short int);
msg->endoffset += sizeof(unsigned short int);
}
}
/* Agrega datos tipo entero de 32 bits. */
else if ((type == MODPLCPP_SINT32TYPE) ||
(type == MODPLCPP_UINT32TYPE))
{
while(count--)
{
*(msg->dat + msg->endoffset + 0) = *(ptr + 3);
*(msg->dat + msg->endoffset + 1) = *(ptr + 2);
*(msg->dat + msg->endoffset + 2) = *(ptr + 1);
*(msg->dat + msg->endoffset + 3) = *(ptr + 0);
ptr += sizeof(unsigned long int);
msg->endoffset += sizeof(unsigned long int);
}
}
/* Agrega datos tipo punto flotante. */
else if (type == MODPLCPP_FLOATTYPE)
{
while(count--)
{
*(msg->dat + msg->endoffset) = *ptr;
ptr += sizeof(float);
msg->endoffset += sizeof(float);
}
}
/* xito. */
return 1;
}
/*
Funcin modplcpp_sendmsg:
Enva un mensaje por medio de la capa de presentacin.
*/
int modplcpp_sendmsg(modplcpp_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;

FernandoArielBeunza79156

463

Tesis de Grado en Ingeniera Informtica


/* Enva un mensaje. */
if (modplcsp_send(((modplcpp_hd *) (msg->pphd))->modsphd, msg->grpid,
msg->mtype, msg->dat, msg->endoffset) == msg->endoffset)
return 1;
return 0;
}
/*
Funcin modplcpp_receivemsg:
Recibe un mensaje por medio de la capa de presentacin.
*/
int modplcpp_receivemsg(modplcpp_hd *hd, modplcpp_msg *msg)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Asigna memoria para almacenar el contenido del mensaje. */
msg->dat = (unsigned char *)
malloc(hd->payloadsize * sizeof(unsigned char));
if (!msg->dat) return 0;
/* Espera la llegada de un mensaje. */
while(!modplcpp_poll(hd));
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
if (msg)
{
msg->grpid = hd->buffer.grpid;
msg->startoffset = hd->buffer.startoffset;
msg->endoffset = hd->buffer.endoffset;
msg->pphd = hd;
memcpy(msg->dat, hd->buffer.dat, hd->buffer.endoffset);
}
hd->buffer.endoffset = 0;
free(hd->buffer.dat);
/* xito. */
return 1;
}
/*
Funcin modplcpp_getfield:
Extrae un campo del mensaje.
*/
int modplcpp_getfield(modplcpp_msg *msg, modplcpp_ftype *type,
unsigned char *count, void *dat)
{
/* Variables. */
unsigned char c;
/* Contador. */
unsigned char *ptr;
/* Puntero a los datos. */

/* Verifica que el puntero al mensaje no sea nulo. */


if (!msg) return 0;
/* Inicializa el puntero a los datos. */
ptr = (unsigned char *) dat;
/* Extrae el tipo de dato. */
*type = *(msg->dat + msg->startoffset);
msg->startoffset += sizeof(modplcpp_ftype);
/* Extrae la cantidad de datos. */
c = *(msg->dat + msg->startoffset);
*count = c;
msg->startoffset += sizeof(unsigned char);

464

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Agrega datos tipo caracter o entero de 8 bits. */
if ((*type == MODPLCPP_CHARTYPE) || (*type == MODPLCPP_SINT8TYPE) ||
(*type == MODPLCPP_UINT8TYPE))
{
while(c --)
{
*ptr = *(msg->dat + msg->startoffset);
ptr += sizeof(unsigned char);
msg->startoffset += sizeof(unsigned char);
}
return 1;
}
/* Agrega datos tipo entero de 16 bits. */
if ((*type == MODPLCPP_SINT16TYPE) || (*type == MODPLCPP_UINT16TYPE))
{
while(c --)
{
*(ptr + 1) = *(msg->dat + msg->startoffset + 0);
*(ptr + 0) = *(msg->dat + msg->startoffset + 1);
ptr += sizeof(unsigned short int);
msg->startoffset += sizeof(unsigned short int);
}
return 1;
}
/* Agrega datos tipo entero de 32 bits. */
if ((*type == MODPLCPP_SINT32TYPE) || (*type == MODPLCPP_UINT32TYPE))
{
while(c --)
{
*(ptr + 3) = *(msg->dat + msg->startoffset + 0);
*(ptr + 2) = *(msg->dat + msg->startoffset + 1);
*(ptr + 1) = *(msg->dat + msg->startoffset + 2);
*(ptr + 0) = *(msg->dat + msg->startoffset + 3);
ptr += sizeof(unsigned long int);
msg->startoffset += sizeof(unsigned long int);
}
return 1;
}
/* Agrega datos tipo punto flotante. */
if (*type == MODPLCPP_FLOATTYPE)
{
while(c --)
{
*ptr = *(msg->dat + msg->startoffset);
ptr += sizeof(float);
msg->startoffset += sizeof(float);
}
return 1;
}
/* Tipo de dato desconocido. */
msg->startoffset -= sizeof(unsigned char);
msg->startoffset -= sizeof(modplcpp_ftype);
return 0;
}
/*
Funcin modplcpp_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcpp_grpid modplcpp_getgrpid(modplcpp_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return msg->grpid;
}

FernandoArielBeunza79156

465

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcpp_destroymsg:
Destruye un mensaje.
*/
int modplcpp_destroymsg(modplcpp_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Elimina el contenido del mensaje. */
if (!msg->dat) return 0;
free(msg->dat);
msg->dat = NULL;
return 1;
}
/*
Funcin modplcpp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcpp_notify(modplcpp_hd *hd, void (*func)(modplcpp_hd *,
modplcpp_msg *, void *), void *param)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Define un manejador de mensajes recibidos. */
hd->recfun = (void (*)(void *, modplcpp_msg *, void *)) func;
hd->param = param;
return 1;
}
/*
Funcin modplcpp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcpp_poll(modplcpp_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Verifica la llegada de un nuevo mensaje. */
return (hd->buffer.endoffset != 0);
}
/*
Funcin modplcpp_status:
Devuelve el estado del modem PLC.
*/
int modplcpp_status(modplcpp_hd *hd)
{
/* Verifica que el manejador de la capa de presentacin exista. */
if (!hd) return 0;
/* Devuelve el estado del modem PLC. */
return modplcsp_status(hd->modsphd);
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcpp_procmsg__:
Procesa un mensaje recibido por medio de la capa de sesin.
*/
static void __modplcpp_procmsg__(modplcsp_hd *hd, modplcsp_grpid grpid,
void *msg, size_t msgsize, void *param)
{
/* Variables. */
modplcpp_hd *pphd;
/* Manejador de capa de

466

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


presentacin. */

/* Carga el manejador de capa de presentacin. */


pphd = (modplcpp_hd *) param;
/* Verifica si el buffer se encuentra lleno. */
if (pphd->buffer.endoffset != 0) return;
/* Reserva memoria para almacenar el mensaje recibido. */
pphd->buffer.dat =
(unsigned char *) malloc(msgsize * sizeof(unsigned char));
if (!pphd->buffer.dat) return;
/* Acepta el mensaje recibido. */
pphd->buffer.grpid = grpid;
pphd->buffer.startoffset = 0;
pphd->buffer.endoffset = msgsize;
pphd->buffer.pphd = pphd;
memcpy(pphd->buffer.dat, msg, msgsize);
/* Invoca a la funcin de atencin de recepcin de mensajes registrada. */
if (!pphd->recfun) return;
pphd->recfun(pphd, &(pphd->buffer), pphd->param);
pphd->buffer.endoffset = 0;
free(pphd->buffer.dat);
}

C.4.1.6. Archivo modplcap.h


/*
modplcap.h:
Declaracin de funciones referentes a la interfaz de la capa de
aplicacin del modem PLC.
*/

#if !defined(__MODPLCAP_H__)
#define __MODPLCAP_H__

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcap_grpid;
/* Identificador de mensaje. */
typedef unsigned short int modplcap_msgid;
/* Tipo de campo. */
typedef unsigned char modplcap_ftype;
/* Estructura del mensaje. */
typedef struct
{
modplcap_msgid msgid;
void *msg;
} modplcap_msg;
/* Manejador de capa de aplicacin. */
typedef struct
{
int msgflag;
modplcap_grpid grpid;

void *pphd;

FernandoArielBeunza79156

/* Identificador de mensaje. */
/* Puntero al mensaje. */

/* Indicador de mensaje en el
buffer. */
/* Identificador de grupo del
mensaje almacenado en el
buffer. */
/* Puntero al manejador de capa de

467

Tesis de Grado en Ingeniera Informtica


presentacin. */
void (*recfun)
(void *, modplcap_msg *,
void *);
void *param;

modplcap_msg buffer;

/* Funcin manejadora de mensajes


recibidos. */
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
/* Puntero al buffer de campos
recibidos. */

} modplcap_hd;

/* Definicin de constantes. */
/* Tipos de datos. */
#define MODPLCAP_NULLTYPE
#define MODPLCAP_CHARTYPE
#define MODPLCAP_SINT8TYPE
#define MODPLCAP_UINT8TYPE
#define MODPLCAP_SINT16TYPE
#define MODPLCAP_UINT16TYPE
#define MODPLCAP_SINT32TYPE
#define MODPLCAP_UINT32TYPE
#define MODPLCAP_FLOATTYPE

0x00
0x01
0x02
0x03
0x04
0x05
0x06
0x07
0x08

/* Declaracin de funciones pblicas. */


/*
Funcin modplcap_init:
Inicializa los recursos utilizados por la capa de aplicacin del modem
PLC.
*/
modplcap_hd *modplcap_init(int);
/*
Funcin modplcap_release:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
int modplcap_release(modplcap_hd *);
/*
Funcin modplcap_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modplcap_publish(modplcap_hd *, modplcap_grpid);
/*
Funcin modplcap_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modplcap_subscribe(modplcap_hd *, modplcap_grpid);
/*
Funcin modplcap_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcap_leave(modplcap_hd *, modplcap_grpid);
/*
Funcin modplcap_newmsg:
Crea un nuevo mensaje.
*/
int modplcap_newmsg(modplcap_hd *, modplcap_msg *, modplcap_grpid,
modplcap_msgid);
/*
Funcin modplcap_copymsg:

468

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Crea un copia de un mensaje.
*/
int modplcap_copymsg(modplcap_msg *, modplcap_msg *);
/*
Funcin modplcap_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcap_putfield(modplcap_msg *, modplcap_ftype, unsigned char,
const void *);
/*
Funcin modplcap_sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
int modplcap_sendmsg(modplcap_msg *);
/*
Funcin modplcap_receivemsg:
Recibe un mensaje por medio de la capa de aplicacin.
*/
int modplcap_receivemsg(modplcap_hd *, modplcap_msg *);
/*
Funcin modplcap_getfield:
Extrae un campo del mensaje.
*/
int modplcap_getfield(modplcap_msg *, modplcap_ftype *, unsigned char *,
void *);
/*
Funcin modplcap_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcap_grpid modplcap_getgrpid(modplcap_msg *);
/*
Funcin modplcap_getmsgid:
Devuelve el identificador de mensaje.
*/
modplcap_msgid modplcap_getmsgid(modplcap_msg *);
/*
Funcin modplcap_destroymsg:
Destruye un mensaje.
*/
int modplcap_destroymsg(modplcap_msg *);
/*
Funcin modplcap_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcap_notify(modplcap_hd *, void (*func)(modplcap_hd *, modplcap_msg *,
void *), void *);
/*
Funcin modplcap_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcap_poll(modplcap_hd *);
/*
Funcin modplcap_status:
Devuelve el estado del modem PLC.
*/
int modplcap_status(modplcap_hd *);

#endif

FernandoArielBeunza79156

469

Tesis de Grado en Ingeniera Informtica

C.4.1.7. Archivo modplcap.c


/*
modplcap.c:
Implementacin de funciones referentes a la capa de aplicacin del
modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "modplcpp.h"
#include "modplcap.h"

/* Declaracin de funciones privadas. */


static void __modplcap_procmsg__(modplcpp_hd *, modplcpp_msg *, void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcap_init:
Inicializa los recursos utilizados por la capa de aplicacin del modem
PLC.
*/
modplcap_hd *modplcap_init(int sid)
{
/* Variables. */
modplcap_hd *handle;

/* Manejador de capa de
aplicacin. */

/* Crea un nuevo manejador de capa de aplicacin. */


handle = (modplcap_hd *) malloc(sizeof(modplcap_hd));
if (!handle) return NULL;
/* Inicializa el manejador de capa de aplicacin. */
while(1)
{
/* Inicializa el manejador de capa de presentancin. */
handle->pphd = modplcpp_init(sid);
if (!handle->pphd) break;
/* Define un manejador de mensajes recibidos por la capa de
presentacin. */
if (!modplcpp_notify((modplcpp_hd *) handle->pphd,
__modplcap_procmsg__, handle))
break;
/* Inicializa el buffer. */
handle->msgflag = 0;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de aplicacin. */
modplcpp_release((modplcpp_hd *) handle->pphd);
free(handle);
return NULL;
}

470

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplcap_release:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
int modplcap_release(modplcap_hd *hd)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modplcpp_notify((modplcpp_hd *) hd->pphd, NULL, NULL);
/* Libera la interfaz con la capa de presentacin. */
modplcpp_release((modplcpp_hd *) hd->pphd);
/* Libera los recursos utilizados por la capa de aplicacin. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcap_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modplcap_publish(modplcap_hd *hd, modplcap_grpid grpid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
return modplcpp_publish((modplcpp_hd *) hd->pphd, grpid);
}
/*
Funcin modplcap_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modplcap_subscribe(modplcap_hd *hd, modplcap_grpid grpid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
return modplcpp_subscribe((modplcpp_hd *) hd->pphd, grpid);
}
/*
Funcin modplcap_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modplcap_leave(modplcap_hd *hd, modplcap_grpid grpid)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
return modplcpp_leave((modplcpp_hd *) hd->pphd, grpid);
}
/*
Funcin modplcap_newmsg:
Crea un nuevo mensaje.
*/
int modplcap_newmsg(modplcap_hd *hd, modplcap_msg *msg, modplcap_grpid grpid,
modplcap_msgid msgid)

FernandoArielBeunza79156

471

Tesis de Grado en Ingeniera Informtica


{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Inicializa el mensaje. */
msg->msgid = msgid;
msg->msg = malloc(sizeof(modplcpp_msg));
if (!msg->msg) return 0;
while(1)
{
if (msgid & 0x8000)
{
if (!modplcpp_newmsg((modplcpp_hd *) hd->pphd,
(modplcpp_msg *) (msg->msg), grpid,
MODPLCPP_NOSECMSG))
break;
}
else
{
if (!modplcpp_newmsg((modplcpp_hd *) hd->pphd,
(modplcpp_msg *) (msg->msg), grpid,
MODPLCPP_SECMSG))
break;
}
if (!modplcpp_putfield((modplcpp_msg *) (msg->msg),
MODPLCPP_UINT16TYPE, 1, &msgid))
break;
return 1;
}
free(msg->msg);
msg->msg = NULL;
return 0;
}
/*
Funcin modplcap_copymsg:
Crea un copia de un mensaje.
*/
int modplcap_copymsg(modplcap_msg *dest, modplcap_msg *src)
{
/* Verifica que el puntero al mensaje original no sea nulo. */
if (!src) return 0;
/* Verifica que el puntero a la copia del mensaje no sea nulo. */
if (!dest) return 0;
/* Copia el mensaje. */
dest->msgid = src->msgid;
return modplcpp_copymsg((modplcpp_msg *) (dest->msg),
(modplcpp_msg *) (src->msg));
}
/*
Funcin modplcap_putfield:
Agrega un nuevo campo al mensaje.
*/
int modplcap_putfield(modplcap_msg *msg, modplcap_ftype type,
unsigned char count, const void *dat)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Agrega un nuevo campo al mensaje. */
return modplcpp_putfield((modplcpp_msg *) (msg->msg), type, count,
dat);
}
/*

472

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin modplcap_sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
int modplcap_sendmsg(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Enva un mensaje. */
return modplcpp_sendmsg((modplcpp_msg *) (msg->msg));
}
/*
Funcin modplcap_receivemsg:
Recibe un mensaje por medio de la capa de aplicacin.
*/
int modplcap_receivemsg(modplcap_hd *hd, modplcap_msg *msg)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Espera la llegada de un mensaje. */
while(!modplcap_poll(hd));
/* Recibe un mensaje. */
if (msg)
{
msg->msgid = hd->buffer.msgid;
msg->msg = malloc(sizeof(modplcpp_msg));
if (!msg->msg) return 0;
memcpy((modplcpp_msg *) (msg->msg),
(modplcpp_msg *) (hd->buffer.msg),
sizeof(modplcpp_msg));
}
modplcpp_destroymsg(hd->buffer.msg);
free(hd->buffer.msg);
hd->msgflag = 0;
return 1;
}
/*
Funcin modplcap_getfield:
Extrae un campo del mensaje.
*/
int modplcap_getfield(modplcap_msg *msg, modplcap_ftype *type,
unsigned char *count, void *dat)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Extrae un campo del mensaje. */
return modplcpp_getfield((modplcpp_msg *) (msg->msg), type, count,
dat);
}
/*
Funcin modplcap_getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcap_grpid modplcap_getgrpid(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return ((modplcpp_msg *) (msg->msg))->grpid;
}
/*
Funcin modplcap_getmsgid:
Devuelve el identificador de mensaje.

FernandoArielBeunza79156

473

Tesis de Grado en Ingeniera Informtica


*/
modplcap_msgid modplcap_getmsgid(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Devuelve el identificador de grupo del mensaje. */
return msg->msgid;
}
/*
Funcin modplcap_destroymsg:
Destruye un mensaje.
*/
int modplcap_destroymsg(modplcap_msg *msg)
{
/* Verifica que el puntero al mensaje no sea nulo. */
if (!msg) return 0;
/* Destruye el mensaje. */
if (msg->msg) free(msg->msg);
msg->msg = NULL;
return 1;
}
/*
Funcin modplcap_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcap_notify(modplcap_hd *hd, void (*func)(modplcap_hd *,
modplcap_msg *, void *), void *param)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Define un manejador de mensajes recibidos. */
hd->recfun = (void (*)(void *, modplcap_msg *, void *)) func;
hd->param = param;
return 1;
}
/*
Funcin modplcap_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modplcap_poll(modplcap_hd *hd)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Verifica la llegada de un nuevo mensaje. */
return (hd->msgflag != 0);
}
/*
Funcin modplcap_status:
Devuelve el estado del modem PLC.
*/
int modplcap_status(modplcap_hd *hd)
{
/* Verifica que el manejador de la capa de aplicacin exista. */
if (!hd) return 0;
/* Devuelve el estado del modem PLC. */
return modplcpp_status(hd->pphd);
}

/* Implementacin de funciones privadas. */


/*

474

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin __modplcap_procmsg__:
Procesa un mensaje recibido por medio de la capa de presentacin.
*/
static void __modplcap_procmsg__(modplcpp_hd *hd, modplcpp_msg *msg,
void *param)
{
/* Variables. */
modplcpp_ftype type;
/* Tipo de campo. */
modplcap_msgid msgid;
/* Identificador de mensaje. */
unsigned char count;
/* Contador. */
modplcap_hd *aphd;
/* Manejador de capa de
aplicacin. */

/* Carga el manejador de capa de aplicacin. */


aphd = (modplcap_hd *) param;
/* Verifica si el buffer se encuentra lleno. */
if (aphd->msgflag) return;
/*
if
if
if

Recibe el mensaje. */
(!modplcpp_getfield(msg, &type, &count, &msgid)) return;
(type != MODPLCPP_UINT16TYPE) return;
(count != 1) return;

/* Acepta el mensaje recibido. */


aphd->buffer.msgid = msgid;
aphd->buffer.msg = malloc(sizeof(modplcpp_msg));
if (!aphd->buffer.msg) return;
if (!modplcpp_copymsg((modplcpp_msg *) aphd->buffer.msg, msg)) return;
aphd->msgflag = 1;
/* Invoca a la funcin de atencin de recepcin de mensajes
registrada. */
if (!aphd->recfun) return;
aphd->recfun(aphd, &(aphd->buffer), aphd->param);
modplcpp_destroymsg(aphd->buffer.msg);
free(aphd->buffer.msg);
aphd->msgflag = 0;
}

C.4.2. Interfaz capa de enlace modplcdl.so


En esta seccin se detalla el cdigo fuente de la biblioteca que implementa la interfaz con la
capa de enlace del modem PLC, que se compone de los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin de la biblioteca


dinmica que implementa la capa de enlace del modem PLC que no pueden ser
modificados en tiempo de ejecucin.

Archivo modplcdl.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa de enlace. Dichas primitivas brindan un conjunto de funcionalidades
que permiten la comunicacin con la capa de enlace implementada en el modem PLC por
medio del driver del mismo.

Archivo modplcdl.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcdl.h.

FernandoArielBeunza79156

475

Tesis de Grado en Ingeniera Informtica

C.4.2.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz con el driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa de enlace. */
#define MODDRVDL_CLOSE
0x00
#define MODDRVDL_OPEN
0x01
#define MODDRVDL_SEND
0x02
#define MODDRVDL_RECEIVE
0x03
#define MODDRVDL_POLL
0x04
#define MODDRVDL_GETADDRESS
0x05
#define MODDRVDL_ADDLOGADDRESS
0x06
#define MODDRVDL_DELLOGADDRESS
0x07
#define MODDRVDL_GETPHYADDRESS
0x08
#define MODDRVDL_STATUS
0x09
#define MODDRVDL_GETPAYLOADSIZE
0x0a

#endif

C.4.2.2. Archivo modplcdl.h


/*
modplcdl.h:
Declaracin de funciones referentes a la interfaz de la capa de enlace
del modem PLC.
*/

#if !defined(__MODPLCDL_H__)
#define __MODPLCDL_H__

/* Archivos includos necesarios. */


#include <pthread.h>

/* Definicin de tipos. */
/* Direccin fsica del modem PLC. */
typedef unsigned char modplcdl_phyaddr[8];
/* Direccin lgica del modem PLC. */
typedef unsigned long int modplcdl_logaddr;
/* Manejador de interfaz con la capa de enlace del modem PLC. */
typedef struct
{
int hq;
/* Manejador de cola de
mensajes. */
pthread_mutex_t hm;
/* Semforo de exclusin mtua. */
unsigned char sid;
/* Identificador de interfaz de
comunicacin por puerto
serie. */
unsigned long int conncounter;
/* Contador de conexiones
abiertas. */
} modplcdl_hd;

476

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Manejador de conexin por medio de la capa de enlace del modem PLC. */
typedef struct
{
int hq;
/* Manejador de cola de
mensajes. */
pthread_t detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
modplcdl_hd *dlhd;
/* Manejador de interfaz con la
capa de enlance del modem
PLC. */
void (*recfun)
(void *, modplcdl_phyaddr,
void *, size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} modplcdlconn_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin modplcdl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
modplcdl_hd *modplcdl_init(int);
/*
Funcin modplcdl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int modplcdl_release(modplcdl_hd *);
/*
Funcin modplcdl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
modplcdlconn_hd *modplcdl_open(modplcdl_hd *, unsigned char, unsigned char);
/*
Funcin modplcdl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplcdl_close(modplcdlconn_hd *);
/*
Funcin modplcdl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplcdl_send(modplcdlconn_hd *, modplcdl_phyaddr, unsigned char,
const void *, size_t);
/*
Funcin modplcdl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplcdl_receive(modplcdlconn_hd *, modplcdl_phyaddr, void *, size_t);
/*
Funcin modplcdl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcdl_notify(modplcdlconn_hd *, void (*func)(modplcdlconn_hd *,
modplcdl_phyaddr, void *, size_t, void *), void *);
/*
Funcin modplcdl_poll:

FernandoArielBeunza79156

477

Tesis de Grado en Ingeniera Informtica


Verifica la recepcin de un mensaje.
*/
int modplcdl_poll(modplcdlconn_hd *);
/*
Funcin modplcdl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplcdl_getaddress(modplcdl_hd *, unsigned char, modplcdl_phyaddr);
/*
Funcin modplcdl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplcdl_addlogaddress(modplcdl_hd *, unsigned char, unsigned char,
modplcdl_logaddr);
/*
Funcin modplcdl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplcdl_dellogaddress(modplcdl_hd *, unsigned char, unsigned char,
modplcdl_logaddr);
/*
Funcin modplcdl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa
de enlace del modem PLC.
*/
int modplcdl_getphyaddress(modplcdl_hd *hd, unsigned char, unsigned char,
modplcdl_logaddr, modplcdl_phyaddr);
/*
Funcin modplcdl_status:
Devuelve el estado del modem PLC.
*/
int modplcdl_status(modplcdl_hd *);
/*
Funcin modplcdl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de enlace del modem PLC.
*/
size_t modplcdl_getpayloadsize(modplcdl_hd *, unsigned char);

#endif

C.4.2.3. Archivo modplcdl.c


/*
modplcdl.c:
Implementacin de funciones referentes a la interfaz de la capa de
enlace del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include "modplcdl.h"

478

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

/* Declaracin de funciones privadas. */


static void *__modplcdl_detectproc__(void *);
static int __modplcdl_sendrecv__(int, void *, size_t, const void *, size_t);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcdl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
modplcdl_hd *modplcdl_init(int sid)
{
/* Variables. */
int layer;
int result;
modplcdl_hd *handle;
struct sockaddr_un servaddr;

/* Capa a la que se quiere


accerder. */
/* Resultado de la solicitud. */
/* Manejador de interfaz con la
capa de enlace del modem PLC. */
/* Direccin del servidor. */

/* Crea un nuevo manejador de interfaz con la capa de enlace del modem


PLC. */
handle = (modplcdl_hd *) malloc(sizeof(modplcdl_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de enlace del modem
PLC. */
while(1)
{
/* Abre una conexin con la cola de mensajes del driver del
modem PLC. */
handle->hq = socket(AF_LOCAL, SOCK_STREAM, 0);
if (handle->hq < 0) break;
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
sprintf(servaddr.sun_path, "/tmp/modemplc%i.str", sid);
if (connect(handle->hq, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0)
break;
/* Inicializa semforo de exclusin mtua. */
if (pthread_mutex_init(&(handle->hm), NULL)) break;
if (pthread_mutex_unlock(&(handle->hm))) break;
/* Solicita acceder a la capa de enlace del modem PLC. */
layer = 2;
if (!__modplcdl_sendrecv__(handle->hq, &result, sizeof(result),
&layer, sizeof(layer)))
break;
if (!result) break;
/* Almacena la interfaz de comunicacin por puerto serie. */
handle->sid = sid;
/* Inicializa el contador de conexiones abiertas. */
handle->conncounter = 0;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de enlace del modem
PLC. */
pthread_mutex_destroy(&(handle->hm));
close(handle->hq);
free(handle);
return NULL;

FernandoArielBeunza79156

479

Tesis de Grado en Ingeniera Informtica


}
/*
Funcin modplcdl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int modplcdl_release(modplcdl_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la solicitud. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Verifica que no existan conexiones abiertas. */
if (hd->conncounter) return 0;
/* Solicita el cierre de la conexin. */
op = MODDRVDL_CLOSE;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Libera los recursos utilizados por el semforo de exclusin mtua. */
if (pthread_mutex_destroy(&(hd->hm))) return 0;
/* Libera los recursos utilizados por la interfaz con la capa de enlace
del modem PLC. */
close(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcdl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
modplcdlconn_hd *modplcdl_open(modplcdl_hd *hd, unsigned char iface,
unsigned char prot)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int layer;
/* Capa a la que se quiere
accerder. */
int result;
/* Resultado de la solicitud. */
size_t payloadsize;
/* Cantidad de bytes que puede
contener un mensaje. */
modplcdlconn_hd *handle;
/* Manejador de conexin de la capa
de enlace del modem PLC. */
struct sockaddr_un servaddr;
/* Direccin del servidor. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return NULL;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Crea un nuevo manejador de conexin por medio de la capa de enlace
del modem PLC. */
handle = (modplcdlconn_hd *) malloc(sizeof(modplcdlconn_hd));
if (!handle)
{

480

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


pthread_mutex_unlock(&(hd->hm));
return NULL;
}
/* Inicializa el manejador de conexin. */
while(1)
{
/* Carga el manejador de interfaz con la capa de enlace del modem
PLC. */
handle->dlhd = hd;
/* Abre una conexin con la cola de mensajes del driver del modem
PLC. */
handle->hq = socket(AF_LOCAL, SOCK_STREAM, 0);
if (handle->hq < 0) break;
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
sprintf(servaddr.sun_path, "/tmp/modemplc%i.str", hd->sid);
if (connect(handle->hq, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0)
break;
/* Solicita acceder a la capa de enlace del modem PLC. */
layer = 2;
if (!__modplcdl_sendrecv__(handle->hq, &result, sizeof(result),
&layer, sizeof(layer)))
break;
if (!result) break;
/* Solicita abrir una conexin. */
op = MODDRVDL_OPEN;
if (!__modplcdl_sendrecv__(handle->hq, NULL, 0, &op,
sizeof(op)))
break;
if (!__modplcdl_sendrecv__(handle->hq, NULL, 0, &iface,
sizeof(iface)))
break;
if (!__modplcdl_sendrecv__(handle->hq, &result, sizeof(result),
&prot, sizeof(prot)))
break;
if (!result) break;
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
op = MODDRVDL_GETPAYLOADSIZE;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, &payloadsize,
sizeof(payloadsize), &iface, sizeof(iface)))
break;
if (!payloadsize) break;
handle->payloadsize = payloadsize;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Actualiza el nmero de conexiones. */
handle->dlhd->conncounter ++;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->hm))) break;
/* Devuelve el manejador creado. */
return handle;
}

FernandoArielBeunza79156

481

Tesis de Grado en Ingeniera Informtica


/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
pthread_mutex_unlock(&(hd->hm));
/* No se pudo abrir la conexin. */
close(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcdl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplcdl_close(modplcdlconn_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la solicitud. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modplcdl_notify(hd, NULL, NULL);
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
/* Solicita el cierre de la conexin. */
op = MODDRVDL_CLOSE;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Actualiza el nmero de conexiones. */
hd->dlhd->conncounter --;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->dlhd->hm))) return 0;
/* Libera los recursos utilizados por la conexin por medio de la capa
de enlace del modem PLC. */
close(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcdl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplcdl_send(modplcdlconn_hd *hd, modplcdl_phyaddr addr,
unsigned char prio, const void *msg, size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem

482

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


PLC. */
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
/* Enva un mensaje. */
while(1)
{
/* Solicita el envo de un mensaje. */
op = MODDRVDL_SEND;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva la direccin destinataria. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, addr,
sizeof(modplcdl_phyaddr)))
break;
/* Enva la prioridad del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prio,
sizeof(prio)))
break;
/* Enva el tamao del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &msgsize,
sizeof(msgsize)))
break;
/* Enva el mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, &msgsize, sizeof(msgsize),
msg, msgsize))
break;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->dlhd->hm))) break;
/* Devuelve la cantidad de bytes enviados. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
pthread_mutex_unlock(&(hd->dlhd->hm));
/* No se pudo realizar el envo. */
return 0;
}
/*
Funcin modplcdl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplcdl_receive(modplcdlconn_hd *hd, modplcdl_phyaddr addr, void *msg,
size_t msgsize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
/* Recibe un mensaje. */
while(1)
{
/* Solicita la recepcin de un mensaje. */
op = MODDRVDL_RECEIVE;

FernandoArielBeunza79156

483

Tesis de Grado en Ingeniera Informtica


if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva la cantidad de bytes que se solicita recibir del
mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, &msgsize, sizeof(msgsize),
&msgsize, sizeof(msgsize)))
break;
if (!msgsize) break;
/* Recibe la direccin de origen del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, addr,
sizeof(modplcdl_phyaddr), NULL, 0))
break;
/* Recibe el mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, msg, msgsize, NULL, 0))
break;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->dlhd->hm))) break;
/* Devuelve la cantidad de bytes enviados. */
return msgsize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
pthread_mutex_unlock(&(hd->dlhd->hm));
/* No se pudo realizar la recepcin. */
return 0;
}
/*
Funcin modplcdl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modplcdl_notify(modplcdlconn_hd *hd, void (*func)(modplcdlconn_hd *,
modplcdl_phyaddr, void *, size_t, void *), void *param)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
hd->recfun = (void (*)(void *, modplcdl_phyaddr, void *,
size_t, void *)) func;
hd->param = param;
if (pthread_mutex_unlock(&(hd->dlhd->hm))) return 0;
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora
definida previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
hd->recfun = NULL;
hd->param = param;
if (pthread_mutex_unlock(&(hd->dlhd->hm))) return 0;
if (pthread_join(hd->detectthread, NULL)) return 0;

484

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
hd->recfun = (void (*)(void *, modplcdl_phyaddr, void *,
size_t, void *)) func;
hd->param = param;
if (pthread_create(&(hd->detectthread), NULL,
__modplcdl_detectproc__, hd))
{
hd->recfun = NULL;
hd->param = NULL;
pthread_mutex_unlock(&(hd->dlhd->hm));
return 0;
}
if (pthread_mutex_unlock(&(hd->dlhd->hm))) return 0;
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modplcdl_poll:
Verifica la recepcin de un mensaje.
*/
int modplcdl_poll(modplcdlconn_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->dlhd->hm))) return 0;
/* Solicita verificar la recepcin de un mensaje. */
op = MODDRVDL_POLL;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->dlhd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplcdl_getaddress(modplcdl_hd *hd, unsigned char iface,
modplcdl_phyaddr addr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

FernandoArielBeunza79156

485

Tesis de Grado en Ingeniera Informtica


/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene la direccin fsica del modem PLC. */
result = 0;
while(1)
{
/* Solicita la direccin fsica del modem PLC. */
op = MODDRVDL_GETADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identifcador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result),
&iface, sizeof(iface)))
break;
if (!result) break;
/* Recibe la direccin fsica. */
if (!__modplcdl_sendrecv__(hd->hq, addr,
sizeof(modplcdl_phyaddr), NULL, 0))
result = 0;
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplcdl_addlogaddress(modplcdl_hd *hd, unsigned char iface,
unsigned char prot, modplcdl_logaddr addr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Agrega una direccin lgica. */
result = 0;
while(1)
{
/* Solicita agregar una direccin lgica. */
op = MODDRVDL_ADDLOGADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &iface,
sizeof(iface)))

486

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


break;
/* Enva el identificador de protocolo. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prot,
sizeof(prot)))
break;
/* Enva la direccin lgica. */
__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &addr,
sizeof(addr));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplcdl_dellogaddress(modplcdl_hd *hd, unsigned char iface,
unsigned char prot, modplcdl_logaddr addr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Elimina una direccin lgica. */
result = 0;
while(1)
{
/* Solicita la eliminacin de una direccin lgica. */
op = MODDRVDL_DELLOGADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el identificador de protocolo. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prot,
sizeof(prot)))
break;
/* Enva la direccin lgica. */
__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &addr,
sizeof(addr));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */

FernandoArielBeunza79156

487

Tesis de Grado en Ingeniera Informtica


return result;
}
/*
Funcin modplcdl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa
de enlace del modem PLC.
*/
int modplcdl_getphyaddress(modplcdl_hd *hd, unsigned char iface,
unsigned char prot, modplcdl_logaddr laddr,
modplcdl_phyaddr paddr)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene la direccin fsica asociada a la direccin lgica. */
result = 0;
while(1)
{
/* Solicita la direccin fsica. */
op = MODDRVDL_GETPHYADDRESS;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el identificador de protocolo. */
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &prot,
sizeof(prot)))
break;
/* Enva la direccin lgica. */
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result),
&laddr, sizeof(laddr)))
break;
if (!result) break;
/* Recibe la direccin fsica. */
__modplcdl_sendrecv__(hd->hq, paddr, sizeof(modplcdl_phyaddr),
NULL, 0);
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcdl_status:
Devuelve el estado del modem PLC.
*/
int modplcdl_status(modplcdl_hd *hd)
{
/* Variables. */

488

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene el estado del modem PLC. */
op = MODDRVDL_STATUS;
if (!__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el estado del modem PLC. */
return result;
}
/*
Funcin modplcdl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de enlace del modem PLC.
*/
size_t modplcdl_getpayloadsize(modplcdl_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Operacin. */
size_t payloadsize;
/* Cantidad de bytes que puede
contener un mensaje. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
payloadsize = 0;
while(1)
{
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
op = MODDRVDL_GETPAYLOADSIZE;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op, sizeof(op)))
break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
__modplcdl_sendrecv__(hd->hq, &payloadsize,
sizeof(payloadsize), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener un

FernandoArielBeunza79156

489

Tesis de Grado en Ingeniera Informtica


mensaje. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcdl_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser
ledo.
*/
static void *__modplcdl_detectproc__(void *param)
{
/* Variables. */
int op;
int result;
int captureflag;
size_t msgsize;
modplcdl_phyaddr addr;
modplcdlconn_hd *hd;

void (*func)
(void *, modplcdl_phyaddr,
void *, size_t, void *);
unsigned char *msg;

/* Identificador de operacin. */
/* Resultado de la operacin. */
/* Indicador de captura de un
mensaje. */
/* Tamao del mensaje. */
/* Direccin de origen. */
/* Manejador de conexin por medio
de la capa de enlace del modem
PLC. */

/* Funcin manejadora de mensajes


recibidos. */
/* Puntero al mensaje recibido. */

/* Carga el manejador de interfaz con la capa de enlace del modem PLC. */


hd = (modplcdlconn_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_lock(&(hd->dlhd->hm))) continue;
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
op = MODDRVDL_POLL;
if (__modplcdl_sendrecv__(hd->hq, &result, sizeof(result), &op,
sizeof(op)))
captureflag = result;
/* Recibe el mensaje. */
while(captureflag)
{
/* Solicita la recepcin de un mensaje. */
op = MODDRVDL_RECEIVE;
if (!__modplcdl_sendrecv__(hd->hq, NULL, 0, &op,
sizeof(op)))
break;
/* Enva la cantidad de bytes que se solicita recibir
del mensaje. */
msgsize = hd->payloadsize;
if (!__modplcdl_sendrecv__(hd->hq, &msgsize,
sizeof(msgsize), &msgsize, sizeof(msgsize)))
break;
if (!msgsize) break;
/* Recibe la direccin de origen del mensaje. */
if (!__modplcdl_sendrecv__(hd->hq, addr,
sizeof(modplcdl_phyaddr), NULL, 0))
break;

490

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Recibe el mensaje. */
msg = (unsigned char *)
malloc(msgsize * sizeof(unsigned char));
if (!msg)
{
captureflag = 0;
break;
}
__modplcdl_sendrecv__(hd->hq, msg, msgsize, NULL, 0);
break;
}
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
pthread_mutex_unlock(&(hd->dlhd->hm));
/* Verifica si se ha detectado la recepcin de un mensaje para
invocar al manejador de mensajes recibidos. */
if (captureflag)
{
func(hd, addr, msg, msgsize, hd->param);
free(msg);
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
pthread_mutex_unlock(&(hd->dlhd->hm));
pthread_exit(0);
}
/*
Funcin __modplcdl_sendrecv__:
Intercambia datos con el driver del modem PLC.
*/
static int __modplcdl_sendrecv__(int hq, void *outdata, size_t outsize,
const void *indata, size_t insize)
{
/* Variables. */
size_t last;
/* Cantidad de bytes enviados o
recibidos. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Enva la operacin. */
sent = 0;
while((indata) && (sent < insize))
{
last = write(hq, indata + sent, insize - sent);
sent += last;
}
/* Recibe la respuesta. */
received = 0;
while((outdata) && (received < outsize))
{
last = read(hq, outdata + received, outsize - received);
received += last;
}
/* xito. */
return 1;
}

FernandoArielBeunza79156

491

Tesis de Grado en Ingeniera Informtica

C.4.3. Interfaz capa fsica modplcphy.so


En esta seccin se detalla el cdigo fuente de la biblioteca que implementa la interfaz con la
capa fsica del modem PLC, que se compone de los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin de la biblioteca


dinmica que implementa la interfaz con la capa fsica del modem PLC que no pueden ser
modificados en tiempo de ejecucin.

Archivo modplcphy.h: en este archivo se declaran las primitivas correspondientes al


interfaz con la capa fsica. Dichas primitivas brindan un conjunto de funcionalidades que
permiten la comunicacin con la capa fsica implementada en el modem PLC por medio
del driver del mismo.

Archivo modplcphy.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo modplcphy.h.

C.4.3.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz con el driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa fsica. */
#define MODDRVPHY_RELEASE
0x00
#define MODDRVPHY_SNDFRAME
0x01
#define MODDRVPHY_CAPFRAME
0x02
#define MODDRVPHY_GETFRAME
0x03
#define MODDRVPHY_POLL
0x04
#define MODDRVPHY_RSDFRAME
0x05
#define MODDRVPHY_CLRBUFFER
0x06
#define MODDRVPHY_SENSECHANNEL
0x07
#define MODDRVPHY_GENSIGNAL
0x08
#define MODDRVPHY_TSTRECEIVE
0x09
#define MODDRVPHY_STATUS
0x0a
#define MODDRVPHY_GETPAYLOADSIZE
0x0b

#endif

C.4.3.2. Archivo modplcphy.h


/*
modplcphy.h:
Declaracin de funciones referentes a la interfaz de la capa fsica del
modem PLC.
*/

#if !defined(__MODPLCPHY_H__)

492

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#define __MODPLCPHY_H__

/* Archivos includos necesarios. */


#include <pthread.h>

/* Definicin de tipos. */
/* Manejador de interfaz con la capa fsica del modem PLC. */
typedef struct
{
int hq;
/* Manejador de cola de
mensajes. */
pthread_mutex_t hm;
/* Semforo de exclusin mtua. */
struct
{
pthread_t detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
void (*recfun)(void *,
void *);
/* Funcin manejadora de tramas
capturadas. */
void *param;
/* Parmetros para la funcin
manejadora de tramas
recibidas. */
} iface[256];
/* Tabla de interfaces fsicas. */
} modplcphy_hd;

/* Definicin de constantes. */
/* Tipos de seales. */
#define MODPLCPHY_NOISESIGNAL
#define MODPLCPHY_TESTSIGNAL1
#define MODPLCPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Declaracin de funciones pblicas. */


/*
Funcin modplcphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
modplcphy_hd *modplcphy_init(int);
/*
Funcin modplcphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modplcphy_release(modplcphy_hd *);
/*
Funcin modplcphy_sndframe:
Enva una trama.
*/
size_t modplcphy_sndframe(modplcphy_hd *, unsigned char, const void *, size_t);
/*
Funcin modplcphy_capframe:
Captura una trama.
*/
int modplcphy_capframe(modplcphy_hd *, unsigned char, size_t);
/*
Funcin modplcphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modplcphy_getframe(modplcphy_hd *, unsigned char, void *, size_t);
/*
Funcin modplcphy_notify:

FernandoArielBeunza79156

493

Tesis de Grado en Ingeniera Informtica


Define una funcin manejadora de tramas capturadas.
*/
int modplcphy_notify(modplcphy_hd *, unsigned char,
void (*func)(modplcphy_hd *, void *), void *);
/*
Funcin modplcphy_poll:
Verifica la captura de una trama.
*/
int modplcphy_poll(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_rsdframe:
Reenva una trama.
*/
int modplcphy_rsdframe(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modplcphy_clrbuffer(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int modplcphy_sensechannel(modplcphy_hd *, unsigned char, unsigned char,
long int);
/*
Funcin modplcphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplcphy_gensignal(modplcphy_hd *, unsigned char, int);
/*
Funcin modplcphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modplcphy_tstreceive(modplcphy_hd *, unsigned char);
/*
Funcin modplcphy_status:
Devuelve el estado del modem PLC.
*/
int modplcphy_status(modplcphy_hd *);
/*
Funcin modplcphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplcphy_getpayloadsize(modplcphy_hd *, unsigned char);

#endif

C.4.3.3. Archivo modplcphy.c


/*
modplcphy.c:
Implementacin de funciones referentes a la interfaz de la capa fsica
del modem PLC.
*/

/* Archivos includos necesarios. */

494

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

"config.h"
<stdio.h>
<stdlib.h>
<unistd.h>
<string.h>
<pthread.h>
<sys/socket.h>
<sys/types.h>
<sys/un.h>
"modplcphy.h"

/* Declaracin de funciones privadas. */


static void *__modplcphy_detectproc__(void *);
static int __modplcphy_sendrecv__(modplcphy_hd *, void *, size_t, const void *,
size_t);

/* Implementacin de funciones pblicas. */


/*
Funcin modplcphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
modplcphy_hd *modplcphy_init(int sid)
{
/* Variables. */
int layer;
int result;
short int iface;
modplcphy_hd *handle;
struct sockaddr_un servaddr;

/* Capa a la que se quiere


accerder. */
/* Resultado de la solicitud. */
/* Identificadores de interfaces
fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Direccin del servidor. */

/* Crea un nuevo manejador de interfaz con la capa fsica del modem


PLC. */
handle = (modplcphy_hd *) malloc(sizeof(modplcphy_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa fsica del modem
PLC. */
while(1)
{
/* Abre una conexin con la cola de mensajes del driver del
modem PLC. */
handle->hq = socket(AF_LOCAL, SOCK_STREAM, 0);
if (handle->hq < 0) break;
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
sprintf(servaddr.sun_path, "/tmp/modemplc%i.str", sid);
if (connect(handle->hq, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0)
break;
/* Inicializa el manejador de tramas capturadas de cada una de las
interfaces fsicas. */
for(iface = 0; iface < 256; iface ++)
{
handle->iface[iface].recfun = NULL;
handle->iface[iface].param = NULL;
}
/* Inicializa semforo de exclusin mtua. */
if (pthread_mutex_init(&(handle->hm), NULL)) break;
if (pthread_mutex_unlock(&(handle->hm))) break;
/* Solicita acceder a la capa fsica del modem PLC. */
layer = 1;

FernandoArielBeunza79156

495

Tesis de Grado en Ingeniera Informtica


if (!__modplcphy_sendrecv__(handle, &result, sizeof(result),
&layer, sizeof(layer)))
break;
if (!result) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa fsica del modem PLC. */
pthread_mutex_destroy(&(handle->hm));
close(handle->hq);
free(handle);
return NULL;
}
/*
Funcin modplcphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modplcphy_release(modplcphy_hd *hd)
{
/* Variables. */
int op;
int result;
short int iface;

/* Operacin. */
/* Resultado de la operacin. */
/* Identificadores de interfaces
fsicas. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Libera el manejador de captura de tramas. */
for(iface = 0; iface < 256; iface ++)
modplcphy_notify(hd, (unsigned char) (iface & 0x00ff), NULL, NULL);
/* Solicita la finalizacin del acceso a la capa fsica del modem
PLC. */
op = MODDRVPHY_RELEASE;
if (!__modplcphy_sendrecv__(hd, &result, sizeof(result), &op,
sizeof(op)))
return 0;
if (!result) return 0;
/* Libera los recursos utilizados por el semforo de exclusin mtua. */
if (pthread_mutex_destroy(&(hd->hm))) return 0;
/* Libera los recursos utilizados por la interfaz con la capa fsica
del modem PLC. */
close(hd->hq);
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplcphy_sndframe:
Enva una trama.
*/
size_t modplcphy_sndframe(modplcphy_hd *hd, unsigned char iface,
const void *frame, size_t framesize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;

496

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Enva una trama. */
while(1)
{
/* Solicita el envo de una trama. */
op = MODDRVPHY_SNDFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el tamao de la trama. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &framesize,
sizeof(framesize)))
break;
/* Enva la trama. */
if (!__modplcphy_sendrecv__(hd, &framesize, sizeof(framesize),
frame, framesize))
break;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve la cantidad de bytes enviados. */
return framesize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
pthread_mutex_unlock(&(hd->hm));
/* No se pudo realizar el envo. */
return 0;
}
/*
Funcin modplcphy_capframe:
Captura una trama.
*/
int modplcphy_capframe(modplcphy_hd *hd, unsigned char iface, size_t framesize)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Solicita la captura una trama. */
result = 0;
while(1)
{
/* Solicita la captura de una trama. */
op = MODDRVPHY_CAPFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;

FernandoArielBeunza79156

497

Tesis de Grado en Ingeniera Informtica


/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el tamao de la trama. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &framesize,
sizeof(framesize));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modplcphy_getframe(modplcphy_hd *hd, unsigned char iface, void *frame,
size_t framesize)
{
/* Variables. */
int op;
/* Identificador de operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Obtiene una trama capturada previamente. */
while(1)
{
/* Solicita la leer una trama. */
op = MODDRVPHY_GETFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el tamao de la trama y obtiene la trama. */
if (!__modplcphy_sendrecv__(hd, frame, framesize, &framesize,
sizeof(framesize)))
break;
/* Obtiene el tamao de la trama leda. */
if (!__modplcphy_sendrecv__(hd, &framesize, sizeof(framesize),
NULL, 0))
break;
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve la cantidad de bytes ledos. */
return framesize;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */

498

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


pthread_mutex_unlock(&(hd->hm));
/* No se pudo obtener la trama capturada. */
return 0;
}
/*
Funcin modplcphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
int modplcphy_notify(modplcphy_hd *hd, unsigned char iface,
void (*func)(modplcphy_hd *, void *), void *param)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem
PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->iface[iface].recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->iface[iface].recfun))
{
if (pthread_mutex_lock(&(hd->hm))) return 0;
hd->iface[iface].recfun = (void (*)(void *, void *)) func;
hd->iface[iface].param = param;
if (pthread_mutex_unlock(&(hd->hm))) return 0;
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora
definida previamente se elimina esta ltima. */
if ((!func) && (hd->iface[iface].recfun))
{
if (pthread_mutex_lock(&(hd->hm))) return 0;
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = param;
if (pthread_mutex_unlock(&(hd->hm))) return 0;
if (pthread_join(hd->iface[iface].detectthread, NULL))
return 0;
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->iface[iface].recfun))
{
if (pthread_mutex_lock(&(hd->hm))) return 0;
hd->iface[iface].recfun = (void (*)(void *, void *)) func;
hd->iface[iface].param = param;
if (pthread_create(&(hd->iface[iface].detectthread), NULL,
__modplcphy_detectproc__, hd))
{
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = NULL;
pthread_mutex_lock(&(hd->hm));
return 0;
}
if (pthread_mutex_unlock(&(hd->hm))) return 0;
return 1;
}
/* No se pudo definir la funcin manejadora de tramas capturadas. */
return 0;
}
/*
Funcin modplcphy_poll:
Verifica la captura de una trama.

FernandoArielBeunza79156

499

Tesis de Grado en Ingeniera Informtica


*/
int modplcphy_poll(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Verifica la captura de una trama. */
result = 0;
while(1)
{
/* Solicita verificar la captura de una trama. */
op = MODDRVPHY_POLL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcphy_rsdframe:
Reenva una trama.
*/
int modplcphy_rsdframe(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Reenva una trama. */
result = 0;
while(1)
{
/* Solicita reenviar una trama. */
op = MODDRVPHY_RSDFRAME;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;

500

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado del reenvo de la trama. */
return result;
}
/*
Funcin modplcphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modplcphy_clrbuffer(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Limpia el buffer de captura de tramas. */
result = 0;
while(1)
{
/* Solicita limpiar el buffer de captura de tramas. */
op = MODDRVPHY_CLRBUFFER;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la limpieza del buffer. */
return result;
}
/*
Funcin modplcphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int modplcphy_sensechannel(modplcphy_hd *hd, unsigned char iface,
unsigned char level, long int waittime)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;

FernandoArielBeunza79156

501

Tesis de Grado en Ingeniera Informtica


/* Solicita el sensado del canal de comunicacin. */
result = 0;
while(1)
{
/* Solicita el sensado del estado del canal de comunicacin. */
op = MODDRVPHY_SENSECHANNEL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el nivel de seal. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &level,
sizeof(level)))
break;
/* Enva el tiempo de espera. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &waittime,
sizeof(waittime));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado del sensado del estado del canal de
comunicacin. */
return result;
}
/*
Funcin modplcphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplcphy_gensignal(modplcphy_hd *hd, unsigned char iface, int sig)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Solicita la generacin de la seal especificada. */
result = 0;
while(1)
{
/* Solicita la generacin de una seal. */
op = MODDRVPHY_GENSIGNAL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
if (!__modplcphy_sendrecv__(hd, NULL, 0, &iface,
sizeof(iface)))
break;
/* Enva el tipo de seal. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &sig,
sizeof(sig));

502

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la solicitud. */
return result;
}
/*
Funcin modplcphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modplcphy_tstreceive(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Identificador de operacin. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Realiza una prueba de recepcin. */
result = 0;
while(1)
{
/* Solicita realizar una prueba de recepcin. */
op = MODDRVPHY_TSTRECEIVE;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &result, sizeof(result), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el resultado de la prueba de recepcin. */
return result;
}
/*
Funcin modplcphy_status:
Devuelve el estado del modem PLC.
*/
int modplcphy_status(modplcphy_hd *hd)
{
/* Variables. */
int op;
int result;

/* Identificador de operacin. */
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;

FernandoArielBeunza79156

503

Tesis de Grado en Ingeniera Informtica


/* Obtiene el estado del modem PLC. */
op = MODDRVPHY_STATUS;
if (!__modplcphy_sendrecv__(hd, &result, sizeof(result), &op,
sizeof(op)))
result = 0;
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve el estado del modem PLC. */
return result;
}
/*
Funcin modplcphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplcphy_getpayloadsize(modplcphy_hd *hd, unsigned char iface)
{
/* Variables. */
int op;
/* Operacin. */
size_t payloadsize;
/* Cantidad de bytes que puede
contener una trama. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_lock(&(hd->hm))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener una trama. */
payloadsize = 0;
while(1)
{
/* Obtiene la cantidad mxima de bytes que puede contener una trama. */
op = MODDRVPHY_GETPAYLOADSIZE;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op, sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &payloadsize, sizeof(payloadsize), &iface,
sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del modem
PLC. */
if (pthread_mutex_unlock(&(hd->hm))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener una
trama. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplcphy_detectproc__:
Verifica la existencia de una trama capturada disponible para ser
leda.
*/
static void *__modplcphy_detectproc__(void *param)
{
/* Variables. */

504

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int op;
int captureflag;
short int i;
unsigned char iface;
modplcphy_hd *hd;
void (*func)(void *, void *);

/* Identificador de operacin. */
/* Indicador de captura de una
trama. */
/* Contador. */
/* Identificadores de interfaces
fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Manejador de captura de
tramas. */

/* Carga el manejador de interfaz con la capa fsica del modem PLC. */


hd = (modplcphy_hd *) param;
/* Obtiene el identificador de interface fsica asociado al hilo de
deteccin de recepcin. */
iface = 0;
if (pthread_mutex_lock(&(hd->hm))) return 0;
for(i = 0; i < 256; i++)
{
if (!pthread_equal(hd->iface[i].detectthread, pthread_self()))
continue;
iface = (unsigned char) (i & 0x00ff);
break;
}
pthread_mutex_unlock(&(hd->hm));
if (i > 255) return 0;
/* Verifica la existencia de una trama capturada. */
while(1)
{
/* Espera el permiso para poder comunicarse con el driver del
modem PLC. */
if (pthread_mutex_lock(&(hd->hm))) continue;
/* Verifica la captura de una trama. */
func = hd->iface[iface].recfun;
if (!func) break;
captureflag = 0;
while(1)
{
/* Solicita verificar la captura de una trama. */
op = MODDRVPHY_POLL;
if (!__modplcphy_sendrecv__(hd, NULL, 0, &op,
sizeof(op)))
break;
/* Enva el identificador de interfaz fsica. */
__modplcphy_sendrecv__(hd, &captureflag, sizeof(captureflag),
&iface, sizeof(iface));
break;
}
/* Permite a otro hilos poder comunicarse con el driver del
modem PLC. */
pthread_mutex_unlock(&(hd->hm));
/* Verifica si se ha detectado la captura de una trama para
invocar al manejador de trama capturadas. */
if (captureflag) func(hd, hd->iface[iface].param);
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
pthread_mutex_unlock(&(hd->hm));
pthread_exit(0);
}
/*
Funcin __modplcphy_sendrecv__:
Intercambia datos con el driver del modem PLC.

FernandoArielBeunza79156

505

Tesis de Grado en Ingeniera Informtica


*/
static int __modplcphy_sendrecv__(modplcphy_hd *hd, void *outdata,
size_t outsize, const void *indata,
size_t insize)
{
/* Variables. */
size_t last;
/* Cantidad de bytes enviados o
recibidos. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t received;
/* Cantidad de bytes recibidos. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Enva la operacin. */
sent = 0;
while((indata) && (sent < insize))
{
last = write(hd->hq, indata + sent, insize - sent);
sent += last;
}
/* Recibe la respuesta. */
received = 0;
while((outdata) && (received < outsize))
{
last = read(hd->hq, outdata + received, outsize - received);
received += last;
}
/* xito. */
return 1;
}

C.4.4. Driver del Modem PLC modem_driver


En esta seccin se detalla el cdigo fuente del driver del modem PLC, que se compone de los
siguientes archivos:

506

Archivo config.h: en este archivo se definen parmetros de configuracin del driver del
del modem PLC que no pueden ser modificados en tiempo de ejecucin.

Archivo serial.h: en este archivo se declaran primitivas con funcionalidades referentes a


la comunicacin por puerto serie.

Archivo serial.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo serial.h.

Archivo modplc.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa fsica, de enlace y de sesin. Dichas primitivas brindan un conjunto de
funcionalidades que permiten la comunicacin con las capas mencionadas implementadas
en el modem PLC.

Archivo modplc.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo modplc.h.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Archivo modsp.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa de sesin. Dichas primitivas brindan un conjunto de funcionalidades que
permiten la comunicacin con las capa de sesin implementada en el modem PLC.

Archivo modsp.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo modsp.h.

Archivo moddl.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa de enlace. Dichas primitivas brindan un conjunto de funcionalidades que
permiten la comunicacin con las capa de enlace implementada en el modem PLC.

Archivo moddl.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo moddl.h.

Archivo modphy.h: en este archivo se declaran las primitivas correspondientes al interfaz


con la capa fsica. Dichas primitivas brindan un conjunto de funcionalidades que permiten
la comunicacin con las capa fsica implementada en el modem PLC.

Archivo modphy.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo modphy.h.

Archivo moddrv.h: en este archivo se declaran las primitivas correspondientes al driver


del modem PLC. Dichas primitivas brindan un conjunto de funcionalidades que permite a
las interfaces mencionadas anteriormente comunicarse con el modem PLC.

Archivo moddrv.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo moddrv.h.

Archivo modem_driver.c: en este archivo se encuentra implementada la inicializacin de


la ejecucin del driver del modem PLC.

C.4.4.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Interfaz del modem PLC. */


/* Tipos de prompt utilizados. */
#define MODPLC_INITPROMPT
#define MODPLC_LAYPROMPT
#define MODPLC_NORMPROMPT
#define MODPLC_PARAMPROMPT

'#'
'?'
'$'
'>'

/* Tipos de reset. */
#define MODPLC_NORMRESET
#define MODPLC_PARAMRESET

'0'
'$'

FernandoArielBeunza79156

507

Tesis de Grado en Ingeniera Informtica


/* Cdigo de operaciones de la capa fsica. */
#define MODPLCPHY_RESET
#define MODPLCPHY_SNDFRAME
#define MODPLCPHY_CAPFRAME
#define MODPLCPHY_GETFRAME
#define MODPLCPHY_POLL
#define MODPLCPHY_RSDFRAME
#define MODPLCPHY_CLRBUFFER
#define MODPLCPHY_SENSECHANNEL
#define MODPLCPHY_GENSIGNAL
#define MODPLCPHY_TSTRECEIVE
#define MODPLCPHY_GETPAYLOADSIZE

MODPLC_NORMRESET
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
'a'

/* Tipos de seal. */
#define MODPLCPHY_NOISESIGNAL
#define MODPLCPHY_TESTSIGNAL1
#define MODPLCPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Cdigo de operaciones de la capa de enlace. */


#define MODPLCDL_RESET
#define MODPLCDL_OPEN
#define MODPLCDL_CLOSE
#define MODPLCDL_SEND
#define MODPLCDL_RECEIVE
#define MODPLCDL_POLL
#define MODPLCDL_GETADDRESS
#define MODPLCDL_ADDLOGADDRESS
#define MODPLCDL_DELLOGADDRESS
#define MODPLCDL_GETPHYADDRESS
#define MODPLCDL_GETPAYLOADSIZE

MODPLC_NORMRESET
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
'a'

/* Cdigo de operaciones de la capa de sesin. */


#define MODPLCSP_RESET
#define MODPLCSP_PUBLISH
#define MODPLCSP_SUBSCRIBE
#define MODPLCSP_LEAVE
#define MODPLCSP_SEND
#define MODPLCSP_RECEIVE
#define MODPLCSP_POLL
#define MODPLCSP_GETPAYLOADSIZE

MODPLC_NORMRESET
'1'
'2'
'3'
'4'
'5'
'6'
'7'

/* Driver del modem PLC. */


/* Cdigos de operaciones de la interfaz de la capa fsica. */
#define MODDRVPHY_RELEASE
0x00
#define MODDRVPHY_SNDFRAME
0x01
#define MODDRVPHY_CAPFRAME
0x02
#define MODDRVPHY_GETFRAME
0x03
#define MODDRVPHY_POLL
0x04
#define MODDRVPHY_RSDFRAME
0x05
#define MODDRVPHY_CLRBUFFER
0x06
#define MODDRVPHY_SENSECHANNEL
0x07
#define MODDRVPHY_GENSIGNAL
0x08
#define MODDRVPHY_TSTRECEIVE
0x09
#define MODDRVPHY_STATUS
0x0a
#define MODDRVPHY_GETPAYLOADSIZE
0x0b
/* Cdigos de operaciones de la interfaz de la capa de enlace. */
#define MODDRVDL_CLOSE
0x00
#define MODDRVDL_OPEN
0x01
#define MODDRVDL_SEND
0x02
#define MODDRVDL_RECEIVE
0x03
#define MODDRVDL_POLL
0x04
#define MODDRVDL_GETADDRESS
0x05
#define MODDRVDL_ADDLOGADDRESS
0x06
#define MODDRVDL_DELLOGADDRESS
0x07
#define MODDRVDL_GETPHYADDRESS
0x08
#define MODDRVDL_STATUS
0x09
#define MODDRVDL_GETPAYLOADSIZE
0x0a

508

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Cdigos de operaciones de la interfaz de la capa de sesin. */
#define MODDRVSP_RELEASE
0x00
#define MODDRVSP_PUBLISH
0x01
#define MODDRVSP_SUBSCRIBE
0x02
#define MODDRVSP_LEAVE
0x03
#define MODDRVSP_SEND
0x04
#define MODDRVSP_RECEIVE
0x05
#define MODDRVSP_POLL
0x06
#define MODDRVSP_STATUS
0x07
#define MODDRVSP_GETPAYLOADSIZE
0x08

/* Interfaz con el modem PLC. */


/* Tamaoo del buffer. */
#define MODPLC_BUFFERSIZE

4096

/* Cantidad de bytes de una lnea por envo. */


#define MODPLC_FRAGMENTLINESIZE

#endif

C.4.4.2. Archivo serial.h


/*
serial.h:
Declaracin de funciones referentes a la interfaz de comunicacin por
puerto serie.
*/

#if !defined(__SERIAL_H__)
#define __SERIAL_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>
#include <termios.h>

/* Definicin de tipos. */
/* Manejador de interfaz de comunicacin por puerto serie. */
typedef struct
{
int serialhd;
/* Manejador de interfaz de puerto
serie. */
struct termios oldtio;
/* Antigua configuracin de la
interfaz de puerto serie. */
struct termios newtio;
/* Nueva configuracin de la
interfaz de puerto serie. */
} serial_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin serial_init:
Inicializa la interfaz de comunicacin por puerto serie.
*/
serial_hd *serial_init(int);
/*
Funcin serial_release:
Libera los recursos utilizdos por la interfaz de comunicacin por puerto
serie.

FernandoArielBeunza79156

509

Tesis de Grado en Ingeniera Informtica


*/
int serial_release(serial_hd *);
/*
Funcin serial_send:
Enva un mensaje a travs de la interfaz de comunicacin por puerto serie.
*/
size_t serial_send(serial_hd *, const void *, size_t);
/*
Funcin serial_receive:
Recibe un mensaje a por medio de la interfaz de comunicacin por puerto
serie.
*/
size_t serial_receive(serial_hd *, void *, size_t);
/*
Funcin serial_poll:
Devuelve si hay un mensaje a la espera de ser recibido.
*/
int serial_poll(serial_hd *);

#endif

C.4.4.3. Archivo serial.c


/*
serial.c:
Implementacin de funciones referentes a la interfaz de comunicacin por
puerto serie.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "serial.h"

/* Implementacin de funciones pblicas. */


/*
Funcin serial_init:
Inicializa la interfaz de comunicacin por puerto serie.
*/
serial_hd *serial_init(int id)
{
/* Variables. */
serial_hd *handle;
char iname[256];

/* Manejador de la interfaz. */
/* Nombre de la interfaz. */

/* Verifica la validez del identificador de la interfaz de comunicacin por


puerto serie. */
if (id < 1) return 0;
/* Crea un nuevo manejador de interfaz de comunicacin por puerto serie. */
handle = (serial_hd *) malloc(sizeof(serial_hd));
if (!handle) return NULL;

510

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Inicializa la interfaz de comunicacin por puerto serie. */
while(1)
{
/* Abre la interfaz de comunicacin por puerto serie. */
if (id < 15)
sprintf(iname, "/dev/ttyS%i", id - 1);
else
sprintf(iname, "/dev/ttyUSB%i", id - 15);
handle->serialhd = open(iname, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (handle->serialhd < 0) break;
/* Configura la interfaz de comunicacin por puerto serie. */
tcgetattr(handle->serialhd, &(handle->oldtio));
handle->newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD;
handle->newtio.c_iflag = IGNPAR;
handle->newtio.c_oflag = 0;
handle->newtio.c_lflag = 0;
tcflush(handle->serialhd, TCIFLUSH);
tcsetattr(handle->serialhd, TCSANOW, &(handle->newtio));
/* Devuelve el manejador de la interfaz de comunicacin por puerto
serie. */
return handle;
}
/* No se pudo inicializar la interfaz de comunicacin por puerto serie. */
free(handle);
return NULL;
}
/*
Funcin serial_release:
Libera los recursos utilizdos por la interfaz de comunicacin por puerto
serie.
*/
int serial_release(serial_hd *hd)
{
/* Verifica la validez del manejador de la interfaz de comunicacin por
puerto serie. */
if (!hd) return 0;
/* Restaura la antigua configuracin de la interfaz de comunicacin por
puerto serie. */
tcsetattr(hd->serialhd, TCSANOW, &(hd->oldtio));
/* Libera los recursos utilizados por la interfaz de comunicacin por
puerto serie. */
close(hd->serialhd);
free(hd);
/* xito. */
return 1;
}
/*
Funcin serial_send:
Enva un mensaje a travs de la interfaz de comunicacin por puerto serie.
*/
size_t serial_send(serial_hd *hd, const void *msg, size_t msgsize)
{
/* Variables. */
size_t sent;
/* Cantidad de bytes enviados. */
unsigned char *ptr;
/* Puntero al mensaje. */

/* Verifica la validez del manejador de la interfaz de comunicacin por


puerto serie. */
if (!hd) return 0;
/* Enva un mensaje. */
sent = 0;

FernandoArielBeunza79156

511

Tesis de Grado en Ingeniera Informtica


ptr = (unsigned char *) msg;
usleep(10000UL);
while(sent < msgsize)
sent += write(hd->serialhd, ptr + sent, msgsize - sent);
/* Devuelve la cantidad de bytes enviados. */
return sent;
}
/*
Funcin serial_receive:
Recibe un mensaje por medio de la interfaz de comunicacin por puerto
serie.
*/
size_t serial_receive(serial_hd *hd, void *msg, size_t msgsize)
{
/* Verifica la validez del manejador de la interfaz de comunicacin por
puerto serie. */
if (!hd) return 0;
/* Espera a que el buffer de recepcin tenga algn contenido. */
usleep(10000UL);
while(!serial_poll(hd));
/* Recibe un mensaje. */
return read(hd->serialhd, (unsigned char *) msg, msgsize);
}
/*
Funcin serial_poll:
Verifica la llegada de un nuevo mensaje.
*/
int serial_poll(serial_hd *hd)
{
/* Variables. */
size_t received;

/* Cantidad de bytes almacenados en


el buffer de entrada. */

/* Verifica la validez del manejador de la interfaz de comunicacin por


puerto serie. */
if (!hd) return 0;
/* Verifica si el buffer no se encuentra vaco. */
ioctl(hd->serialhd, FIONREAD, &received);
return (received != 0);
}

C.4.4.4. Archivo modplc.h


/*
modplc.h:
Declaracin de funciones referentes a la interfaz con el modem PLC.
*/

#if !defined(__MODPLC_H__)
#define __MODPLC_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "serial.h"

/* Definicin de tipos. */
/* Direccin fsica del modem PLC. */

512

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


typedef unsigned char modplc_dlphyaddr[8];
/* Direccin lgica del modem PLC. */
typedef unsigned long int modplc_dllogaddr;
/* Identificador de grupo. */
typedef unsigned char modplc_spgrpid;
/* Manejador de interfaz con el modem PLC. */
typedef struct
{
serial_hd *serialhd;

int layer;
int status;
int debugmode;
} modplc_hd;

/* Manejador de interfaz de
comunicacin por puerto
serie. */
/* Capa del modem PLC utilizada. */
/* Estado del modem PLC. */
/* Indicador de modo depuracin. */

/* Definicin de constantes. */
/* Capas de acceso. */
#define MODPLC_PHYSICALLAYER
#define MODPLC_DATALINKLAYER
#define MODPLC_SESSIONLAYER

0x01
0x02
0x03

/* Tipos de seales. */
#define MODPLC_PHYNOISESIGNAL
#define MODPLC_PHYTESTSIGNAL1
#define MODPLC_PHYTESTSIGNAL2

0x01
0x02
0x03

/* Declaracin de funciones pblicas. */


/*
Funcin modplc_init:
Inicializa los recursos utilizados por la interfaz con el modem PLC.
*/
modplc_hd *modplc_init(int, int, int);
/*
Funcin modplc_release:
Libera los recursos utilizados por la interfaz con el modem PLC.
*/
int modplc_release(modplc_hd *);
/*
Funcin modplc_status:
Devuelve el estado del modem PLC.
*/
int modplc_status(modplc_hd *);
/*
Funcin modplc_physndframe:
Enva una trama por medio de la capa fsica del modem PLC.
*/
size_t modplc_physndframe(modplc_hd *, unsigned char, const void *, size_t);
/*
Funcin modplc_phycapframe:
Captura una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phycapframe(modplc_hd *, unsigned char, size_t);
/*
Funcin modplc_phygetframe:
Obtiene una trama capturada previamente por medio de la capa fsica del
modem PLC.
*/
size_t modplc_phygetframe(modplc_hd *, unsigned char, void *, size_t);

FernandoArielBeunza79156

513

Tesis de Grado en Ingeniera Informtica


/*
Funcin phy_poll:
Verifica la captura de una trama por medio de la capa fsica del
modem PLC.
*/
int modplc_phypoll(modplc_hd *, unsigned char);
/*
Funcin modplc_phyrsdframe:
Reenva una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phyrsdframe(modplc_hd *, unsigned char);
/*
Funcin modplc_phyclrbuffer:
Limpia el buffer de captura de tramas de la capa fsica del modem PLC.
*/
int modplc_phyclrbuffer(modplc_hd *, unsigned char);
/*
Funcin modplc_physensechannel:
Sensa el estado del canal de comunicacin por medio de la capa fsica
del modem PLC.
*/
int modplc_physensechannel(modplc_hd *, unsigned char, unsigned char,
long int);
/*
Funcin modplc_phygensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplc_phygensignal(modplc_hd *, unsigned char, int);
/*
Funcin modplc_phytstreceive:
Realiza una prueba de recepcin de la capa fsica del modem PLC.
*/
int modplc_phytstreceive(modplc_hd *, unsigned char);
/*
Funcin modplc_phygetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplc_phygetpayloadsize(modplc_hd *, unsigned char);
/*
Funcin modplc_dlopen:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlopen(modplc_hd *, unsigned char, unsigned char);
/*
Funcin modplc_dlclose:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlclose(modplc_hd *, int);
/*
Funcin modplc_dlsend:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlsend(modplc_hd *, int, modplc_dlphyaddr, unsigned char,
const void *, size_t);
/*
Funcin modplc_dlreceive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlreceive(modplc_hd *, int, modplc_dlphyaddr, void *, size_t);

514

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplc_dlpoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de enlace
del modem PLC.
*/
int modplc_dlpoll(modplc_hd *, int);
/*
Funcin modplc_dlgetaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplc_dlgetaddress(modplc_hd *, unsigned char, modplc_dlphyaddr);
/*
Funcin modplc_dladdlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dladdlogaddress(modplc_hd *, unsigned char, unsigned char,
modplc_dllogaddr);
/*
Funcin modplc_dldellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dldellogaddress(modplc_hd *, unsigned char, unsigned char,
modplc_dllogaddr);
/*
Funcin modplc_dlgetphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa
de enlace del modem PLC.
*/
int modplc_dlgetphyaddress(modplc_hd *, unsigned char, unsigned char,
modplc_dllogaddr, modplc_dlphyaddr);
/*
Funcin modplc_dlgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de enlace del modem PLC.
*/
size_t modplc_dlgetpayloadsize(modplc_hd *, unsigned char);
/*
Funcin modplc_sppublish:
Registra el dispositivo como publicador del grupo de difusin
especificado de la capa de sesin del modem PLC.
*/
int modplc_sppublish(modplc_hd *, modplc_spgrpid);
/*
Funcin modplc_spsubscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado de la capa de sesin del modem PLC.
*/
int modplc_spsubscribe(modplc_hd *, modplc_spgrpid);
/*
Funcin modplc_spleave:
Desvincula el dispositivo del grupo de difusin especificado de la capa
de sesin del modem PLC.
*/
int modplc_spleave(modplc_hd *, modplc_spgrpid);
/*
Funcin modplc_spsend:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spsend(modplc_hd *, modplc_spgrpid, int, const void *, size_t);
/*

FernandoArielBeunza79156

515

Tesis de Grado en Ingeniera Informtica


Funcin modplc_spreceive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spreceive(modplc_hd *, modplc_spgrpid *, void *, size_t);
/*
Funcin modplc_sppoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de sesin
del modem PLC.
*/
int modplc_sppoll(modplc_hd *);
/*
Funcin modplc_spgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de sesin del modem PLC.
*/
size_t modplc_spgetpayloadsize(modplc_hd *);

#endif

C.4.4.5. Archivo modplc.c


/*
modplc.c:
Implementacin de funciones referentes a la interfaz con el modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "serial.h"
#include "modplc.h"

/* Declaracin de funciones privadas. */


static char __modplc_sendcmdline__(modplc_hd *, const char *, char *, size_t);
static int __modplc_sendcmd__(modplc_hd *, char, const char *, void **,
const void *, const char *, void **, void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modplc_init:
Inicializa los recursos utilizados por la interfaz con el modem PLC.
*/
modplc_hd *modplc_init(int sid, int layer, int debugmode)
{
/* Variables. */
char prompt;
modplc_hd *handle;
char cmdline[MODPLC_BUFFERSIZE];
char respline[MODPLC_BUFFERSIZE];

/* Smbolo de la lnea de
comando. */
/* Manejador de interfaz con el
modem PLC. */
/* Lnea de comando. */
/* Lnea de respuesta de
comando. */

/* Crea un nuevo manejador de interfaz con el modem PLC. */


handle = (modplc_hd *) malloc(sizeof(modplc_hd));
if (!handle) return NULL;
/* Inicializa la interfaz de comunicacin por puerto serie. */

516

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


handle->serialhd = serial_init(sid);
if (!handle->serialhd)
{
free(handle);
return NULL;
}
/* Si es requerido establece el modo depuracin. */
handle->debugmode = 0;
if (debugmode) handle->debugmode = 1;
/* Inicializa la interfaz con el modem PLC. */
while(1)
{
/* Inicializa el modem PLC. */
*(cmdline + 0) = '\n';
*(cmdline + 1) = 0;
prompt = __modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE);
if (prompt == MODPLC_INITPROMPT)
sprintf(cmdline, "reset");
else if (prompt == MODPLC_LAYPROMPT)
{
*(cmdline + 0) = MODPLC_NORMRESET;
*(cmdline + 1) = 0;
}
else if (prompt == MODPLC_NORMPROMPT)
{
*(cmdline + 0) = MODPLC_NORMRESET;
*(cmdline + 1) = 0;
}
else if (prompt == MODPLC_PARAMPROMPT)
{
*(cmdline + 0) = MODPLC_PARAMRESET;
*(cmdline + 1) = 0;
}
else
break;
strcat(cmdline, "\n");
if (__modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_INITPROMPT)
break;
sprintf(cmdline, "init\n");
if (__modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_LAYPROMPT)
break;
/* Establece la capa a la cual se quiere acceder. */
handle->layer = layer;
if (handle->layer == MODPLC_PHYSICALLAYER)
*(cmdline + 0) = MODPLC_PHYSICALLAYER + '0';
else if (handle->layer == MODPLC_DATALINKLAYER)
*(cmdline + 0) = MODPLC_DATALINKLAYER + '0';
else if (handle->layer == MODPLC_SESSIONLAYER)
*(cmdline + 0) = MODPLC_SESSIONLAYER + '0';
else
break;
*(cmdline + 1) = '\n';
*(cmdline + 2) = 0;
if (__modplc_sendcmdline__(handle, cmdline, respline,
MODPLC_BUFFERSIZE) != MODPLC_NORMPROMPT)
break;
/* Modem PLC en estado activo. */
handle->status = 1;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con el modem PLC. */

FernandoArielBeunza79156

517

Tesis de Grado en Ingeniera Informtica


modplc_release(handle);
return NULL;
}
/*
Funcin modplc_release:
Libera los recursos utilizados por la interfaz con el modem PLC.
*/
int modplc_release(modplc_hd *hd)
{
/* Verifica que el manejador de interfaz con el modem PLC exista. */
if (!hd) return 0;
/* Libera la interfaz de comunicacin por puerto serie. */
serial_release(hd->serialhd);
/* Libera los recursos utilizados por la interfaz con el modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modplc_status:
Devuelve el estado del modem PLC.
*/
int modplc_status(modplc_hd *hd)
{
/* Verifica que el manejador de interfaz con el modem PLC exista. */
if (!hd) return 0;
/* Verifica que el modem PLC se encuentre activo. */
if (!hd->status) return 0;
if (__modplc_sendcmdline__(hd, "\n", NULL, MODPLC_BUFFERSIZE) ==
MODPLC_NORMPROMPT)
return 1;
hd->status = 0;
return 0;
}
/*
Funcin modplc_physndframe:
Enva una trama por medio de la capa fsica del modem PLC.
*/
size_t modplc_physndframe(modplc_hd *hd, unsigned char iface,
const void *frame, size_t framesize)
{
/* Variables. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Enva una trama. */
inparam[0] = &iface;
inparam[1] = &framesize;
outparam[0] = &framesize;
if (__modplc_sendcmd__(hd, MODPLCPHY_SNDFRAME, "bs", inparam, frame,
"s", outparam, NULL))
return framesize;
return 0;
}

518

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplc_phycapframe:
Captura una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phycapframe(modplc_hd *hd, unsigned char iface, size_t framesize)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Captura una trama. */
inparam[0] = &iface;
inparam[1] = &framesize;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_CAPFRAME, "bs", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_phygetframe:
Obtiene una trama capturada previamente por medio de la capa fsica del
modem PLC.
*/
size_t modplc_phygetframe(modplc_hd *hd, unsigned char iface, void *frame,
size_t framesize)
{
/* Variables. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Obtiene una trama capturada. */
inparam[0] = &iface;
inparam[1] = &framesize;
outparam[0] = &framesize;
if (__modplc_sendcmd__(hd, MODPLCPHY_GETFRAME, "bs", inparam, NULL,
"s", outparam, frame))
return framesize;
return 0;
}
/*
Funcin modplc_phypoll:
Verifica la captura de una trama por medio de la capa fsica del modem
PLC.
*/
int modplc_phypoll(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
void *inparam[1];

FernandoArielBeunza79156

/* Resultado del comando. */


/* Parmetros de entrada del

519

Tesis de Grado en Ingeniera Informtica


void *outparam[1];

comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Verifica la captura de una trama. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_POLL, "b", inparam, NULL,
outparam, NULL))
return (result == 1);
return 0;

"b",

}
/*
Funcin modplc_phyrsdframe:
Reenva una trama por medio de la capa fsica del modem PLC.
*/
int modplc_phyrsdframe(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Reenva una trama. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_RSDFRAME, "b", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_phyclrbuffer:
Limpia el buffer de captura de tramas de la capa fsica del modem PLC.
*/
int modplc_phyclrbuffer(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Limpia el buffer de captura de tramas. */
inparam[0] = &iface;

520

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_CLRBUFFER, "b", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_physensechannel:
Sensa el estado del canal de comunicacin por medio de la capa fsica
del modem PLC.
*/
int modplc_physensechannel(modplc_hd *hd, unsigned char iface,
unsigned char level, long int waittime)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Sensa el estado del canal de comunicacin. */
inparam[0] = &iface;
inparam[1] = &level;
inparam[2] = &waittime;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_SENSECHANNEL, "bbl", inparam,
NULL, "b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_phygensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modplc_phygensignal(modplc_hd *hd, unsigned char iface, int sig)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Genera la seal especificada. */
inparam[0] = &iface;
inparam[1] = &sig;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_GENSIGNAL, "bb", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*

FernandoArielBeunza79156

521

Tesis de Grado en Ingeniera Informtica


Funcin modplc_phytstreceive:
Realiza una prueba de recepcin de la capa fsica del modem PLC.
*/
int modplc_phytstreceive(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Realiza una prueba de recepcin. */
inparam[0] = &iface;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, MODPLCPHY_TSTRECEIVE, "b", inparam, NULL,
"b", outparam, NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_phygetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modplc_phygetpayloadsize(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned short int payloadsize;
/* Cantidad mxima de bytes que
puede contener una trama. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa fsica. */
if (hd->layer != MODPLC_PHYSICALLAYER) return 0;
/* Devuelve la cantidad mxima de byes que puede contener una trama. */
inparam[0] = &iface;
outparam[0] = &payloadsize;
if (__modplc_sendcmd__(hd, MODPLCPHY_GETPAYLOADSIZE, "b", inparam,
NULL, "s", outparam, NULL))
return (size_t) payloadsize;
return 0;
}
/*
Funcin modplc_dlopen:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlopen(modplc_hd *hd, unsigned char iface, unsigned char prot)
{
/* Variables. */
unsigned short int handle;
/* Manejador de conexin. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

522

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Abre una conexin. */
inparam[0] = &iface;
inparam[1] = &prot;
outparam[0] = &handle;
if (__modplc_sendcmd__(hd, '1', "bb", inparam, NULL,
NULL))
return (int) handle;
return 0;

"s", outparam,

}
/*
Funcin modplc_dlclose:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int modplc_dlclose(modplc_hd *hd, int handle)
{
/* Variables. */
unsigned char result;
void *inparam[2];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Cierra una conexin. */
inparam[0] = &handle;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '2', "s", inparam, NULL,
NULL))
return (result == 1);
return 0;

"b", outparam,

}
/*
Funcin modplc_dlsend:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlsend(modplc_hd *hd, int handle, modplc_dlphyaddr addr,
unsigned char prio, const void *msg, size_t msgsize)
{
/* Variables. */
void *inparam[4];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Enva un mensaje. */
inparam[0] = &handle;
inparam[1] = addr;
inparam[2] = &prio;

FernandoArielBeunza79156

523

Tesis de Grado en Ingeniera Informtica


inparam[3] = &msgsize;
outparam[0] = &msgsize;
if (__modplc_sendcmd__(hd, '3', "sabs", inparam, msg,
NULL))
return msgsize;
return 0;

"s", outparam,

}
/*
Funcin modplc_dlreceive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t modplc_dlreceive(modplc_hd *hd, int handle, modplc_dlphyaddr addr,
void *msg, size_t msgsize)
{
/* Variables. */
void *inparam[2];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Recibe un mensaje. */
inparam[0] = &handle;
inparam[1] = &msgsize;
outparam[0] = addr;
outparam[1] = &msgsize;
if (__modplc_sendcmd__(hd, '4', "ss", inparam, NULL,
msg))
return msgsize;
return 0;

"as", outparam,

}
/*
Funcin modplc_dlpoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de enlace del
modem PLC.
*/
int modplc_dlpoll(modplc_hd *hd, int handle)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Verifica la llegada de un nuevo mensaje. */
inparam[0] = &handle;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '5', "s", inparam, NULL,
NULL))
return (result == 1);
return 0;

"b", outparam,

}
/*
Funcin modplc_dlgetaddress:

524

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int modplc_dlgetaddress(modplc_hd *hd, unsigned char iface,
modplc_dlphyaddr paddr)
{
/* Variables. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Devuelve la direccin fsica. */
inparam[0] = &iface;
outparam[0] = paddr;
return __modplc_sendcmd__(hd, '6', "b", inparam, NULL,
NULL);

"a", outparam,

}
/*
Funcin modplc_dladdlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dladdlogaddress(modplc_hd *hd, unsigned char iface,
unsigned char prot, modplc_dllogaddr laddr)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Agrega una nueva direccin lgica. */
inparam[0] = &iface;
inparam[1] = &prot;
inparam[2] = &laddr;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '7', "bbl", inparam, NULL,
NULL))
return (result == 1);
return 0;

"b", outparam,

}
/*
Funcin modplc_dldellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int modplc_dldellogaddress(modplc_hd *hd, unsigned char iface,
unsigned char prot, modplc_dllogaddr laddr)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

FernandoArielBeunza79156

525

Tesis de Grado en Ingeniera Informtica


/* Verifica que el manejador de interfaz con el modem PLC exista. */
if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Elimina una direccin lgica. */
inparam[0] = &iface;
inparam[1] = &prot;
inparam[2] = &laddr;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '8', "bbl", inparam, NULL,
NULL))
return (result == 1);
return 0;

"b", outparam,

}
/*
Funcin modplc_dlgetphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa
de enlace del modem PLC.
*/
int modplc_dlgetphyaddress(modplc_hd *hd, unsigned char iface,
unsigned char prot, modplc_dllogaddr laddr,
modplc_dlphyaddr paddr)
{
/* Variables. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;
/* Devuelve la direccin fsica asociada a la direccin lgica. */
inparam[0] = &iface;
inparam[1] = &prot;
inparam[2] = &laddr;
outparam[0] = paddr;
return __modplc_sendcmd__(hd, '9', "bbl", inparam, NULL, "a",
outparam, NULL);
}
/*
Funcin modplc_dlgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de enlace del modem PLC.
*/
size_t modplc_dlgetpayloadsize(modplc_hd *hd, unsigned char iface)
{
/* Variables. */
unsigned short int payloadsize;
/* Cantidad mxima de bytes que
puede contener una trama. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de enlace. */
if (hd->layer != MODPLC_DATALINKLAYER) return 0;

526

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Devuelve la cantidad mxima de byes que puede contener un mensaje. */
inparam[0] = &iface;
outparam[0] = &payloadsize;
if (__modplc_sendcmd__(hd, 'a', "b", inparam, NULL, "s", outparam,
NULL))
return (size_t) payloadsize;
return 0;
}
/*
Funcin modplc_sppublish:
Registra el dispositivo como publicador del grupo de difusin
especificado de la capa de sesin del modem PLC.
*/
int modplc_sppublish(modplc_hd *hd, modplc_spgrpid grpid)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Registra el dispositivo como publicador del grupo de difusin
especificado. */
inparam[0] = &grpid;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '1', "b", inparam, NULL, "b", outparam,
NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_spsubscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado de la capa de sesin del modem PLC.
*/
int modplc_spsubscribe(modplc_hd *hd, modplc_spgrpid grpid)
{
/* Variables. */
unsigned char result;
/* Resultado del comando. */
void *inparam[1];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Registra el dispositivo como suscriptor del grupo de difusin
especificado. */
inparam[0] = &grpid;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '2', "b", inparam, NULL, "b", outparam,
NULL))
return (result == 1);
return 0;
}

FernandoArielBeunza79156

527

Tesis de Grado en Ingeniera Informtica


/*
Funcin modplc_spleave:
Desvincula el dispositivo del grupo de difusin especificado de la capa
de sesin del modem PLC.
*/
int modplc_spleave(modplc_hd *hd, modplc_spgrpid grpid)
{
/* Variables. */
unsigned char result;
void *inparam[1];
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de entrada del
comando. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Desvincula el dispositivo del grupo de difusin especificado. */
inparam[0] = &grpid;
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '3', "b", inparam, NULL, "b", outparam,
NULL))
return (result == 1);
return 0;
}
/*
Funcin modplc_spsend:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spsend(modplc_hd *hd, modplc_spgrpid grpid, int nosec,
const void *msg, size_t msgsize)
{
/* Variables. */
void *inparam[3];
/* Parmetros de entrada del
comando. */
void *outparam[1];
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Enva un mensaje. */
inparam[0] = &grpid;
inparam[1] = &nosec;
inparam[2] = &msgsize;
outparam[0] = &msgsize;
if (__modplc_sendcmd__(hd, '4', "bbs", inparam, msg,
NULL))
return msgsize;
return 0;

"s", outparam,

}
/*
Funcin modplc_spreceive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modplc_spreceive(modplc_hd *hd, modplc_spgrpid *grpid, void *msg,
size_t msgsize)
{
/* Variables. */
void *inparam[1];
/* Parmetros de entrada del
comando. */

528

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


void *outparam[2];

/* Parmetros de salida del


comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Recibe un mensaje. */
inparam[0] = &msgsize;
outparam[0] = grpid;
outparam[1] = &msgsize;
if (__modplc_sendcmd__(hd, '5', "s", inparam, NULL,
msg))
return msgsize;
return 0;

"bs", outparam,

}
/*
Funcin modplc_sppoll:
Verifica la llegada de un nuevo mensaje por medio de la capa de sesin
del modem PLC.
*/
int modplc_sppoll(modplc_hd *hd)
{
/* Variables. */
unsigned char result;
void *outparam[1];

/* Resultado del comando. */


/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Verifica la llegada de un nuevo mensaje. */
outparam[0] = &result;
if (__modplc_sendcmd__(hd, '6', "", NULL, NULL,
return (result == 1);
return 0;

"b", outparam, NULL))

}
/*
Funcin modplc_spgetpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de sesin del modem PLC.
*/
size_t modplc_spgetpayloadsize(modplc_hd *hd)
{
/* Variables. */
unsigned short int payloadsize;
void *outparam[1];

/* Cantidad mxima de bytes que


puede contener una trama. */
/* Parmetros de salida del
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Verifica que la capa a la que se accede es la capa de sesin. */
if (hd->layer != MODPLC_SESSIONLAYER) return 0;
/* Devuelve la cantidad mxima de byes que puede contener un
mensaje. */
outparam[0] = &payloadsize;
if (__modplc_sendcmd__(hd, '7', "", NULL, NULL, "s", outparam, NULL))
return (size_t) payloadsize;

FernandoArielBeunza79156

529

Tesis de Grado en Ingeniera Informtica


return 0;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modplc_sendcmdline__:
Enva una lnea de comando por medio de la interfaz de comunicacin por
puerto serie.
*/
static char __modplc_sendcmdline__(modplc_hd *hd, const char *cmdline,
char *resp, size_t respsize)
{
/* Variables. */
size_t send;
/* Cantidad de bytes por envo. */
size_t size;
/* Tamaoo de la lnea de
respuesta. */
char *lastchar;
/* Puntero al ltimo caracter. */
char respline[MODPLC_BUFFERSIZE];
/* Respuesta a la lnea de
comando. */

/* Verifica que el manejador de interfaz con el modem PLC exista. */


if (!hd) return 0;
/* Recibe la respuesta al comando. */
size = 0;
*respline = 0;
while(size < respsize)
{
/* Enva un fragmento de la lnea de comando. */
send = strlen(cmdline) - size;
if (send > MODPLC_FRAGMENTLINESIZE)
send = MODPLC_FRAGMENTLINESIZE;
if (size < strlen(cmdline))
serial_send(hd->serialhd, cmdline + size, send);
/* Recibe la respuesta. */
size += serial_receive(hd->serialhd, respline + size, respsize - size);
*(respline + size) = 0;
/* Verifica si se recibi el smbolo de la lnea de comando. */
lastchar = strchr(respline, '#');
if (lastchar) break;
lastchar = strchr(respline, '?');
if (lastchar) break;
lastchar = strchr(respline, '$');
if (lastchar) break;
lastchar = strchr(respline, '>');
if (lastchar) break;
if (size > respsize)
{
lastchar = respline + size - 1;
break;
}
}
/* Devuelve la respuesta al comando. */
if (resp) strcpy(resp, respline);
if (hd->debugmode && size)
{
printf("%s", respline);
fflush(stdout);
}
return *lastchar;
}
/*
Funcin __modplc_sendcmd__:
Enva un comando por medio de la interfaz de comunicacin por puerto

530

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


serie y devuelve su respuesta.
*/
static int __modplc_sendcmd__(modplc_hd *hd, char op, const char *infmt,
void **inparam, const void *inframe,
const char *outfmt, void **outparam,
void *outframe)
{
/* Variables. */
int param;
/* Nmero de parmetro. */
size_t i;
/* Contador. */
size_t j;
/* Contador. */
size_t framesize;
/* Tamao de la trama. */
unsigned char *ptrline;
/* Puntero a la lnea de
respuesta de comando. */
unsigned char *ptrparam;
/* Puntero al parmetro. */
unsigned char *ptrresp;
/* Puntero a la respuesta. */
unsigned char *ptrframe;
/* Puntero a la trama. */
unsigned int dat1;
/* Dato. */
unsigned char dat2;
/* Dato. */
char hexval[3];
/* Valor hexadecimal. */
char cmdline[MODPLC_BUFFERSIZE];
/* Lnea de comando. */
char rline[MODPLC_BUFFERSIZE];
/* Lnea de respuesta de
comando. */
char respline[MODPLC_BUFFERSIZE];
/* Lnea de respuesta de
comando. */

/* Verifica que el modem PLC se encuentre en estado activo. */


modplc_status(hd);
if (!hd->status) return 0;
/* Enva el comando y sus parmetros. */
param = 0;
*(cmdline + 0) = op;
*(cmdline + 1) = '\n';
*(cmdline + 2) = 0;
while(infmt && inparam)
{
/* Enva el comando y un parmetro procesado. */
if (!infmt[param]) break;
if (__modplc_sendcmdline__(hd, cmdline, cmdline,
MODPLC_BUFFERSIZE) != '>')
return 0;
/* Procesa el siguiente parmetro a enviar. */
ptrparam = (unsigned char *) inparam[param];
if (infmt[param] == 'b')
sprintf(cmdline, "\\%02X\n",
*((unsigned char *) inparam[param]));
else if (infmt[param] == 's')
sprintf(cmdline, "\\%02X\\%02X\n",
ptrparam[1], ptrparam[0]);
else if (infmt[param] == 'l')
sprintf(cmdline, "\\%02X\\%02X\\%02X\\%02X\n",
ptrparam[3], ptrparam[2], ptrparam[1],
ptrparam[0]);
else if (infmt[param] == 'a')
sprintf(cmdline,
"\\%02X\\%02X\\%02X\\%02X\\%02X\\%02X\\%02X\\%02X\n",
ptrparam[0], ptrparam[1], ptrparam[2], ptrparam[3],
ptrparam[4], ptrparam[5], ptrparam[6], ptrparam[7]);
param ++;
}
/* Si hay una trama que enviar se enva su contenido. */
if (inframe)
{
/* Espera para poder enviar la trama. */
if (__modplc_sendcmdline__(hd, cmdline, respline,
MODPLC_BUFFERSIZE) != '>')
return 0;

FernandoArielBeunza79156

531

Tesis de Grado en Ingeniera Informtica


/* Enva la trama. */
*cmdline = 0;
ptrframe = (unsigned char *) inframe;
framesize = *((size_t *) inparam[param - 1]);
for(i = 0; i < framesize; )
{
dat2 = (unsigned char) *ptrframe;
if ((dat2 >= 0x20) && (dat2 <= 0x7e) &&
(dat2 != '\\') && (dat2 != '#') &&
(dat2 != '?') && (dat2 != '$') &&
(dat2 != '>'))
sprintf(hexval, "%c", dat2);
else
sprintf(hexval, "\\%02X", dat2);
strcat(cmdline, hexval);
ptrframe ++;
i ++;
if ((i & 0x000f) && (i < framesize)) continue;
strcat(cmdline, "\n");
if (__modplc_sendcmdline__(hd, cmdline, respline,
MODPLC_BUFFERSIZE) != '>')
break;
*cmdline = 0;
}
}
/* Caso contrario se espera la respuesta al comando. */
else
{
if (__modplc_sendcmdline__(hd, cmdline, respline,
MODPLC_BUFFERSIZE) != '$')
return 0;
}
/* Recibe los parmetros de respuesta. */
i = 0;
param = 0;
ptrresp = (unsigned char *) respline;
while(*ptrresp != '$')
{
if (*ptrresp == '\r')
{
ptrresp ++;
continue;
}
else if (*ptrresp != '\n')
{
rline[i++] = *(ptrresp ++);
continue;
}
rline[i] = 0;
ptrresp ++;
i = 0;
if (!strlen(rline)) continue;
if (param < 1)
{
param ++;
continue;
}
if (!outfmt[param - 1])
{
ptrresp -= (strlen(rline) + 2);
break;
}
ptrline = (unsigned char *) rline;
ptrparam = (unsigned char *) outparam[param - 1];
if (outfmt[param - 1] == 'b')
{
if (*ptrline != '\\')

532

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*ptrparam = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat1);
*ptrparam = (unsigned char) dat1;
}
}
else if (outfmt[param - 1] == 's')
{
for(j = 0; j < 2; j++)
{
if (*ptrline != '\\')
*(ptrparam + 1 - j) = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat1);
*(ptrparam + 1 - j) =
(unsigned char) dat1;
}
}
}
else if (outfmt[param - 1] == 'l')
{
for(j = 0; j < 4; j++)
{
if (*ptrline != '\\')
*(ptrparam + 3 - j) = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat1);
*(ptrparam + 3 - j) =
(unsigned char) dat1;
}
}
}
else if (outfmt[param - 1] == 'a')
{
for(j = 0; j < 8; j++)
{
if (*ptrline != '\\')
*(ptrparam + j) = *(ptrline ++);
else
{
ptrline ++;
hexval[0] = *(ptrline ++);
hexval[1] = *(ptrline ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat1);
*(ptrparam + j) = (unsigned char) dat1;
}
}
}
param++;
}
/* Si hay una trama que recibir se recibe su contenido. */
if (outframe)
{
ptrframe = (unsigned char *) outframe;

FernandoArielBeunza79156

533

Tesis de Grado en Ingeniera Informtica


framesize = *((size_t *) outparam[param - 2]);
for(j = 0; j < framesize; )
{
dat2 = *(ptrresp ++);
if ((dat2 == '\n') || (dat2 == '\r')) continue;
if (dat2 != '\\')
*ptrframe = dat2;
else
{
hexval[0] = *(ptrresp ++);
hexval[1] = *(ptrresp ++);
hexval[2] = 0;
sscanf(hexval, "%X", &dat1);
*ptrframe = (unsigned char) dat1;
}
ptrframe ++;
j ++;
}
}
/* xito. */
return 1;
}

C.4.4.6. Archivo modsp.h


/*
modsp.h:
Declaracin de funciones referentes a la interfaz de la capa de sesin
del modem PLC.
*/

#if !defined(__MODSP_H__)
#define __MODSP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <pthread.h>
#include "modplc.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modsp_grpid;
/* Manejador de interfaz con la capa de sesin del modem PLC. */
typedef struct
{
pthread_mutex_t mutexsem;
/* Semforo de exclusin mtua. */
pthread_t detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
modplc_hd *modplchd;
/* Manejador de interfaz con el
modem PLC. */
void (*recfun)
(void *, modsp_grpid,
void *, size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} modsp_hd;

534

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Declaracin de funciones pblicas. */
/*
Funcin modsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modsp_hd *modsp_init(int, int);
/*
Funcin modsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modsp_release(modsp_hd *);
/*
Funcin modsp_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modsp_publish(modsp_hd *, modsp_grpid);
/*
Funcin modsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int modsp_subscribe(modsp_hd *, modsp_grpid);
/*
Funcin modsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modsp_leave(modsp_hd *, modsp_grpid);
/*
Funcin modsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_send(modsp_hd *, modsp_grpid, unsigned char, const void *,
size_t);
/*
Funcin modsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_receive(modsp_hd *, modsp_grpid *, void *, size_t);
/*
Funcin modsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modsp_notify(modsp_hd *, void (*func)(modsp_hd *, modsp_grpid, void *,
size_t, void *), void *);
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modsp_poll(modsp_hd *);
/*
Funcin modsp_status:
Devuelve el estado del modem PLC.
*/
int modsp_status(modsp_hd *);
/*
Funcin modsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de sesin del modem PLC.

FernandoArielBeunza79156

535

Tesis de Grado en Ingeniera Informtica


*/
size_t modsp_getpayloadsize(modsp_hd *);

#endif

C.4.4.7. Archivo modsp.c


/*
modsp.c:
Implementacin de funciones referentes a la interfaz de la capa de
sesin del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <pthread.h>
#include "modplc.h"
#include "modsp.h"

/* Declaracin de funciones privadas. */


static void *__modsp_detectproc__(void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modsp_init:
Inicializa los recursos utilizados por la capa de sesin del modem PLC.
*/
modsp_hd *modsp_init(int sid, int debugmode)
{
/* Variables. */
modsp_hd *handle;

/* Manejador de interfaz con la


capa de sesin del modem PLC. */

/* Crea un nuevo manejador de interfaz con la capa de sesin del modem


PLC. */
handle = (modsp_hd *) malloc(sizeof(modsp_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de sesin del modem
PLC. */
while(1)
{
/* Inicializa el manejador de interfaz con el modem PLC. */
handle->modplchd = modplc_init(sid, MODPLC_SESSIONLAYER,
debugmode);
if (!handle->modplchd) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
handle->payloadsize =
modplc_spgetpayloadsize(handle->modplchd);
if (!handle->payloadsize) break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Inicializa semforo. */
if (pthread_mutex_init(&(handle->mutexsem), NULL)) break;
if (pthread_mutex_unlock(&(handle->mutexsem))) break;
/* Devuelve el manejador creado. */

536

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return handle;
}
/* No se pudo inicializar la interfaz con la capa de sesin del modem
PLC. */
pthread_mutex_destroy(&(handle->mutexsem));
modplc_release(handle->modplchd);
free(handle);
return NULL;
}
/*
Funcin modsp_release:
Libera los recursos utilizados por la capa de sesin del modem PLC.
*/
int modsp_release(modsp_hd *hd)
{
/* Verifica que el manejador de interfaz con la capa de sesin del
modem PLC exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
modsp_notify(hd, NULL, NULL);
/* Libera los recursos utilizados por el semforo de exclusin mtua. */
if (pthread_mutex_destroy(&(hd->mutexsem))) return 0;
/* Libera la interfaz con el modem PLC. */
modplc_release(hd->modplchd);
/* Libera los recursos utilizados por la interfaz con la capa de sesin
del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modsp_publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
int modsp_publish(modsp_hd *hd, modsp_grpid grpid)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Registra el dispositivo como publicador. */
result = modplc_sppublish(hd->modplchd, grpid);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modsp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.

FernandoArielBeunza79156

537

Tesis de Grado en Ingeniera Informtica


*/
int modsp_subscribe(modsp_hd *hd, modsp_grpid grpid)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Registra el dispositivo como suscriptor. */
result = modplc_spsubscribe(hd->modplchd, grpid);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del registro del dispositivo. */
return result;
}
/*
Funcin modsp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int modsp_leave(modsp_hd *hd, modsp_grpid grpid)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Desvincula el dispositivo. */
result = modplc_spleave(hd->modplchd, grpid);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la desvinculacin del dispositivo. */
return result;
}
/*
Funcin modsp_send:
Enva un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_send(modsp_hd *hd, modsp_grpid grpid, unsigned char nosec,
const void *msg, size_t msgsize)
{
/* Verifica que el manejador de interfaz con la capa de sesin del
modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Enva un mensaje. */
msgsize = modplc_spsend(hd->modplchd, grpid, nosec, msg, msgsize);

538

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad de bytes envados. */
return msgsize;
}
/*
Funcin modsp_receive:
Recibe un mensaje por medio de la capa de sesin del modem PLC.
*/
size_t modsp_receive(modsp_hd *hd, modsp_grpid *grpid, void *msg,
size_t msgsize)
{
/* Verifica que el manejador de interfaz con la capa de sesin del
modem PLC exista. */
if (!hd) return 0;
/* Espera la llegada de un mensaje. */
while(!modsp_poll(hd));
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Recibe un mensaje. */
msgsize = modplc_spreceive(hd->modplchd, grpid, msg, msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad de bytes recibidos. */
return msgsize;
}
/*
Funcin modsp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int modsp_notify(modsp_hd *hd, void (*func)(modsp_hd *, modsp_grpid, void *,
size_t, void *), void *param)
{
/* Verifica que el manejador de interfaz con la capa de sesin del
modem PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
hd->recfun = (void (*)(void *, modsp_grpid, void *, size_t,
void *)) func;
hd->param = param;
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora
definida previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
hd->recfun = NULL;
hd->param = param;
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
if (pthread_join(hd->detectthread, NULL)) return 0;

FernandoArielBeunza79156

539

Tesis de Grado en Ingeniera Informtica


return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
hd->recfun = (void (*)(void *, modsp_grpid, void *, size_t,
void *)) func;
hd->param = param;
if (pthread_create(&(hd->detectthread), NULL,
__modsp_detectproc__, hd))
{
hd->recfun = NULL;
hd->param = NULL;
pthread_mutex_unlock(&(hd->mutexsem));
return 0;
}
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int modsp_poll(modsp_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Verifica la recepcin de un mensaje. */
result = modplc_sppoll(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la verificacin de la recepcin de un
mensaje. */
return result;
}
/*
Funcin modsp_status:
Devuelve el estado del modem PLC.
*/
int modsp_status(modsp_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem

540

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene el estado del modem PLC. */
result = modplc_status(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del modem PLC. */
return result;
}
/*
Funcin modsp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de sesin del modem PLC.
*/
size_t modsp_getpayloadsize(modsp_hd *hd)
{
/* Variables. */
size_t payloadsize;

/* Cantidad mxima de bytes que


puede contener un mensaje. */

/* Verifica que el manejador de interfaz con la capa de sesin del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
payloadsize = modplc_spgetpayloadsize(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener un
mensaje. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __modsp_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser
ledo.
*/
static void *__modsp_detectproc__(void *param)
{
/* Variables. */
int recvflag;
size_t msgsize;
modsp_grpid grpid;
modsp_hd *hd;
void (*func)
(void *, modsp_grpid,
void *, size_t, void *);
unsigned char *msg;

/* Indicador de recepcin de un
mensaje. */
/* Tamaoo del mensaje recibido. */
/* Identificador de grupo. */
/* Manejador de interfaz con la
capa de sesin del modem PLC. */

/* Manejador de mensajes
recibidos. */
/* Puntero al mensaje recibido. */

/* Carga el manejador de interfaz con la capa de sesin del modem


PLC. */

FernandoArielBeunza79156

541

Tesis de Grado en Ingeniera Informtica


hd = (modsp_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder acceder a la interfaz con el
modem PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) continue;
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
recvflag = modplc_sppoll(hd->modplchd);
if (recvflag)
{
msg = (unsigned char *)
malloc(hd->payloadsize *
sizeof(unsigned char));
if (msg)
msgsize = modplc_spreceive(hd->modplchd,
&grpid, msg, hd->payloadsize);
else
recvflag = 0;
}
/* Permite a otro hilos el acceso a la interfaz del modem
PLC. */
pthread_mutex_unlock(&(hd->mutexsem));
/* Verifica si se ha detectado la recepcin de un mensaje para
invocar a la funcin manejadora de mensajes recibidos. */
if (recvflag)
{
func(hd, grpid, msg, msgsize, hd->param);
free(msg);
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
pthread_mutex_unlock(&(hd->mutexsem));
pthread_exit(0);
}

C.4.4.8. Archivo moddl.h


/*
moddl.h:
Declaracin de funciones referentes a la interfaz de la capa de enlace
del modem PLC.
*/

#if !defined(__MODDL_H__)
#define __MODDL_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <pthread.h>
#include "modplc.h"

/* Definicin de tipos. */
/* Direccin fsica del modem PLC. */
typedef unsigned char moddl_phyaddr[8];
/* Direccin lgica del modem PLC. */

542

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


typedef unsigned long int moddl_logaddr;
/* Manejador de interfaz con la capa de enlace del modem PLC. */
typedef struct
{
pthread_mutex_t mutexsem;
/* Semforo de exclusin mtua. */
unsigned long int conncounter;
/* Contador de conexiones
abiertas. */
modplc_hd *modplchd;
/* Manejador de interfaz con el
modem PLC. */
} moddl_hd;
/* Manejador de conexin por medio de la capa de enlace del modem PLC. */
typedef struct
{
pthread_t detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
int handle;
/* Identificador de conexin. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */
unsigned char iface;
/* Identificador de intarfaz
fsica. */
moddl_hd *moddlhd;
/* Manejador de interfaz con la
capa de enlance del modem
PLC. */
void (*recfun)
(void *, moddl_phyaddr,
void *, size_t, void *);
/* Funcin manejadora de mensajes
recibidos. */
void *param;
/* Parmetros para la funcin
manejadora de mensajes
recibidos. */
} moddlconn_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin moddl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
moddl_hd *moddl_init(int, int);
/*
Funcin moddl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int moddl_release(moddl_hd *);
/*
Funcin moddl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
moddlconn_hd *moddl_open(moddl_hd *, unsigned char, unsigned char);
/*
Funcin moddl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int moddl_close(moddlconn_hd *);
/*
Funcin moddl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t moddl_send(moddlconn_hd *, moddl_phyaddr, unsigned char, const void *,
size_t);
/*
Funcin moddl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.

FernandoArielBeunza79156

543

Tesis de Grado en Ingeniera Informtica


*/
size_t moddl_receive(moddlconn_hd *, moddl_phyaddr, void *, size_t);
/*
Funcin moddl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int moddl_notify(moddlconn_hd *, void (*func)(moddlconn_hd *, moddl_phyaddr,
void *, size_t, void *), void *);
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int moddl_poll(moddlconn_hd *);
/*
Funcin moddl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int moddl_getaddress(moddl_hd *, unsigned char, moddl_phyaddr);
/*
Funcin moddl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlade del modem PLC.
*/
int moddl_addlogaddress(moddl_hd *, unsigned char, unsigned char,
moddl_logaddr);
/*
Funcin moddl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int moddl_dellogaddress(moddl_hd *, unsigned char, unsigned char,
moddl_logaddr);
/*
Funcin moddl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa
de enlace del modem PLC.
*/
int moddl_getphyaddress(moddl_hd *, unsigned char, unsigned char,
moddl_logaddr, moddl_phyaddr);
/*
Funcin moddl_status:
Devuelve el estado del modem PLC.
*/
int moddl_status(moddl_hd *);
/*
Funcin moddl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de enlace del modem PLC.
*/
size_t moddl_getpayloadsize(moddl_hd *, unsigned char);

#endif

C.4.4.9. Archivo moddl.c


/*
moddl.c:
Implementacin de funciones referentes a la interfaz de la capa de
enlace del modem PLC.
*/

544

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include "config.h"
#include <pthread.h>
#include "modplc.h"
#include "moddl.h"

/* Declaracin de funciones privadas. */


static void *__moddl_detectproc__(void *);

/* Implementacin de funciones pblicas. */


/*
Funcin moddl_init:
Inicializa los recursos utilizados por la capa de enlace del modem PLC.
*/
moddl_hd *moddl_init(int sid, int debugmode)
{
/* Variables. */
moddl_hd *handle;

/* Manejador de interfaz con la


capa de enlace del modem PLC. */

/* Crea un nuevo manejador de interfaz con la capa de enlace del modem


PLC. */
handle = (moddl_hd *) malloc(sizeof(moddl_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa de enlace del modem
PLC. */
while(1)
{
/* Inicializa el manejador de interfaz con el modem PLC. */
handle->modplchd = modplc_init(sid, MODPLC_DATALINKLAYER,
debugmode);
if (!handle->modplchd) break;
/* Inicializa el contador de conexiones abiertas. */
handle->conncounter = 0;
/* Inicializa semforo. */
if (pthread_mutex_init(&(handle->mutexsem), NULL)) break;
if (pthread_mutex_unlock(&(handle->mutexsem))) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa de enlace del modem
PLC. */
pthread_mutex_destroy(&(handle->mutexsem));
modplc_release(handle->modplchd);
free(handle);
return NULL;
}
/*
Funcin moddl_release:
Libera los recursos utilizados por la capa de enlace del modem PLC.
*/
int moddl_release(moddl_hd *hd)
{
/* Verifica que el manejador de interfaz con la capa de enlace del
modem PLC exista. */
if (!hd) return 0;
/* Verifica que no existan conexiones abiertas. */
if (hd->conncounter) return 0;

FernandoArielBeunza79156

545

Tesis de Grado en Ingeniera Informtica


/* Libera los recursos utilizados por el semforo de exclusin mtua. */
if (pthread_mutex_destroy(&(hd->mutexsem))) return 0;
/* Libera la interfaz con el modem PLC. */
modplc_release(hd->modplchd);
/* Libera los recursos utilizados por la interfaz con la capa de enlace
del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin moddl_open:
Abre una conexin por medio de la capa de enlace del modem PLC.
*/
moddlconn_hd *moddl_open(moddl_hd *hd, unsigned char iface, unsigned char prot)
{
/* Variables. */
moddlconn_hd *handle;
/* Manejador de conexin de la capa
de enlace del modem PLC. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return NULL;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return NULL;
/* Crea un nuevo manejador de conexin por medio de la capa de enlace
del modem PLC. */
handle = (moddlconn_hd *) malloc(sizeof(moddlconn_hd));
if (!handle)
{
pthread_mutex_unlock(&(hd->mutexsem));
return NULL;
}
/* Inicializa el manejador de conexin. */
while(1)
{
/* Abre una conexin. */
handle->moddlhd = hd;
handle->iface = iface;
handle->handle =
modplc_dlopen(hd->modplchd, handle->iface, prot);
if (!handle->handle) break;
/* Obtiene la cantidad mxima de bytes que puede contener un
mensaje. */
handle->payloadsize =
modplc_dlgetpayloadsize(hd->modplchd, iface);
if (!handle->payloadsize) break;
/* Inicializa el manejador de mensajes recibidos. */
handle->param = NULL;
handle->recfun = NULL;
/* Actualiza el nmero de conexiones. */
handle->moddlhd->conncounter ++;
/* Permite a otro hilos el acceso a la interfaz del modem
PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) break;
/* Devuelve el manejador creado. */
return handle;

546

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
pthread_mutex_unlock(&(hd->mutexsem));
/* No se pudo abrir la conexin. */
modplc_dlclose(hd->modplchd, handle->handle);
free(handle);
return NULL;
}
/*
Funcin moddl_close:
Cierra una conexin por medio de la capa de enlace del modem PLC.
*/
int moddl_close(moddlconn_hd *hd)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Libera el manejador de mensajes recibidos. */
moddl_notify(hd, NULL, NULL);
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
/* Actualiza el nmero de conexiones. */
hd->moddlhd->conncounter --;
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
/* Libera los recursos utilizados por la conexin por medio de la capa
de enlace del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin moddl_send:
Enva un mensaje por medio de la capa de enlace del modem PLC.
*/
size_t moddl_send(moddlconn_hd *hd, moddl_phyaddr addr, unsigned char prio,
const void *msg, size_t msgsize)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
/* Enva un mensaje. */
msgsize = modplc_dlsend(hd->moddlhd->modplchd, hd->handle, addr, prio,
msg, msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
/* Devuelve la cantidad de bytes recibidos. */
return msgsize;
}
/*
Funcin moddl_receive:
Recibe un mensaje por medio de la capa de enlace del modem PLC.

FernandoArielBeunza79156

547

Tesis de Grado en Ingeniera Informtica


*/
size_t moddl_receive(moddlconn_hd *hd, moddl_phyaddr addr, void *msg,
size_t msgsize)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Espera la llegada de un mensaje. */
while(!moddl_poll(hd));
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
/* Recibe un mensaje. */
msgsize = modplc_dlreceive(hd->moddlhd->modplchd, hd->handle, addr,
msg, msgsize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
/* Devuelve la cantidad de bytes recibidos. */
return msgsize;
}
/*
Funcin moddl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int moddl_notify(moddlconn_hd *hd, void (*func)(moddlconn_hd *, moddl_phyaddr,
void *, size_t, void *), void *param)
{
/* Verifica que el manejador de conexin por medio de la capa de enlace
del modem PLC exista. */
if (!hd) return 0;
/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
hd->recfun = (void (*)(void *, moddl_phyaddr, void *, size_t,
void *)) func;
hd->param = param;
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora
definida previamente se elimina esta ltima. */
if ((!func) && (hd->recfun))
{
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
hd->recfun = NULL;
hd->param = param;
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
if (pthread_join(hd->detectthread, NULL)) return 0;
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->recfun))
{
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
hd->recfun = (void (*)(void *, moddl_phyaddr, void *, size_t,

548

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


void *)) func;
hd->param = param;
if (pthread_create(&(hd->detectthread), NULL,
__moddl_detectproc__, hd))
{
hd->recfun = NULL;
hd->param = NULL;
pthread_mutex_unlock(&(hd->moddlhd->mutexsem));
return 0;
}
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
return 1;
}
/* No se pudo definir la funcin manejadora de mensajes recibidos. */
return 0;
}
/*
Funcin modsp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int moddl_poll(moddlconn_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de conexin por medio de la capa de enlace


del modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) return 0;
/* Verifica la recepcin de un mensaje. */
result = modplc_dlpoll(hd->moddlhd->modplchd, hd->handle);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->moddlhd->mutexsem))) return 0;
/* Devuelve el resultado de la verificacin de la recepcin de un
mensaje. */
return result;
}
/*
Funcin moddl_getaddress:
Devuelve la direccin fsica de la capa de enlace del modem PLC.
*/
int moddl_getaddress(moddl_hd *hd, unsigned char iface, moddl_phyaddr addr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene la direccin fsica. */
result = modplc_dlgetaddress(hd->modplchd, iface, addr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;

FernandoArielBeunza79156

549

Tesis de Grado en Ingeniera Informtica


/* Devuelve el resultado de la bsqueda. */
return result;
}
/*
Funcin moddl_addlogaddress:
Agrega una nueva direccin lgica a la capa de enlace del modem PLC.
*/
int moddl_addlogaddress(moddl_hd *hd, unsigned char iface, unsigned char prot,
moddl_logaddr addr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Agrega una nueva direccin lgica. */
result = modplc_dladdlogaddress(hd->modplchd, iface, prot, addr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del agregado de la direccin lgica. */
return result;
}
/*
Funcin moddl_dellogaddress:
Elimina una direccin lgica a la capa de enlace del modem PLC.
*/
int moddl_dellogaddress(moddl_hd *hd, unsigned char iface, unsigned char prot,
moddl_logaddr addr)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Elimina una direccin lgica. */
result = modplc_dldellogaddress(hd->modplchd, iface, prot, addr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la eliminacin de la direccin lgica. */
return result;
}
/*
Funcin moddl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica de la capa
de enlace del modem PLC.
*/
int moddl_getphyaddress(moddl_hd *hd, unsigned char iface, unsigned char prot,
moddl_logaddr laddr, moddl_phyaddr paddr)
{
/* Variables. */

550

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene la direccin fsica asociada a la direccin lgica. */
result = modplc_dlgetphyaddress(hd->modplchd, iface, prot, laddr,
paddr);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la bsqueda. */
return result;
}
/*
Funcin moddl_status:
Devuelve el estado del modem PLC.
*/
int moddl_status(moddl_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene el estado del modem PLC. */
result = modplc_status(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del modem PLC. */
return result;
}
/*
Funcin moddl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje de
la capa de enlace del modem PLC.
*/
size_t moddl_getpayloadsize(moddl_hd *hd, unsigned char iface)
{
/* Variables. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener un mensaje. */

/* Verifica que el manejador de interfaz con la capa de enlace del


modem PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene la cantidad mxima de bytes que puede contener un

FernandoArielBeunza79156

551

Tesis de Grado en Ingeniera Informtica


mensaje. */
payloadsize = modplc_dlgetpayloadsize(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener un
mensaje. */
return payloadsize;
}

/* Implementacin de funciones privadas. */


/*
Funcin __moddl_detectproc__:
Verifica la existencia de un mensaje recibido disponible para ser
ledo.
*/
static void *__moddl_detectproc__(void *param)
{
/* Variables. */
int recvflag;
size_t msgsize;
moddl_phyaddr addr;
moddlconn_hd *hd;

void (*func)
(void *, moddl_phyaddr,
void *, size_t, void *);
unsigned char *msg;

/* Indicador de recepcin de un
mensaje. */
/* Tamao del mensaje recibido. */
/* Direccin fsica de origen del
mensaje. */
/* Manejador de conexin por medio
de la capa de enlace del modem
PLC. */

/* Manejador de mensajes
recibidos. */
/* Puntero al mensaje recibido. */

/* Carga el manejador de conexin por medio de la capa de enlace del


modem PLC. */
hd = (moddlconn_hd *) param;
/* Verifica la existencia de un mensaje recibido. */
while(1)
{
/* Espera el permiso para poder acceder a la interfaz con el
modem PLC. */
if (pthread_mutex_lock(&(hd->moddlhd->mutexsem))) continue;
/* Verifica la recepcin de un mensaje. */
func = hd->recfun;
if (!func) break;
recvflag = modplc_dlpoll(hd->moddlhd->modplchd, hd->handle);
if (recvflag)
{
msg = (unsigned char *)
malloc(hd->payloadsize *
sizeof(unsigned char));
if (msg)
msgsize = modplc_dlreceive(
hd->moddlhd->modplchd,
hd->handle, addr, msg,
hd->payloadsize);
else
recvflag = 0;
}
/* Permite a otro hilos el acceso a la interfaz del modem
PLC. */
pthread_mutex_unlock(&(hd->moddlhd->mutexsem));
/* Verifica si se ha detectado la recepcin de un mensaje para

552

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


invocar a la funcin manejadora de mensajes recibidos. */
if (recvflag)
{
func(hd, addr, msg, msgsize, hd->param);
free(msg);
}
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
pthread_mutex_unlock(&(hd->moddlhd->mutexsem));
pthread_exit(0);
}

C.4.4.10. Archivo modphy.h


/*
modphy.h:
Declaracin de funciones referentes a la interfaz de la capa fsica del
modem PLC.
*/

#if !defined(__MODPHY_H__)
#define __MODPHY_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <pthread.h>
#include "modplc.h"

/* Definicin de tipos. */
/* Manejador de interfaz con la capa fsica del modem PLC. */
typedef struct
{
pthread_mutex_t mutexsem;
/* Semforo de exclusin mtua. */
modplc_hd *modplchd;
/* Manejador de interfaz con el
modem PLC. */
struct
{
pthread_t detectthread;
/* Manejador de hilo de deteccin
de recepcin. */
void (*recfun)
(void *, void *);
/* Funcin manejadora de tramas
capturadas. */
void *param;
/* Parmetros para la funcin
manejadora de tramas
recibidos. */
} iface[256];
/* Tabla de interfaces fsicas. */
} modphy_hd;

/* Definicin de constantes. */
/* Tipos de seales. */
#define MODPHY_NOISESIGNAL
#define MODPHY_TESTSIGNAL1
#define MODPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Declaracin de funciones pblicas. */


/*
Funcin modphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/

FernandoArielBeunza79156

553

Tesis de Grado en Ingeniera Informtica


modphy_hd *modphy_init(int, int);
/*
Funcin modphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modphy_release(modphy_hd *);
/*
Funcin modphy_sndframe:
Enva una trama.
*/
size_t modphy_sndframe(modphy_hd *, unsigned char, const void *, size_t);
/*
Funcin modphy_capframe:
Captura una trama.
*/
int modphy_capframe(modphy_hd *, unsigned char, size_t);
/*
Funcin modphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modphy_getframe(modphy_hd *, unsigned char, void *, size_t);
/*
Funcin modphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
int modphy_notify(modphy_hd *, unsigned char,
void (*func)(modphy_hd *, void *), void *);
/*
Funcin modphy_poll:
Verifica la captura de una trama.
*/
int modphy_poll(modphy_hd *, unsigned char);
/*
Funcin modphy_rsdframe:
Reenva una trama.
*/
int modphy_rsdframe(modphy_hd *, unsigned char);
/*
Funcin modphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modphy_clrbuffer(modphy_hd *, unsigned char);
/*
Funcin modphy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int modphy_sensechannel(modphy_hd *, unsigned char, unsigned char, long int);
/*
Funcin modphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modphy_gensignal(modphy_hd *, unsigned char, int);
/*
Funcin modphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modphy_tstreceive(modphy_hd *, unsigned char);
/*
Funcin modphy_status:

554

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Devuelve el estado del modem PLC.
*/
int modphy_status(modphy_hd *);
/*
Funcin modphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modphy_getpayloadsize(modphy_hd *, unsigned char);

#endif

C.4.4.11. Archivo modphy.c


/*
modphy.c:
Implementacin de funciones referentes a la interfaz de la capa fsica
del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <pthread.h>
#include "modplc.h"
#include "modphy.h"
#include "moddl.h"

/* Declaracin de funciones privadas. */


static void *__modphy_detectproc__(void *);

/* Implementacin de funciones pblicas. */


/*
Funcin modphy_init:
Inicializa los recursos utilizados por la capa fsica del modem PLC.
*/
modphy_hd *modphy_init(int sid, int debugmode)
{
/* Variables. */
short int iface;
modphy_hd *handle;

/* Identificadores de interfaces
fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */

/* Crea un nuevo manejador de interfaz con la capa fsica del modem


PLC. */
handle = (modphy_hd *) malloc(sizeof(modphy_hd));
if (!handle) return NULL;
/* Inicializa el manejador de interfaz con la capa fsica del modem
PLC. */
while(1)
{
/* Inicializa el manejador de interfaz con el modem PLC. */
handle->modplchd = modplc_init(sid, MODPLC_PHYSICALLAYER,
debugmode);
if (!handle->modplchd) break;
/* Inicializa el manejador de tramas capturadas de cada una de
las interfaces fsicas. */
for(iface = 0; iface < 256; iface ++)
{

FernandoArielBeunza79156

555

Tesis de Grado en Ingeniera Informtica


handle->iface[iface].recfun = NULL;
handle->iface[iface].param = NULL;
}
/* Inicializa semforo. */
if (pthread_mutex_init(&(handle->mutexsem), NULL)) break;
if (pthread_mutex_unlock(&(handle->mutexsem))) break;
/* Devuelve el manejador creado. */
return handle;
}
/* No se pudo inicializar la interfaz con la capa fsica del modem
PLC. */
pthread_mutex_destroy(&(handle->mutexsem));
modplc_release(handle->modplchd);
free(handle);
return NULL;
}
/*
Funcin modphy_release:
Libera los recursos utilizados por la capa fsica del modem PLC.
*/
int modphy_release(modphy_hd *hd)
{
/* Variables. */
short int iface;

/* Identificadores de interfaces
fsicas. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Libera el manejador de captura de tramas. */
for(iface = 0; iface < 256; iface ++)
modphy_notify(hd, (unsigned char) (iface & 0x00ff), NULL,
NULL);
/* Libera los recursos utilizados por el semforo de exclusin mtua. */
if (pthread_mutex_destroy(&(hd->mutexsem))) return 0;
/* Libera la interfaz con el modem PLC. */
modplc_release(hd->modplchd);
/* Libera los recursos utilizados por la interfaz con la capa fsica
del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin modphy_sndframe:
Enva una trama.
*/
size_t modphy_sndframe(modphy_hd *hd, unsigned char iface, const void *frame,
size_t framesize)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem
PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Enva una trama. */
framesize = modplc_physndframe(hd->modplchd, iface, frame, framesize);

556

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad de bytes envados. */
return framesize;
}
/*
Funcin modphy_capframe:
Captura una trama.
*/
int modphy_capframe(modphy_hd *hd, unsigned char iface, size_t framesize)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Captura una trama. */
result = modplc_phycapframe(hd->modplchd, iface, framesize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la solicitud de captura de una trama. */
return result;
}
/*
Funcin modphy_getframe:
Obtiene una trama capturada previamente.
*/
size_t modphy_getframe(modphy_hd *hd, unsigned char iface, void *frame,
size_t framesize)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem
PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene una trama capturada previamente. */
framesize = modplc_phygetframe(hd->modplchd, iface, frame, framesize);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad de bytes recibidos. */
return framesize;
}
/*
Funcin modphy_notify:
Define una funcin manejadora de tramas capturadas.
*/
int modphy_notify(modphy_hd *hd, unsigned char iface,
void (*func)(modphy_hd *, void *), void *param)
{
/* Verifica que el manejador de interfaz con la capa fsica del modem
PLC exista. */
if (!hd) return 0;

FernandoArielBeunza79156

557

Tesis de Grado en Ingeniera Informtica


/* Si la funcin manejadora es nula y no hay ninguna funcin manejadora
definida previamente no se hace nada. */
if ((!func) && (!hd->iface[iface].recfun)) return 1;
/* Si la funcin manejadora no es nula y hay una funcin manejadora
previamente definida actualiza la funcin manejadora. */
if ((func) && (hd->iface[iface].recfun))
{
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
hd->iface[iface].recfun = (void (*)(void *, void *)) func;
hd->iface[iface].param = param;
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
return 1;
}
/* Si la funcin manejadora es nula y hay una funcin manejadora
definida previamente se elimina esta ltima. */
if ((!func) && (hd->iface[iface].recfun))
{
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
hd->iface[iface].recfun = (void (*)(void *, void *)) NULL;
hd->iface[iface].param = param;
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
if (pthread_join(hd->iface[iface].detectthread, NULL))
return 0;
return 1;
}
/* Si la funcin manejadora no es nula y no hay una funcin manejadora
previamente definida se define la nueva funcin manejadora. */
if ((func) && (!hd->iface[iface].recfun))
{
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
hd->iface[iface].recfun = (void (*)(void *, void *)) func;
hd->iface[iface].param = param;
if (pthread_create(&(hd->iface[iface].detectthread), NULL,
__modphy_detectproc__, hd))
{
hd->iface[iface].recfun = NULL;
hd->iface[iface].param = NULL;
pthread_mutex_unlock(&(hd->mutexsem));
return 0;
}
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
return 1;
}
/* No se pudo definir la funcin manejadora de tramas capturadas. */
return 0;
}
/*
Funcin modphy_poll:
Verifica la captura de una trama.
*/
int modphy_poll(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Verifica la captura de una trama. */

558

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


result = modplc_phypoll(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la verificacin de la captura de una
trama. */
return result;
}
/*
Funcin modphy_rsdframe:
Reenva una trama.
*/
int modphy_rsdframe(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Reenva una trama. */
result = modplc_phyrsdframe(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del reenvo de una trama. */
return result;
}
/*
Funcin modphy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int modphy_clrbuffer(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Limpia el buffer de captura de tramas. */
result = modplc_phyclrbuffer(hd->modplchd, iface);
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la limpieza del buffer de captura de
tramas. */
return result;
}
/*
Funcin modphy_sensechannel:
Sensa el estado del canal de comunicacin.

FernandoArielBeunza79156

559

Tesis de Grado en Ingeniera Informtica


*/
int modphy_sensechannel(modphy_hd *hd, unsigned char iface,
unsigned char level, long int waittime)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Sensa el estado del canal de comunicacin. */
result = modplc_physensechannel(hd->modplchd, iface, level, waittime);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del sensado del canal de comunicacin. */
return result;
}
/*
Funcin modphy_gensignal:
Genera la seal especificada por medio de la capa fsica del modem PLC.
*/
int modphy_gensignal(modphy_hd *hd, unsigned char iface, int sig)
{
/* Variables. */
int result;
/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Genera la seal especificada. */
result = modplc_phygensignal(hd->modplchd,iface , sig);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la generacin de la seal. */
return result;
}
/*
Funcin modphy_tstreceive:
Realiza una prueba de recepcin.
*/
int modphy_tstreceive(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;

560

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Realiza una prueba de recepcin. */
result = modplc_phytstreceive(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado de la prueba de recepcin. */
return result;
}
/*
Funcin modphy_status:
Devuelve el estado del modem PLC.
*/
int modphy_status(modphy_hd *hd)
{
/* Variables. */
int result;

/* Resultado de la operacin. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene el estado del modem PLC. */
result = modplc_status(hd->modplchd);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve el resultado del modem PLC. */
return result;
}
/*
Funcin modphy_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener una trama de la
capa fsica del modem PLC.
*/
size_t modphy_getpayloadsize(modphy_hd *hd, unsigned char iface)
{
/* Variables. */
size_t payloadsize;
/* Cantidad mxima de bytes que
puede contener una trama. */

/* Verifica que el manejador de interfaz con la capa fsica del modem


PLC exista. */
if (!hd) return 0;
/* Espera el permiso para poder acceder a la interfaz con el modem
PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
/* Obtiene la cantidad mxima de bytes que puede contener una trama. */
payloadsize = modplc_phygetpayloadsize(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem PLC. */
if (pthread_mutex_unlock(&(hd->mutexsem))) return 0;
/* Devuelve la cantidad mxima de bytes que puede contener una
trama. */
return payloadsize;
}

FernandoArielBeunza79156

561

Tesis de Grado en Ingeniera Informtica


/* Implementacin de funciones privadas. */
/*
Funcin __modphy_detectproc__:
Verifica la existencia de una trama capturada disponible para ser
leda.
*/
static void *__modphy_detectproc__(void *param)
{
/* Variables. */
int captureflag;
short int i;
unsigned char iface;
modphy_hd *hd;
void (*func)(void *, void *);

/* Indicador de captura de una


trama. */
/* Contador. */
/* Identificadores de interfaces
fsicas. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Manejador de captura de
tramas. */

/* Carga el manejador de interfaz con la capa fsica del modem PLC. */


hd = (modphy_hd *) param;
/* Obtiene el identificador de interface fsica asociado al hilo de
deteccin de recepcin. */
iface = 0;
if (pthread_mutex_lock(&(hd->mutexsem))) return 0;
for(i = 0; i < 256; i++)
{
if (!pthread_equal(hd->iface[i].detectthread, pthread_self()))
continue;
iface = (unsigned char) (i & 0x00ff);
break;
}
pthread_mutex_unlock(&(hd->mutexsem));
if (i > 255) return 0;
/* Verifica la existencia de una trama capturada. */
while(1)
{
/* Espera el permiso para poder acceder a la interfaz con el
modem PLC. */
if (pthread_mutex_lock(&(hd->mutexsem))) continue;
/* Verifica la captura de una trama. */
func = hd->iface[iface].recfun;
if (!func) break;
captureflag = modplc_phypoll(hd->modplchd, iface);
/* Permite a otro hilos el acceso a la interfaz del modem
PLC. */
pthread_mutex_unlock(&(hd->mutexsem));
/* Verifica si se ha detectado la captura de una trama para
invocar al manejador de trama capturadas. */
if (captureflag) func(hd, hd->iface[iface].param);
}
/* Fin de ejecucin del hilo de deteccin de recepcin. */
pthread_mutex_unlock(&(hd->mutexsem));
pthread_exit(0);
}

C.4.4.12. Archivo modrv.h


/*
moddrv.h:

562

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Declaracin de funciones referentes al driver del modem PLC.
*/

#if !defined(__MODDRV_H__)
#define __MODDRV_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "modphy.h"
#include "moddl.h"
#include "modsp.h"

/* Definicin de tipos. */
/* Estructura del manejador del driver del modem PLC. */
typedef struct
{
int port;
int layer;
int debugmode;
int stopflag;

/*
/*
/*
/*

unsigned long int clients;


modsp_hd *sphd;

/*
/*

moddl_hd *dlhd;

/*

modphy_hd *phyhd;

/*

Identificador de puerto. */
Capa del modem PLC utilizada. */
Indicador de modo depuracin. */
Indicador de detencin de
ejecucin del driver del modem
PLC. */
Cantidad de clientes activos. */
Manejador de interfaz con la
capa de sesin del modem PLC. */
Manejador de interfaz con la
capa de enlace del modem PLC. */
Manejador de interfaz con la
capa fsica del modem PLC. */

} moddrv_hd;

/* Declaracin de funciones pblicas. */


/*
Funcin moddrv_init:
Inicializa los recursos utilizados por el driver del modem PLC.
*/
moddrv_hd *moddrv_init(int, int);
/*
Funcin moddrv_release:
Libera los recursos utilizados por el driver del modem PLC.
*/
int moddrv_release(moddrv_hd *);
/*
Funcin moddrv_run:
Ejecuta el driver del modem PLC.
*/
int moddrv_run(moddrv_hd *);
/*
Funcin moddrv_stop:
Detiene la ejecucin del driver del modem PLC.
*/
int moddrv_stop(moddrv_hd *);

#endif

C.4.4.13. Archivo moddrv.c


/*

FernandoArielBeunza79156

563

Tesis de Grado en Ingeniera Informtica


moddrv.c:
Implementacin de funciones referentes al driver del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#include "modphy.h"
#include "moddl.h"
#include "modsp.h"
#include "moddrv.h"

/* Definicin de tipos. */
/* Estructura de informacin compartida entre hilos de ejecucin. */
typedef struct
{
int hq;
/* Manejador
mensajes.
pthread_mutex_t hm;
/* Manejador
exclusin
moddrv_hd *hd;
/* Manejador
PLC. */
} __moddrv_shareinf__;

de cola de
*/
de semforo de
mutua. */
del driver del modem

/* Declaracin de funciones privadas. */


static void *__moddrv_clientthread__(void *);
static int __moddrv_phyclient__(moddrv_hd *, int, pthread_mutex_t);
static int __moddrv_dlclient__(moddrv_hd *, int, pthread_mutex_t);
static int __moddrv_spclient__(moddrv_hd *, int, pthread_mutex_t);
static int __moddrv_send__(int, const void *, size_t);
static int __moddrv_receive__(int, void *, size_t);

/* Implementacin de funciones pblicas. */


/*
Funcin moddrv_init:
Inicializa los recursos utilizados por el driver del modem PLC.
*/
moddrv_hd *moddrv_init(int sid, int debugmode)
{
/* Variables. */
moddrv_hd *handle;

/* Manejador del driver del modem


PLC. */

/* Crea un nuevo manejador del driver del modem PLC. */


handle = (moddrv_hd *) malloc(sizeof(moddrv_hd));
if (!handle) return NULL;
/* Inicializa el driver del modem PLC. */
handle->port = sid;
handle->layer = 0;
handle->clients = 0;
handle->debugmode = debugmode;
handle->stopflag = 0;
/* Devuelve el manejador creado. */
return handle;

564

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/*
Funcin moddrv_release:
Libera los recursos utilizados por el driver del modem PLC.
*/
int moddrv_release(moddrv_hd *hd)
{
/* Verifica que el manejador del driver del modem PLC exista. */
if (!hd) return 0;
/* Libera los recursos utilizados el driver del modem PLC. */
free(hd);
/* xito. */
return 1;
}
/*
Funcin moddrv_run:
Ejecuta el driver del modem PLC.
*/
int moddrv_run(moddrv_hd *hd)
{
/* Variables. */
int hl;
int hq;
pthread_mutex_t hm;
pthread_t cthread;
char qname[256];
__moddrv_shareinf__ sinf;
socklen_t clilen;
struct sockaddr_un cliaddr;
struct sockaddr_un servaddr;

/* Manejador de espera de
conexin. */
/* Manejador de cola de
mensajes. */
/* Manejador de semforo de
exclusin mutua. */
/* Manejador de hilo. */
/* Nombre de la cola de
mensajes. */
/* Informacin compartida. */
/* Longitud de direccin del
cliente. */
/* Direccin del cliente. */
/* Direccin del servidor. */

/* Verifica que el manejador del driver del modem PLC exista. */


if (!hd) return 0;
/* Inicializa semforo. */
if (pthread_mutex_init(&hm, NULL)) return 0;
if (pthread_mutex_unlock(&hm)) return 0;
/* Procesa las solicitudes de los clientes. */
hd->layer = 0;
hd->clients = 0;
sprintf(qname, "/tmp/modemplc%i.str", hd->port);
while(1)
{
/* Crea una nueva cola de mensajes. */
hl = socket(AF_LOCAL, SOCK_STREAM, 0);
if (hl < 0) break;
unlink(qname);
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, qname);
if (bind(hl, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0)
break;
if (listen(hl, 20) < 0) break;
if (chmod(qname, 0777) < 0) break;
/* Espera la conexin de un nuevo cliente. */
if (hd->stopflag) break;
clilen = sizeof(cliaddr);
hq = accept(hl, (struct sockaddr *) &cliaddr, &clilen);

FernandoArielBeunza79156

565

Tesis de Grado en Ingeniera Informtica


if (hq < 0)
{
if (errno == EINTR)
continue;
else
break;
}
/* Crea un nuevo hilo para atender las solicitudes del nuevo
cliente. */
sinf.hd = hd;
sinf.hq = hq;
sinf.hm = hm;
if (pthread_create(&cthread, NULL, __moddrv_clientthread__,
(void *) &sinf))
{
close(hq);
continue;
}
if (pthread_detach(cthread)) close(hq);
}
/* Fin de ejecucin del driver del modem PLC. */
pthread_mutex_destroy(&hm);
close(hl);
unlink(qname);
return 1;
}
/*
Funcin moddrv_stop:
Detiene la ejecucin del driver del modem PLC.
*/
int moddrv_stop(moddrv_hd *hd)
{
/* Variables. */
int hq;
int layer;
int result;
struct sockaddr_un servaddr;

/* Manejador de cola de
mensajes. */
/* Capa que se solicita
utilizar. */
/* Respuesta a la solicitud. */
/* Direccin del servidor. */

/* Verifica que el manejador del driver del modem PLC exista. */


if (!hd) return 0;
/* Abre una conexin con la cola de mensajes del driver del modem
PLC. */
hq = socket(AF_LOCAL, SOCK_STREAM, 0);
if (hq < 0) return 0;
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
sprintf(servaddr.sun_path, "/tmp/modemplc%i.str", hd->port);
if (connect(hq, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
return 0;
/* Solicita detener la ejecucin del driver del modem PLC. */
layer = 0;
result = 0;
if (__moddrv_send__(hq, &layer, sizeof(layer)))
{
if (__moddrv_receive__(hq, &result, sizeof(result)))
result = 1;
}
if (!result)
{
close(hq);
return 0;
}

566

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Cierra la conexin con al cola de mensajes del driver del modem PLC. */
close(hq);
return 1;
}

/* Implementacin de funciones privadas. */


/*
Funcin __moddrv_clientthread__:
Atiene a los clientes del driver del modem PLC.
*/
static void *__moddrv_clientthread__(void *param)
{
/* Variables. */
int hq;
pthread_mutex_t hm;
int layer;
int result;
moddrv_hd *hd;
__moddrv_shareinf__ *sinf;

/* Manejador de cola de
mensajes. */
/* Manejador de semforo de
exclusin mutua. */
/* Capa que se solicita
utilizar. */
/* Respuesta a la solicitud. */
/* Manejador del driver del modem
PLC. */
/* Informacin compartida. */

/* Carga el manejador de cola de mensajes y el manejador del driver del


modem PLC. */
sinf = (__moddrv_shareinf__ *) param;
hq = sinf->hq;
hd = sinf->hd;
hm = sinf->hm;
/* Espera el permiso para poder acceder a los recursos del driver del
modem PLC. */
if (pthread_mutex_lock(&hm)) pthread_exit(0);
/* Recibe la capa a la cual el cliente quiere acceder. */
while(!__moddrv_receive__(hq, &layer, sizeof(layer)));
/* Verifica si se solicita detener la ejecucin del driver del modem
PLC. */
if (!layer)
{
result = 1;
hd->stopflag = 1;
__moddrv_send__(hq, &result, sizeof(result));
pthread_mutex_unlock(&hm);
close(hq);
pthread_exit(0);
}
/* Verifica si es vlida la solicitud. */
result = 0;
if ((layer >= 1) && (layer <= 3))
{
if (!hd->layer) hd->layer = layer;
if (hd->layer == layer) result = 1;
}
/* Verifica si es necesario inicializar alguna interfaz. */
if ((result) && (!hd->clients))
{
/* Inicializa la interfaz de la capa fsica del modem PLC. */
if (layer == 1)
{
hd->phyhd = modphy_init(hd->port, hd->debugmode);
if (!hd->phyhd) result = 0;
}
/* Inicializa la interfaz de la capa de enlace del modem

FernandoArielBeunza79156

567

Tesis de Grado en Ingeniera Informtica


PLC. */
else if (layer == 2)
{
hd->dlhd = moddl_init(hd->port, hd->debugmode);
if (!hd->dlhd) result = 0;
}
/* Inicializa la interfaz de la capa de sesin del modem
PLC. */
else if (layer == 3)
{
hd->sphd = modsp_init(hd->port, hd->debugmode);
if (!hd->sphd) result = 0;
}
}
/* Enva el resultado de la solicitud. */
__moddrv_send__(hq, &result, sizeof(result));
if (!result)
{
if (!hd->clients) hd->layer = 0;
pthread_mutex_unlock(&hm);
close(hq);
pthread_exit(0);
}
/* Agrega un nuevo cliente. */
hd->clients ++;
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
pthread_mutex_unlock(&hm);
/* Verifica si el cliente solicit acceder a la capa fsica. */
if (layer == 1)
__moddrv_phyclient__(hd, hq, hm);
/* Verifica si el cliente solicit acceder a la capa de enlace. */
else if (layer == 2)
__moddrv_dlclient__(hd, hq, hm);
/* Verifica si el cliente solicit acceder a la capa de aplicacin. */
else if (layer == 3)
__moddrv_spclient__(hd, hq, hm);
/* Espera el permiso para poder acceder a los recursos del driver del
modem PLC. */
pthread_mutex_lock(&hm);
/* Elimina un cliente. */
hd->clients --;
/* Verifica si es necesario liberar alguna interfaz. */
if (!hd->clients)
{
/* Libera la interfaz de la capa fsica del modem PLC. */
if (layer == 1)
modphy_release(hd->phyhd);
/* Libera la interfaz de la capa de enlace del modem PLC. */
else if (layer == 2)
moddl_release(hd->dlhd);
/* Libera la interfaz de la capa de sesin del modem PLC. */
else if (layer == 3)
modsp_release(hd->sphd);
/* No se esta utilizando ninguna capa. */
hd->layer = 0;
}
/* Permite a otro hilos el acceso a los recursos del driver del modem
PLC. */
pthread_mutex_unlock(&hm);

568

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Fin de ejecucin del hilo de deteccin de recepcin. */
close(hq);
return 0;
}
/*
Funcin __moddrv_phyclient__:
Procesa las solicitudes de los clientes destinadas a la capa fsica del
modem PLC.
*/
static int __moddrv_phyclient__(moddrv_hd *hd, int hq, pthread_mutex_t hm)
{
/* Variables. */
int op;
/* Cdigo de operacin. */
int sig;
/* Tipo de seal. */
int result;
/* Respuesta a la solicitud. */
size_t size;
/* Cantidad de bytes. */
unsigned char iface;
/* Identificador de interfaz
fsica. */
unsigned char level;
/* Nivel de seal. */
long int waittime;
/* Tiempo de espera. */
unsigned char *frame;
/* Puntero a la trama recibida. */

/* Procesa solicitudes destinadas a la capa fsica del modem PLC. */


while(!hd->stopflag)
{
/* Recibe el cdigo de operacin. */
if (!__moddrv_receive__(hq, &op, sizeof(op))) continue;
/* Espera el permiso para poder acceder a los recursos del
driver del modem PLC. */
pthread_mutex_lock(&hm);
/* Solicita terminar la conexin. */
if (op == MODDRVPHY_RELEASE)
{
result = 1;
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
break;
}
/* Solicita el envo de una trama. */
else if (op == MODDRVPHY_SNDFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el tamao de la trama. */
if (!__moddrv_receive__(hq, &size, sizeof(size)))
continue;
/* Recibe la trama. */
frame = (unsigned char *)
malloc(size * sizeof(unsigned char));
if (!frame) continue;
if (!__moddrv_receive__(hq, frame, size))
{
free(frame);
continue;
}
/* Enva la trama. */
size = modphy_sndframe(hd->phyhd, iface, frame, size);
free(frame);
/* Enva la cantidad de bytes enviados. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
}

FernandoArielBeunza79156

569

Tesis de Grado en Ingeniera Informtica


/* Solicita la captura de una trama. */
else if (op == MODDRVPHY_CAPFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el tamao de la trama. */
if (!__moddrv_receive__(hq, &size, sizeof(size)))
continue;
/* Catura una trama. */
result = modphy_capframe(hd->phyhd, iface, size);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la lectura de una trama capturada. */
else if (op == MODDRVPHY_GETFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el tamao de la trama. */
if (!__moddrv_receive__(hq, &size, sizeof(size)))
continue;
/* Catura una trama. */
frame = (unsigned char *)
malloc(size * sizeof(unsigned char));
if (!frame) continue;
size = modphy_getframe(hd->phyhd, iface, frame, size);
/* Enva la trama leda. */
if (!__moddrv_send__(hq, frame, size))
{
free(frame);
continue;
}
free(frame);
/* Enva la cantidad de bytes ledos. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
}
/* Solicita la verificacin de la captura de una trama. */
else if (op == MODDRVPHY_POLL)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Verifica de la captura de una trama. */
result = modphy_poll(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita el reenvo de una trama. */
else if (op == MODDRVPHY_RSDFRAME)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Reenva una trama. */
result = modphy_rsdframe(hd->phyhd, iface);

570

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la limpieza del buffer de captura de tramas. */
else if (op == MODDRVPHY_CLRBUFFER)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Limpia el buffer de captura de tramas. */
result = modphy_clrbuffer(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita el sensado del canal de comunicacin. */
else if (op == MODDRVPHY_SENSECHANNEL)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el nivel de seal. */
if (!__moddrv_receive__(hq, &level, sizeof(level)))
continue;
/* Recibe el tiempo de espera. */
if (!__moddrv_receive__(hq, &waittime,
sizeof(waittime)))
continue;
/* Sensa el estado del canal de comunicacin. */
result = modphy_sensechannel(hd->phyhd, iface, level,
waittime);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la generacin de una seal. */
else if (op == MODDRVPHY_GENSIGNAL)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el tipo de seal. */
if (!__moddrv_receive__(hq, &sig, sizeof(sig)))
continue;
/* Genera la seal solicitada. */
result = modphy_gensignal(hd->phyhd, iface, sig);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita realizar una prueba de recepcin. */
else if (op == MODDRVPHY_TSTRECEIVE)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Realiza la prueba de recepcin. */
result = modphy_tstreceive(hd->phyhd, iface);
/* Enva el resultado de la solicitud. */

FernandoArielBeunza79156

571

Tesis de Grado en Ingeniera Informtica


if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita verifica el estado del modem PLC. */
else if (op == MODDRVPHY_STATUS)
{
/* Verifica el estado del modem PLC. */
result = modphy_status(hd->phyhd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la cantidad mxima de bytes que puede contener una
trama. */
else if (op == MODDRVPHY_GETPAYLOADSIZE)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Obtiene la cantidad mxima de bytes que puede
contener una trama. */
size = modphy_getpayloadsize(hd->phyhd, iface);
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
}
/* Solicitud desconocida. */
else
{
result = 0;
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Permite a otro hilos el acceso a los recursos del driver del
modem PLC. */
pthread_mutex_unlock(&hm);
}
pthread_mutex_unlock(&hm);
return 0;
}
/*
Funcin __moddrv_dlclient__:
Procesa las solicitudes de los clientes destinadas a la capa de enlace
del modem PLC.
*/
static int __moddrv_dlclient__(moddrv_hd *hd, int hq, pthread_mutex_t hm)
{
/* Variables. */
int op;
/* Cdigo de operacin. */
int result;
/* Respuesta a la solicitud. */
unsigned char prot;
/* Identificador de protocolo. */
unsigned char prio;
/* Prioridad del mensaje. */
unsigned char iface;
/* Identificador de interfaz
fsica. */
size_t size;
/* Cantidad de bytes. */
moddlconn_hd *dlconnhd;
/* Manejador de conexin por medio
de la capa de enlace del modem
PLC. */
moddl_logaddr laddr;
/* Direccin lgica. */
moddl_phyaddr paddr;
/* Direccin fsica. */
unsigned char *msg;
/* Puntero al mensaje recibido. */

/* Procesa solicitudes destinadas a la capa de enlace del modem PLC. */


dlconnhd = NULL;
while(!hd->stopflag)
{
/* Recibe el cdigo de operacin. */

572

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (!__moddrv_receive__(hq, &op, sizeof(op))) continue;
/* Espera el permiso para poder acceder a los recursos del
driver del modem PLC. */
pthread_mutex_lock(&hm);
/* Solicita cerrar la conexin. */
if (op == MODDRVDL_CLOSE)
{
result = 0;
if (moddl_close(dlconnhd)) result = 1;
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
break;
}
/* Solicita abrir la conexin. */
else if (op == MODDRVDL_OPEN)
{
/* Abre la conexin si no fue abierta anteriormente. */
result = 0;
if (!dlconnhd)
{
/* Recibe el identificador de interfaz
fsica. */
if (!__moddrv_receive__(hq, &iface,
sizeof(iface)))
continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot,
sizeof(prot)))
continue;
/* Abre la conexin. */
dlconnhd = moddl_open(hd->dlhd, iface, prot);
if (dlconnhd) result = 1;
}
/* Devuelve el resultado de la operacin. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita enviar un mensaje. */
else if (op == MODDRVDL_SEND)
{
/* Enva un mensaje. */
size = 0;
if (dlconnhd)
{
/* Recibe la direccin destinataria. */
if (!__moddrv_receive__(hq, paddr,
sizeof(paddr)))
continue;
/* Recibe la prioridad del mensaje. */
if (!__moddrv_receive__(hq, &prio,
sizeof(prio)))
continue;
/* Recibe el tamao del mensaje. */
if (!__moddrv_receive__(hq, &size,
sizeof(size)))
continue;
/* Recibe el mensaje. */
msg = (unsigned char *)
malloc(size * sizeof(unsigned char));
if (!msg) continue;
if (!__moddrv_receive__(hq, msg, size))
{
free(msg);

FernandoArielBeunza79156

573

Tesis de Grado en Ingeniera Informtica


continue;
}
/* Enva el mensaje. */
size = moddl_send(dlconnhd, paddr, prio, msg,
size);
free(msg);
}
/* Devuelve la cantidad de bytes enviados. */
if (!__moddrv_send__(hq, &size, sizeof(size))) continue;
}
/* Solicita recibir un mensaje. */
else if (op == MODDRVDL_RECEIVE)
{
/* Recibe un mensaje. */
size = 0;
msg = NULL;
if (dlconnhd)
{
/* Recibe el tamao del mensaje. */
if (!__moddrv_receive__(hq, &size,
sizeof(size)))
continue;
/* Recibe el mensaje. */
msg = (unsigned char *)
malloc(size * sizeof(unsigned char));
if (!msg) continue;
size = moddl_receive(dlconnhd, paddr, msg,
size);
}
/* Devuelve la cantidad de bytes recibidos. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
{
if (msg) free(msg);
continue;
}
if (!size)
{
free(msg);
continue;
}
/* Enva la direccin de origen del mensaje. */
if (!__moddrv_send__(hq, paddr, sizeof(paddr)))
{
free(msg);
continue;
}
/* Enva la direccin de origen del mensaje. */
if (!__moddrv_send__(hq, msg, size))
{
free(msg);
continue;
}
free(msg);
}
/* Solicita la verificacin de un mensaje. */
else if (op == MODDRVDL_POLL)
{
/* Verifica de la recepcin de un mensaje. */
result = 0;
if (dlconnhd) result = moddl_poll(dlconnhd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}

574

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Solicita la direccin fsica del modem PLC. */
else if (op == MODDRVDL_GETADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Obtiene la direccin fsica. */
result = moddl_getaddress(hd->dlhd, iface, paddr);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
if (!result) continue;
/* Enva la direccin fsica solicitada. */
if (!__moddrv_send__(hq, paddr, sizeof(paddr)))
continue;
}
/* Solicita agregar una nueva direccin lgica. */
else if (op == MODDRVDL_ADDLOGADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot)))
continue;
/* Recibe la direccin lgica. */
if (!__moddrv_receive__(hq, &laddr, sizeof(laddr)))
continue;
/* Agrega la direccin lgica. */
result = moddl_addlogaddress(hd->dlhd, iface, prot,
laddr);
/* Devuelve el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita eliminar una direccin lgica. */
else if (op == MODDRVDL_DELLOGADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot)))
continue;
/* Recibe la direccin lgica. */
if (!__moddrv_receive__(hq, &laddr, sizeof(laddr)))
continue;
/* Elimina la direccin lgica. */
result = moddl_dellogaddress(hd->dlhd, iface, prot,
laddr);
/* Devuelve el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita obtener la direccin fsica asociada a la direccin
lgica. */
else if (op == MODDRVDL_GETPHYADDRESS)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))

FernandoArielBeunza79156

575

Tesis de Grado en Ingeniera Informtica


continue;
/* Recibe el identificador de protocolo. */
if (!__moddrv_receive__(hq, &prot, sizeof(prot)))
continue;
/* Recibe la direccin lgica. */
if (!__moddrv_receive__(hq, &laddr, sizeof(laddr)))
continue;
/* Obtiene la direccin lgica. */
result = moddl_getphyaddress(hd->dlhd, iface, prot,
laddr, paddr);
/* Devuelve el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
if (!result) continue;
/* Enva la direccin fsica. */
if (!__moddrv_send__(hq, paddr, sizeof(paddr)))
continue;
}
/* Solicita verifica el estado del modem PLC. */
else if (op == MODDRVDL_STATUS)
{
/* Verifica el estado del modem PLC. */
result = moddl_status(hd->dlhd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
else if (op == MODDRVDL_GETPAYLOADSIZE)
{
/* Recibe el identificador de interfaz fsica. */
if (!__moddrv_receive__(hq, &iface, sizeof(iface)))
continue;
/* Obtiene la cantidad mxima de bytes que puede
contener un mensaje. */
size = moddl_getpayloadsize(hd->dlhd, iface);
/* Devuelve la cantidad mxima de bytes que puede
contener un mensaje. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
}
/* Solicitud desconocida. */
else
{
result = 0;
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Permite a otro hilos el acceso a los recursos del driver del
modem PLC. */
pthread_mutex_unlock(&hm);
}
pthread_mutex_unlock(&hm);
return 0;
}
/*
Funcin __moddrv_spclient__:
Procesa las solicitudes de los clientes destinadas a la capa de sesin
del modem PLC.
*/

576

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


static int __moddrv_spclient__(moddrv_hd *hd, int hq, pthread_mutex_t hm)
{
/* Variables. */
int op;
/* Cdigo de operacin. */
int result;
/* Respuesta a la solicitud. */
size_t size;
/* Cantidad de bytes. */
modsp_grpid grpid;
/* Identificador de grupo. */
unsigned char nosec;
/* Indicador de mensaje fuera de
secuencia. */
unsigned char *msg;
/* Puntero al mensaje recibido. */

/* Procesa solicitudes destinadas a la capa de aplicacin del modem


PLC. */
while(!hd->stopflag)
{
/* Recibe el cdigo de operacin. */
if (!__moddrv_receive__(hq, &op, sizeof(op))) continue;
/* Espera el permiso para poder acceder a los recursos del
driver del modem PLC. */
pthread_mutex_lock(&hm);
/* Solicita terminar la conexin. */
if (op == MODDRVSP_RELEASE)
{
result = 1;
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
break;
}
/* Solicita el registro del dispositivo como publicador. */
else if (op == MODDRVSP_PUBLISH)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid)))
continue;
/* Registra el dispositivo como publicador. */
result = modsp_publish(hd->sphd, grpid);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita el registro del dispositivo como suscriptor. */
else if (op == MODDRVSP_SUBSCRIBE)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid)))
continue;
/* Registra el dispositivo como suscriptor. */
result = modsp_subscribe(hd->sphd, grpid);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la desvinculacin del dispositivo a un grupo de
difusin. */
else if (op == MODDRVSP_LEAVE)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid)))
continue;
/* Desvincula el dispositivo de un grupo de difusin. */
result = modsp_leave(hd->sphd, grpid);
/* Enva el resultado de la solicitud. */

FernandoArielBeunza79156

577

Tesis de Grado en Ingeniera Informtica


if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita el envo de un mensaje. */
else if (op == MODDRVSP_SEND)
{
/* Recibe el identificador de grupo. */
if (!__moddrv_receive__(hq, &grpid, sizeof(grpid)))
continue;
/* Recibe el indicador de mensaje fuera de
secuencia. */
if (!__moddrv_receive__(hq, &nosec, sizeof(nosec)))
continue;
/* Recibe el tamao del mensaje. */
if (!__moddrv_receive__(hq, &size, sizeof(size)))
continue;
/* Enva el mensaje solicitado. */
while(1)
{
/* Recibe el mensaje. */
msg = (unsigned char *)
malloc(size * sizeof(unsigned char));
if (!msg)
{
size = 0;
break;
}
if (!__moddrv_receive__(hq, msg, size))
{
size = 0;
break;
}
/* Enva el mensaje. */
size = modsp_send(hd->sphd, grpid, nosec, msg,
size);
break;
}
/* Enva la cantidad de bytes enviados. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
}
/* Solicita la recepcin de un mensaje. */
else if (op == MODDRVSP_RECEIVE)
{
/* Recibe la cantidad de bytes que se desea recibir del
mensaje. */
if (!__moddrv_receive__(hq, &size, sizeof(size)))
continue;
/* Recibe el mensaje. */
msg = (unsigned char *)
malloc(size * sizeof(unsigned char));
if (msg)
size = modsp_receive(hd->sphd, &grpid, msg,
size);
else
size = 0;
/* Enva la cantidad de bytes recibidos. */
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
if (!size) continue;
/* Enva el indentificador del grupo de difusin por el
cual se recibi el mensaje. */
if (!__moddrv_send__(hq, &grpid, sizeof(grpid)))

578

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
free(msg);
continue;
}
/* Enva el mensaje recibido. */
if (!__moddrv_send__(hq, msg, size))
{
free(msg);
continue;
}
free(msg);
}
/* Solicita la verificacin de la recepcin de un mensaje. */
else if (op == MODDRVSP_POLL)
{
/* Verifica de la recepcin de un mensaje. */
result = modsp_poll(hd->sphd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita verifica el estado del modem PLC. */
else if (op == MODDRVSP_STATUS)
{
/* Verifica el estado del modem PLC. */
result = modsp_status(hd->sphd);
/* Enva el resultado de la solicitud. */
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Solicita la cantidad mxima de bytes que puede contener un
mensaje. */
else if (op == MODDRVSP_GETPAYLOADSIZE)
{
size = modsp_getpayloadsize(hd->sphd);
if (!__moddrv_send__(hq, &size, sizeof(size)))
continue;
}
/* Solicitud desconocida. */
else
{
result = 0;
if (!__moddrv_send__(hq, &result, sizeof(result)))
continue;
}
/* Permite a otro hilos el acceso a los recursos del driver del
modem PLC. */
pthread_mutex_unlock(&hm);
}
pthread_mutex_unlock(&hm);
return 0;
}
/*
Funcin __moddrv_send__:
Enva datos por medio de la cola de mensajes.
*/
static int __moddrv_send__(int hq, const void *stream, size_t size)
{
/* Variables. */
size_t sent;
/* Cantidad de bytes enviados. */
size_t lastsent;
/* Cantidad de bytes enviados en el
ltimo envo. */
unsigned char *ptr;
/* Puntero a los datos. */

/* Envia los datos. */

FernandoArielBeunza79156

579

Tesis de Grado en Ingeniera Informtica


sent = 0;
ptr = (unsigned char *) stream;
while((stream) && (sent < size))
{
lastsent = write(hq, ptr + sent, size - sent);
sent += lastsent;
}
return 1;
}
/*
Funcin __moddrv_receive__:
Enva datos por medio de la cola de mensajes.
*/
static int __moddrv_receive__(int hq, void *stream, size_t size)
{
/* Variables. */
size_t received;
/* Cantidad de bytes recibidos. */
size_t lastreceive;
/* Cantidad de bytes recibidos en
la ltima recepcin. */
unsigned char *ptr;
/* Puntero a los datos. */

/* Enva los datos. */


received = 0;
ptr = (unsigned char *) stream;
while((stream) && (received < size))
{
lastreceive = read(hq, ptr + received, size - received);
received += lastreceive;
}
return 1;
}

C.4.4.14. Archivo modem_driver.c


/*
modplc_driver.c:
Implementacin de funcin principal del driver del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <string.h>
#include "moddrv.h"

/* Declaracin de funciones privadas. */


static char *strlwr(const char *);

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port;
int debug;
moddrv_hd *hd;
char *option;

/* Puerto serie utilizado. */


/* Modo depuracin. */
/* Manejador del driver del modem
PLC. */
/* Opcin especificada. */

/* Carga los parmentros */


if (argc < 3) return -1;

580

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


port = atoi(argv[1]);
debug = 0;
if (argc > 3)
{
option = strlwr(strdup(argv[3]));
if (!option) return -1;
if (!strcmp(option, "debug")) debug = 1;
}
option = strlwr(strdup(argv[2]));
if (!option) return -1;
/* Inicializa el driver del modem PLC. */
hd = moddrv_init(port, debug);
if (!hd) return 0;
/* Evala la opcin solicitada. */
while(1)
{
/* Activa el driver. */
if (!strcmp(option, "start"))
moddrv_run(hd);
/* Desactiva el driver. */
else if (!strcmp(option, "stop"))
moddrv_stop(hd);
break;
}
/* Libera los recursos del driver del modem PLC. */
moddrv_release(hd);
free(option);
return 0;
}

/* Implementacin de funciones privadas. */


/*
Funcin strlwr:
Convierte todas las letras de una cadena a letra minscula.
*/
static char *strlwr(const char *str)
{
/* Variables. */
char *ostr;
char *instr;
char *outstr;

/* Cadena de salida. */
/* Puntero a la cadena de
entrada. */
/* Puntero a la cadena de
salida. */

/* Convierte a minscula todas las letras de la cadena suministrada. */


if (!str) return NULL;
ostr = (char *) malloc(strlen(str) + 1);
if (!ostr) return NULL;
instr = (char *) str;
outstr = (char *) ostr;
while(*instr)
{
*outstr = *instr;
if ((*outstr >= 'A') && (*outstr <= 'Z'))
{
*outstr -= 'A';
*outstr += 'a';
}
outstr ++;
instr ++;
}
*outstr = *instr;
return ostr;

FernandoArielBeunza79156

581

Tesis de Grado en Ingeniera Informtica


}

C.5. Especificacin del cdigo fuente del firmware


del modem PLC
En esta seccin se detalla el cdigo fuente del firmware del modem PLC compuesto por los
siguientes archivos:

582

Archivo config.h: en este archivo se definen parmetros de configuracin del modem


PLC que no pueden ser modificados, tales como tamao del buffer, caracteres
delimitadores de mensajes, tiempos de espera, la direccin fsica del dispositivo, etc.

Archivo common.h: en este archivo se declaran primitivas con funcionalidades generales


utilizadas por todas las capas.

Archivo common.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo common.h.

Archivo serial.h: en este archivo se declaran primitivas con funcionalidades referentes a


la entrada y salida va puerto RS232.

Archivo serial.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo serial.c.

Archivo phy.h: en este archivo se declaran las primitivas correspondientes al manejo de


los aspectos fsicos del modem PLC, inicializacin y liberacin de recursos (activacin y
desactivacin de circuitos transmisor y/o receptor), y envo y recepcin de cadenas de
bytes en bruto.

Archivo phy.c: en este archivo se encuentran implementadas las primitivas declaradas en


el archivo phy.h.

Archivo mac.h: en este archivo se declaran las primitivas referentes a la subcapa de


control de acceso al medio (subcapa MAC), perteneciente a la capa de enlace. Dichas
primitivas brindan la capacidad de enviar y recibir mensajes por medio de un nico medio
de comunicacin compartido por todos los dispositivos conectados al mismo.

Archivo mac.c: en este archivo se encuentran implementadas las primitivas declaradas el


el archivo mac.h. Dichas primitivas implementan, entre otras cosas, el algoritmo de
control de acceso al medio.

Archivo llc.h: en este archivo se declaran las primitivas referentes a la subcapa de control
de lgica de enlace (subcapa LLC), perteneciente a la capa de enlace. Dichas primitivas
brindan la capacidad de enviar y recibir mensajes manteniendo el control de flujo de los
mismos.

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Archivo llc.c: en este archivo se encuentran implementadas las primitivas declaradas el el


archivo llc.h.

Archivo arp.h: en este archivo se declaran las primitivas referentes al protocolo de


resolucin de direcciones (ARP). Dichas primitivas brindan la capacidad de identificar a
cada uno de los dispositivos por medio de direcciones lgicas que pueden ser definidas
independientemente de la direccin fsica preasignada.

Archivo arp.c: en este archivo se encuentran implementadas las primitivas declaradas el


el archivo arp.h.

Archivo dl.h: en este archivo se declaran las primitivas referentes a la interfaz de la capa
de enlace. Dichas primitivas renen las funcionalidades provistas por la subcapa de
control de lgica de enlace (subcapa LLC) y el protocolo de resolucin de direcciones
(ARP).

Archivo dl.c: en este archivo se encuentran implementadas las primitivas declaradas el el


archivo dl.c.

Archivo net.h: en este archivo se declaran las primitivas correspondientes al manejo de la


capa de red. Dichas primitivas brindan la capacidad de trabajar con mltiples redes
lgicas sobre una nica red fsica.

Archivo net.c: en este archivo se encuentran implementadas las primitivas declaradas en


el archivo net.h.

Archivo tp.h: en este archivo se declaran las primitivas correspondientes al manejo de la


capa de transporte. Dichas primitivas brindan la capacidad de trabajar con grupos de
difusin utilizando redes lgicas.

Archivo tp.c: en este archivo se encuentran implementadas las primitivas declaradas en el


archivo tp.h.

Archivo sp.h: en este archivo se declaran las primitivas correspondientes al manejo de la


capa de sesin. Dichas primitivas brindan la capacidad de administrar las sesiones de los
grupos de difusin.

Archivo sp.c: en este archivo se encuentran implementadas las primitivas declaradas en el


archivo sp.h.

Archivo modem.c: en este archivo se encuentra implementado el interprete de comandos


del modem PLC, con el cual se interacta por medio del puerto RS232.

C.5.1. Archivo config.h


/*
config.h
Definicin de parmetros de configuracin.
*/

FernandoArielBeunza79156

583

Tesis de Grado en Ingeniera Informtica

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Frecuencia de reloj del microcontrolador. */


#define F_CPU

11059200UL

/* Capa de fsica. */
/* Mxima cantidad de bytes que puede almacenar el buffer. */
#define PHY_PAYLOADSIZE
400
/* Cdigo de operacin de envo de trama. */
#define PHY_SNDFRMOP

0xa9

/* Cdigo de operacin de obtencin de trama capturada. */


#define PHY_GETFRMOP
0xaa
/* Cdigo de operacin de captura de trama. */
#define PHY_CAPFRMOP

0xab

/* Cdigo de operacin de reenvo de trama. */


#define PHY_RSDFRMOP

0xac

/* Cdigo de operacin de sensado del canal de comunicacin. */


#define PHY_SENSCHOP
0xad
/* Cdigo de operacin de generacin de seal de ruido. */
#define PHY_GENNOISEOP
0xae
/* Cdigo de limpieza del buffer. */
#define PHY_CRBUFFOP

0xaf

/* Cdigo de generacin de seal de prueba 1. */


#define PHY_TSTSIGOP1

0xba

/* Cdigo de generacin de seal de prueba 2. */


#define PHY_TSTSIGOP2

0xbb

/* Cdigo de prueba de recepcin. */


#define PHY_TSTRCVOP

0xbc

/* Capa de enlace (subcapa MAC). */


/* Mxima cantidad de bytes que puede contener un mensaje. */
#define MAC_PAYLOADSIZE
1024
/* Caracter delimitador. */
#define MAC_DELIMITERBYTE

0x7e

/* Unidad de tiempo de espera. */


#define MAC_UNITTIME

20

/* Tiempo entre mensajes. */


#define MAC_IFS

(MAC_UNITTIME * 100)

/* Cantidad mxima de reintentos de transmisin. */


#define MAC_MAXRETRIES

10

/* Cantidad mxima de errores tolerables. */


#define MAC_MAXERRORS

100

/* Nivel de umbral de deteccin de ocupacin del canal de comunicacin. */


#define MAC_THRBUSYCHANNEL
8
/* Direccin de broadcast. */
#define MAC_BROADCASTADDR_0

584

0xff

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#define
#define
#define
#define
#define
#define
#define

MAC_BROADCASTADDR_1
MAC_BROADCASTADDR_2
MAC_BROADCASTADDR_3
MAC_BROADCASTADDR_4
MAC_BROADCASTADDR_5
MAC_BROADCASTADDR_6
MAC_BROADCASTADDR_7

0xff
0xff
0xff
0xff
0xff
0xff
0xff

/* Posicin de memoria de cdigo donde se almacena la direccin fsica del


dispositivo. */
#define MAC_ADDRESS_ADDR
0xfff8
/* Tipos de mensaje. */
#define MAC_RTSMSG
#define MAC_DATAMSG

0x01
0x02

/* Capa de enlace (subcapa LLC). */


/* Cantidad mxima de conexiones simultneas. */
#define LLC_CONNECTIONS

/* Protocolos. */
#define LLC_ARPPROT
#define LLC_UNUSEDPROT

0x01
0x02

/* Protocolo de resolucin de direcciones (ARP). */


/* Cantidad de direcciones lgicas por dispositivo. */
#define ARP_ADDRESS

20

/* Cantidad mxima de reintentos de solicitud de direccin fsica. */


#define ARP_MAXRETRIES
10
/* Tipos de mensaje. */
#define ARP_REQUESTMSG
#define ARP_REPLYMSG

0x01
0x02

/* Protocolos. */
#define ARP_UNUSEDPROT

0x01

/* Capa de red. */
/* Mxima cantidad de bytes que puede contener un mensaje. */
#define NET_PAYLOADSIZE
1500
/* Identificador de protocolo de red. */
#define NET_PROTID

0x01

/* Cantidad de interfaces fsicas presentes en el dispositivo. */


#define NET_PHYINTERFACES
1
/* Versin del protocolo de red. */
#define NET_VERSION

/* Capa de transporte. */
/* Tamao del buffer de mensajes. */
#define TP_BUFFERSIZE

(14 * 1024)

/* Identificador de protocolo de transporte. */


#define TP_PROTID

0x01

/* Versin del protocolo de transporte. */


#define TP_VERSION

/* Nivel de prioridad para mensajes con mxima prioridad. */


#define TP_MAXPRIOMSG
0

FernandoArielBeunza79156

585

Tesis de Grado en Ingeniera Informtica


/* Nivel de prioridad para mensajes con mxima mnima. */
#define TP_MINPRIOMSG

20

/* Capa de sesin. */
/* Versin del protocolo de transporte. */
#define SP_VERSION

/* Interfaz del modem PLC. */


/* Tamao de la lnea. */
#define MODPLC_CMDLINESIZE

80

/* Tipos de prompt utilizados. */


#define MODPLC_INITPROMPT
#define MODPLC_LAYPROMPT
#define MODPLC_NORMPROMPT
#define MODPLC_PARAMPROMPT

'#'
'?'
'$'
'>'

/* Tipos de reset. */
#define MODPLC_NORMRESET
#define MODPLC_PARAMRESET

"0"
'$'

/* Capas de acceso. */
#define MODPLC_PHYSICALLAYER
#define MODPLC_DATALINKLAYER
#define MODPLC_SESSIONLAYER

"1"
"2"
"3"

/* Cdigo de operaciones de la capa fsica. */


#define MODPLCPHY_RESET
#define MODPLCPHY_SNDFRAME
#define MODPLCPHY_CAPFRAME
#define MODPLCPHY_GETFRAME
#define MODPLCPHY_POLL
#define MODPLCPHY_RSDFRAME
#define MODPLCPHY_CLRBUFFER
#define MODPLCPHY_SENSECHANNEL
#define MODPLCPHY_GENSIGNAL
#define MODPLCPHY_TSTRECEIVE
#define MODPLCPHY_GETPAYLOADSIZE

MODPLC_NORMRESET
"1"
"2"
"3"
"4"
"5"
"6"
"7"
"8"
"9"
"a"

/* Tipos de seal. */
#define MODPLCPHY_NOISESIGNAL
#define MODPLCPHY_TESTSIGNAL1
#define MODPLCPHY_TESTSIGNAL2

0x01
0x02
0x03

/* Cdigo de operaciones de la capa de enlace. */


#define MODPLCDL_RESET
#define MODPLCDL_OPEN
#define MODPLCDL_CLOSE
#define MODPLCDL_SEND
#define MODPLCDL_RECEIVE
#define MODPLCDL_POLL
#define MODPLCDL_GETADDRESS
#define MODPLCDL_ADDLOGADDRESS
#define MODPLCDL_DELLOGADDRESS
#define MODPLCDL_GETPHYADDRESS
#define MODPLCDL_GETPAYLOADSIZE

MODPLC_NORMRESET
"1"
"2"
"3"
"4"
"5"
"6"
"7"
"8"
"9"
"a"

/* Cdigo de operaciones de la capa de sesin. */


#define MODPLCSP_RESET
#define MODPLCSP_PUBLISH
#define MODPLCSP_SUBSCRIBE
#define MODPLCSP_LEAVE
#define MODPLCSP_SEND
#define MODPLCSP_RECEIVE
#define MODPLCSP_POLL
#define MODPLCSP_GETPAYLOADSIZE

MODPLC_NORMRESET
"1"
"2"
"3"
"4"
"5"
"6"
"7"

586

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

#endif

C.5.2. Archivo common.h


/*
common.h:
Declaracin de funciones comunes.
*/

#if !defined(___COMMON_H__)
#define ___COMMON_H__

/* Archivos includos necesarios. */


#include "../common/common.h"

/* Definicin de funciones pblicas. */


/*
Funcin wait_usecs:
Espera el transcurso de una determinada microsegundos.
*/
void wait_usecs(long int);

#endif

C.5.3. Archivo common.c


/*
common.c:
Implementacin de funciones comunes.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "../common/common.c"

/* Implementacin de funciones pblicas. */


/*
Funcin wait_usecs:
Espera el transcurso de una determinada microsegundos.
*/
void wait_usecs(long int usecs)
{
/* Espera con watchdog desactivado. */
if (!__wdt_status__)
{
while(1)
{
__asm
nop
nop
nop
nop
nop
nop
nop

FernandoArielBeunza79156

;
;
;
;
;
;
;

587

Tesis de Grado en Ingeniera Informtica


__endasm;
if (usecs < ((66 * F_CPU) / 11059200UL)) break;
usecs -= ((66 * F_CPU) / 11059200UL);
}
return;
}
/* Espera con watchdog activado. */
while(1)
{
__asm
push
IE
;
clr
EA
;
mov
_WDTRST, #0x1e
;
mov
_WDTRST, #0xe1
;
pop
IE
;
__endasm;
if (usecs < ((66 * F_CPU) / 11059200UL)) break;
usecs -= ((66 * F_CPU) / 11059200UL);
}
}

C.5.4. Archivo serial.h


/*
serial.h:
Declaracin de funciones referentes a la UART.
*/

#include "../common/serial.h"

C.5.5. Archivo serial.c


/*
serial.c:
Implementacin de funciones referentes a la UART.
*/

#include "../common/serial.c"

C.5.6. Archivo phy.h


/*
phy.h:
Declaracin de funciones referentes a la capa fsica.
*/

#if !defined(__PHY_H__)
#define __PHY_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <stdlib.h>

/* Definicin de funciones pblicas. */


/*

588

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin phy_init:
Inicializa los recursos utilizados por la capa fsica.
*/
void phy_init(void);
/*
Funcin phy_release:
Libera los recursos utilizados por la capa fsica.
*/
void phy_release(void);
/*
Funcin phy_sndframe:
Enva una trama.
*/
short int phy_sndframe(const void *, short int);
/*
Funcin phy_capframe:
Captura una trama.
*/
int phy_capframe(short int);
/*
Funcin phy_getframe:
Obtiene una trama capturada previamente.
*/
short int phy_getframe(void *, short int);
/*
Funcin phy_notify:
Define una funcin manejadora de tramas capturadas.
*/
void phy_notify(void (*func)(void));
/*
Funcin phy_poll:
Verifica la captura de una trama.
*/
int phy_poll(void);
/*
Funcin phy_rsdframe:
Reenva una trama.
*/
int phy_rsdframe(void);
/*
Funcin phy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int phy_clrbuffer(void);
/*
Funcin phy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int phy_sensechannel(unsigned char, long int);
/*
Funcin phy_gennoisesignal:
Genera una seal de ruido.
*/
int phy_gennoisesignal(void);
/*
Funcin phy_tstsignal1:
Genera una seal de prueba 1.
*/
int phy_tstsignal1(void);

FernandoArielBeunza79156

589

Tesis de Grado en Ingeniera Informtica


/*
Funcin phy_tstsignal2:
Genera una seal de prueba 2.
*/
int phy_tstsignal2(void);
/*
Funcin phy_tstreceive:
Realiza una prueba de recepcin.
*/
int phy_tstreceive(void);
/*
Interrupcin INT0:
Procesa la seal recibida.
*/
extern void __phy_int0__(void) __interrupt 0;

#endif

C.5.7. Archivo phy.c


/*
phy.c:
Implementacin de funciones referentes a la capa fsica.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <string.h>
#include <at89x52.h>
#include "common.h"
#include "phy.h"

/* Variables globales. */
/* Buffer de envo de un byte. */
static __data unsigned char __phy_buffbyte__;
/* Funcin manejadora de tramas capturadas. */
static void (*__phy_recfun__)(void) __reentrant;

/* Declaracin de funciones privadas. */


static void __phy_waitendop__(void);
static int __phy_sendbyte__(void);
static int __phy_sendop__(unsigned char);

/* Implementacin de funciones pblicas. */


/*
Funcin phy_init:
Inicializa los recursos utilizados por la capa fsica.
*/
void phy_init(void)
{
/* Inicializa TXDAT y TXCLK. */
P1 |= 0x03;
/* Inicializa RXDAT y RXCLK. */
P3 |= 0x14;
/* Inicializa la funcin manejadora de tramas recibidas. */
__phy_recfun__ = NULL;

590

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


reset_watchdog();
}
/*
Funcin phy_release:
Libera los recursos utilizados por la capa fsica.
*/
void phy_release(void)
{
reset_watchdog();
__phy_recfun__ = NULL;
}
/*
Funcin phy_sndframe:
Enva una trama.
*/
short int phy_sndframe(const void *dat, short int size)
{
/* Variables. */
register short int send;
register unsigned char ea;
unsigned char *ptr;

/* Cantidad de bytes enviados. */


/* Estado de las interrupciones. */
/* Puntero a la trama. */

/* Verifica que el tamao de la trama no supere el mximo permitido. */


reset_watchdog();
if (size < 1)
return 0;
if (size < PHY_PAYLOADSIZE)
send = size;
else
send = PHY_PAYLOADSIZE;
/* Desactiva las interruciones. */
ea = EA;
EA = 0;
/* Enva el cdigo de operacin. */
__phy_buffbyte__ = PHY_SNDFRMOP;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != PHY_SNDFRMOP)
{
__phy_waitendop__();
EA = ea;
return 0;
}
/* Enva la trama. */
ptr = (unsigned char *) dat;
while(send)
{
__phy_buffbyte__ = *((__xdata unsigned char *) ptr);
if (!__phy_sendbyte__()) break;
*((__xdata unsigned char *) ptr) = __phy_buffbyte__;
send --;
ptr ++;
}
/* Espera comienzo de transmisin. */
P1 |= 0x02;
while(P3 & 0x04)
{
__asm
mov
_WDTRST, #0x1e
mov
_WDTRST, #0xe1

FernandoArielBeunza79156

;
;

591

Tesis de Grado en Ingeniera Informtica


__endasm;
}
/* Espera fin de transmisin. */
__phy_waitendop__();
/* Restaura el estado de las interrupciones. */
EA = ea;
/* Devuelve la cantidad de bytes enviados. */
return size - send;
}
/*
Funcin phy_capframe:
Captura una trama.
*/
int phy_capframe(short int size)
{
/* Variables. */
unsigned char hsize;
unsigned char lsize;
register unsigned char ea;

/* Parte alta de la cantidad de


bytes a capturar. */
/* Parte baja de la cantidad de
bytes a capturar. */
/* Estado de las interrupciones. */

/* Desactiva las interruciones. */


ea = EA;
EA = 0;
/* Enva el cdigo de operacin. */
__phy_buffbyte__ = PHY_CAPFRMOP;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != PHY_CAPFRMOP)
{
__phy_waitendop__();
EA = ea;
return 0;
}
/* Enva la cantidad de bytes a capturar. */
hsize = (unsigned char) (size >> 8);
lsize = (unsigned char) (size & 0x00ff);
__phy_buffbyte__ = hsize;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != hsize)
{
__phy_waitendop__();
EA = ea;
return 0;
}
__phy_buffbyte__ = lsize;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != lsize)
{

592

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


__phy_waitendop__();
EA = ea;
return 0;
}
__phy_waitendop__();
/* xito. */
EA = ea;
return 1;
}
/*
Funcin phy_getframe:
Obtiene una trama capturada previamente.
*/
short int phy_getframe(void *dat, short int size)
{
/* Variables. */
register short int receive;
register unsigned char ea;
unsigned char *ptr;

/* Cantidad de bytes recibidos. */


/* Estado de las interrupciones. */
/* Puntero a la trama. */

/* Verifica que el tamao de la trama no supere el mximo permitido. */


reset_watchdog();
if (size < 1)
return 0;
if (size < PHY_PAYLOADSIZE)
receive = size;
else
receive = PHY_PAYLOADSIZE;
/* Desactiva las interruciones. */
ea = EA;
EA = 0;
/* Enva el cdigo de operacin. */
__phy_buffbyte__ = PHY_GETFRMOP;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != PHY_GETFRMOP)
{
__phy_waitendop__();
EA = ea;
return 0;
}
/* Obtiene la trama. */
ptr = (unsigned char *) dat;
while(receive)
{
__phy_buffbyte__ = 0xff;
if (!__phy_sendbyte__()) break;
*((__xdata unsigned char *) ptr) = __phy_buffbyte__;
receive --;
ptr ++;
}
__phy_waitendop__();
/* Restaura el estado de las interrupciones. */
EA = ea;
/* Devuelve la cantidad de bytes recibidos. */
return size - receive;
}
/*

FernandoArielBeunza79156

593

Tesis de Grado en Ingeniera Informtica


Funcin phy_notify:
Define una funcin manejadora de tramas capturadas.
*/
void phy_notify(void (*func)(void))
{
/* Define el manejador. */
__phy_recfun__ = func;
/* Activa interrupcin exterior. */
cli();
IE &= 0xfe;
TCON &= 0xfd;
TCON |= 0x01;
if (__phy_recfun__) IE |= 0x01;
sei();
reset_watchdog();
}
/*
Funcin phy_poll:
Verifica la captura de una trama.
*/
int phy_poll(void)
{
reset_watchdog();
if (P3 & 0x04) return 0;
return 1;
}
/*
Funcin phy_rsdframe:
Reenva una trama.
*/
int phy_rsdframe(void)
{
/* Variables. */
register unsigned char ea;

/* Estado de las interrupciones. */

/* Desactiva las interruciones. */


ea = EA;
EA = 0;
/* Enva el cdigo de operacin. */
__phy_buffbyte__ = PHY_RSDFRMOP;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != PHY_RSDFRMOP)
{
__phy_waitendop__();
EA = ea;
return 0;
}
/* Espera comienzo de transmisin. */
P1 |= 0x02;
while(P3 & 0x04)
{
__asm
mov
_WDTRST, #0x1e
mov
_WDTRST, #0xe1
__endasm;
}

;
;

/* Espera fin de transmisin. */


__phy_waitendop__();

594

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Restaura el estado de las interrupciones. */
EA = ea;
/* xito. */
return 1;
}
/*
Funcin phy_clrbuffer:
Limpia el buffer de captura de tramas.
*/
int phy_clrbuffer(void)
{
return __phy_sendop__(PHY_CRBUFFOP);
}
/*
Funcin phy_sensechannel:
Sensa el estado del canal de comunicacin.
*/
int phy_sensechannel(unsigned char thrl, long int usecs)
{
/* Variables. */
int busych;
unsigned char thrlevel;

register unsigned char ea;

/* Indicador de canal ocupado. */


/* Nivel de umbral de deteccin de
ocupacin de canal de
comunicacin. */
/* Estado de las interrupciones. */

/* Desactiva las interruciones. */


ea = EA;
EA = 0;
/* Enva el cdigo de operacin. */
__phy_buffbyte__ = PHY_SENSCHOP;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != PHY_SENSCHOP)
{
__phy_waitendop__();
EA = ea;
return 0;
}
/* Enva el nivel de umbral de deteccin de ocupacin de canal
comunicacin. */
thrlevel = thrl;
__phy_buffbyte__ = thrlevel;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != thrlevel)
{
__phy_waitendop__();
EA = ea;
return 0;
}
/* Espera comienzo del sensado del canal de comunicacin. */
P1 |= 0x02;
while(!(P3 & 0x04))
{
__asm

FernandoArielBeunza79156

595

Tesis de Grado en Ingeniera Informtica


mov
_WDTRST, #0x1e
mov
_WDTRST, #0xe1
__endasm;

;
;

}
wait_usecs(1000);
/* Espera durante el tiempo especificado la ocupacin del canal
comunicacin. */
while(P3 & 0x04)
{
wait_usecs(66);
if (usecs < ((66 * F_CPU) / 11059200UL)) break;
usecs -= ((66 * F_CPU) / 11059200UL);
}
busych = 2;
if (P3 & 0x04) busych = 1;
__phy_sendop__(0x00);
/* Restaura el estado de las interrupciones. */
EA = ea;
/* No se detect ocupacin del canal de comunicacin. */
return busych;
}
/*
Funcin phy_gennoisesignal:
Genera una seal de ruido.
*/
int phy_gennoisesignal(void)
{
return __phy_sendop__(PHY_GENNOISEOP);
}
/*
Funcin phy_tstsignal1:
Genera una seal de prueba 1.
*/
int phy_tstsignal1(void)
{
return __phy_sendop__(PHY_TSTSIGOP1);
}
/*
Funcin phy_tstsignal2:
Genera una seal de prueba 2.
*/
int phy_tstsignal2(void)
{
return __phy_sendop__(PHY_TSTSIGOP2);
}
/*
Funcin phy_tstreceive:
Realiza una prueba de recepcin.
*/
int phy_tstreceive(void)
{
return __phy_sendop__(PHY_TSTRCVOP);
}

/* Implementacin de funciones privadas. */


/*
Interrupcin INT0:
Procesa la seal recibida.
*/
void __phy_int0__(void) __interrupt 0
{
cli();

596

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


reset_watchdog();
if (__phy_recfun__) __phy_recfun__();
sei();
}
/*
Funcin __phy_waitendop__:
Espera fin de recepcin de operacin.
*/
static void __phy_waitendop__(void)
{
/* Variables. */
unsigned short int i;

/* Contador. */

/* Espera fin de recepcin de operacin. */


while(1)
{
P1 |= 0x02;
while(!(P3 & 0x04))
{
__asm
mov
_WDTRST, #0x1e
;
mov
_WDTRST, #0xe1
;
__endasm;
}
for(i = 0; (i < ((50 * F_CPU) / 11059200UL)) && (P3 & 0x04); i++)
{
__asm
mov
_WDTRST, #0x1e
;
mov
_WDTRST, #0xe1
;
__endasm;
}
if (P3 & 0x04) break;
}
TCON &= 0xfd;
}
/*
Funcin __phy_sendbyte__:
Enva un byte del mensaje.
*/
static int __phy_sendbyte__(void)
{
/* Variables. */
register short int i;

/* Sincronizacin. */
P1 &= 0xfd;
for(i = 0; i < 0x4000; i++)
{
__asm
mov
_WDTRST, #0x1e
mov
_WDTRST, #0xe1
__endasm;
if (!(P3 & 0x04)) break;
}
if (P3 & 0x04) return 0;
/* Envo del byte. */
__asm
push
push
nop
mov
clr
rlc
mov
setb
nop

acc
psw
a, ___phy_buffbyte__
P1.1
a
P1.0, C
P1.1

FernandoArielBeunza79156

/* Contador. */

;
;

;
;
;
; Carga el byte a enviar.
; Enva el bit 0.
;
;
;
;

597

Tesis de Grado en Ingeniera Informtica


mov
clr
rlc
mov
setb
nop
mov
clr
rlc
mov
setb
nop
mov
clr
rlc
mov
setb
nop
mov
clr
rlc
mov
setb
nop
mov
clr
rlc
mov
setb
nop
mov
clr
rlc
mov
setb
nop
mov
clr
rlc
mov
setb
nop
mov
clr
rlc
setb
mov
nop
pop
pop

C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0, C
P1.1
C, P3.4
P1.1
a
P1.0
___phy_buffbyte__, a
psw
acc

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Enva el bit 1.

Enva el bit 2.

Enva el bit 3.

Enva el bit 4.

Enva el bit 5.

Enva el bit 6.

Enva el bit 7.

Fin.

__endasm;
return 1;
}
/*
Funcin __phy_sendop__:
Enva una solicitud de ejecucin de una operacin.
*/
static int __phy_sendop__(unsigned char op)
{
/* Variables. */
register unsigned char ea;

/* Estado de las interrupciones. */

/* Reinicia el watchdog. */
reset_watchdog();
/* Desactiva las interruciones. */
ea = EA;
EA = 0;

598

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Enva el cdigo de operacin. */
__phy_buffbyte__ = op;
if (!__phy_sendbyte__())
{
__phy_waitendop__();
EA = ea;
return 0;
}
if (__phy_buffbyte__ != op)
{
__phy_waitendop__();
EA = ea;
return 0;
}
__phy_waitendop__();
/* Restaura el estado de las interrupciones. */
EA = ea;
/* xito. */
return 1;
}

C.5.8. Archivo mac.h


/*
mac.h:
Declaracin de funciones referentes a la capa de enlace (subcapa MAC).
*/

#if !defined(__MAC_H__)
#define __MAC_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "phy.h"

/* Definicin de tipos. */
/* Direccin fsica de dispositivo. */
typedef unsigned char mac_addr[8];
/* Encabezado del mensaje. */
typedef struct
{
unsigned char delimiter;
mac_addr src_addr;
mac_addr dest_addr;
unsigned char type;
unsigned char protocol;
unsigned char fragment;
unsigned short int size;
unsigned short int total_size;
} __mac_header__;

/*
/*
/*
/*
/*
/*
/*
/*
/*

/* Definicin de constantes. */
#define MAC_HEADERSIZE
#define MAC_FCSSIZE

sizeof(__mac_header__)
sizeof(unsigned short int)

Comienzo de mensaje. */
Direccin de origen. */
Direccin de destino. */
Tipo de mensaje. */
Identificador de protocolo. */
Nmero de fragmento. */
Tamao del mensaje. */
Tamao total. */
Encabezado del mensaje. */

/* Direccin de broadcast. */
static __code mac_addr __mac_broadcastaddr__ = {
MAC_BROADCASTADDR_0, MAC_BROADCASTADDR_1,
MAC_BROADCASTADDR_2, MAC_BROADCASTADDR_3,
MAC_BROADCASTADDR_4, MAC_BROADCASTADDR_5,

FernandoArielBeunza79156

599

Tesis de Grado en Ingeniera Informtica


MAC_BROADCASTADDR_6, MAC_BROADCASTADDR_7
};

/* Definicin de funciones pblicas. */


/*
Funcin mac_init:
Inicializa los recursos utilizados por la subcapa MAC.
*/
void mac_init(void);
/*
Funcin mac_release:
Libera los recursos utilizados por la subcapa MAC.
*/
void mac_release(void);
/*
Funcin mac_send:
Enva un mensaje por medio de la subcapa MAC.
*/
short int mac_send(mac_addr, unsigned char, unsigned char, const void *,
short int);
/*
Funcin mac_receive:
Recibe un mensaje por medio de la subcapa MAC.
*/
short int mac_receive(mac_addr, unsigned char *, void *, short int);
/*
Funcin mac_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void mac_notify(void (*func)(mac_addr, unsigned char, void *, short int));
/*
Funcin mac_poll:
Verifica la llegada de un nuevo mensaje.
*/
int mac_poll(void);
/*
Funcin mac_acceptprotocol:
Establece la recepcin de mensajes cuyo identificador de protocolo coincide
con el especificado.
*/
int mac_acceptprotocol(unsigned char);
/*
Funcin mac_rejectprotocol:
Bloquea la recepcin de mensajes cuyo identificador de protocolo coincide
con el especificado.
*/
int mac_rejectprotocol(unsigned char);
/*
Funcin mac_status:
Devuelve el estado del dispositivo.
*/
int mac_status(void);
/*
Funcin mac_getaddress:
Devuelve la direccin fsica del dispositivo.
*/
void mac_getaddress(mac_addr);

#endif

600

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

C.5.9. Archivo mac.c


/*
mac.c:
Implementacin de funciones referentes a la capa de enlace (subcapa MAC).
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <string.h>
#include "common.h"
#include "phy.h"
#include "mac.h"

/* Definicin de constantes. */
/* Tamao de un mensaje corto. */
#define MAC_SMSGSIZE

/* Tamao mximo de un fragmento de mensaje. */


#define MAC_FRAGMENTSIZE

(2 * (MAC_HEADERSIZE + \
MAC_FCSSIZE))

(PHY_PAYLOADSIZE - \
MAC_HEADERSIZE - MAC_FCSSIZE)

/* Direccin asignada al dispositivo. */


static __code __at (MAC_ADDRESS_ADDR) mac_addr __mac_address__;

/* Variables globales. */
/* Tamao del mensaje almacenado en el primer buffer. */
static volatile short int __mac_msg_size1__;
/* Tamao del mensaje almacenado en el segundo buffer. */
static volatile short int __mac_msg_size2__;
/* ltimo nmero de fragmento recibido. */
static volatile short int __mac_msg_last_frag__;
/* Tamao del ltimo fragmento recibido. */
static volatile short int __mac_msg_last_frag_size__;
/* Direccin de origen del mensaje recibido. */
static volatile mac_addr __mac_msg_address__;
/* Contador de errores ocurridos. */
static volatile unsigned char __mac_errors__;
/* Identificador de protocolo del mensaje recibido. */
static volatile unsigned char __mac_msg_protocol__;
/* Valor del ltimo nmero pseudoaleatorio generado. */
static unsigned char __mac_randnum__;
/* Tabla de bloqueo de protocolos. */
static volatile __mac_prot_block__[32];
/* Primer buffer de recepcin de mensajes. */
static volatile unsigned char __mac_msg_buffer1__[MAC_PAYLOADSIZE];
/* Segundo buffer de recepcin de mensajes. */
static volatile unsigned char __mac_msg_buffer2__[MAC_PAYLOADSIZE];
/* Funcin manejadora de mensajes recibidos. */
static void (*__mac_recfun__)(mac_addr, unsigned char, void *, short int)

FernandoArielBeunza79156

601

Tesis de Grado en Ingeniera Informtica


__reentrant;

/* Definicin de funciones privadas. */


static void __mac_procmsg__(void);
static int __mac_sensechannel__(int);
static int __mac_sendmsg__(mac_addr, unsigned char, unsigned char,
unsigned char, short int, short int, const void *);
static unsigned char __mac_receivemsg__(unsigned char *, mac_addr, mac_addr,
unsigned char *, unsigned char *,
unsigned char *, short int *,
short int *);

/* Implementacin de funciones pblicas. */


/*
Funcin mac_init:
Inicializa los recursos utilizados por la subcapa MAC.
*/
void mac_init(void)
{
/* Variables. */
unsigned char i;

/* ndice de tabla de bloqueo de


protocolos. */

/* Inicializa los recursos utilizados por la capa fsica. */


phy_init();
/* Define un manejador de mensajes recibidos por la capa fsica. */
phy_notify(__mac_procmsg__);
/* Inicializa el buffer de mensajes. */
__mac_msg_size1__ = 0;
__mac_msg_size2__ = 0;
__mac_msg_last_frag__ = -1;
__mac_msg_last_frag_size__ = 0;
__mac_msg_protocol__ = 0;
/* Inicializa el contador de errores. */
__mac_errors__ = 0;
/* Inicializa la tabla de bloqueo de protocolos, bloqueando todos los
protocolos. */
for(i = 0; i < 32; i++) __mac_prot_block__[i] = 0xff;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__mac_recfun__ = NULL;
/* Define la semilla para la generacin del tiempo de espera
pseudoaleatorio. */
__mac_randnum__ = __mac_address__[0];
/* Establece el modo captura. */
reset_watchdog();
phy_capframe(MAC_HEADERSIZE + MAC_SMSGSIZE + MAC_FCSSIZE);
}
/*
Funcin mac_release:
Libera los recursos utilizados por la subcapa MAC.
*/
void mac_release(void)
{
phy_notify(NULL);
phy_release();
}
/*
Funcin mac_send:

602

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Enva un mensaje por medio de la subcapa MAC.
*/
short int mac_send(mac_addr dest_addr, unsigned char prio,
const void *msg, short int msgsize)
{
/* Variables. */
int rsend;
int result;
int chstatus;
short int wait;
short int tosend;
short int fragsize;
unsigned char frag;
unsigned char retries;
unsigned char *ptrmsg;

unsigned char prot,

/* Indicador de reenvo. */
/* Resultado del envo. */
/* Estado del canal de
comunicacin. */
/* Espera. */
/* Cantidad de bytes a enviar. */
/* Tamao del fragmento. */
/* Nmero de fragmento. */
/* Cantidad de reintentos de
envo. */
/* Puntero al mensaje a enviar. */

/* Verifica que el dispositivo no se haya desactivado por sobrepasar el


contador de errores. */
reset_watchdog();
if (__mac_errors__ > MAC_MAXERRORS) return 0;
/* Verifica que el identificador de protocolo sea vlido. */
if (!prot) return 0;
/* Verifica que el tamao del mensaje no supere el mximo permitido. */
if (msgsize > MAC_PAYLOADSIZE) return 0;
/* Verifica que el transmisor no se envie un mensaje a si mismo. */
if (memccmp1(dest_addr, __mac_address__, sizeof(mac_addr)))
return 0;
/* Enva el mensaje. */
phy_notify(NULL);
rsend = 0;
fragsize = MAC_FRAGMENTSIZE;
for(retries = 0; (retries < MAC_MAXRETRIES) && (msgsize); )
{
/* Agrega un tiempo de espera pseudoaleatorio. */
if (retries)
{
__mac_randnum__ = ((__mac_randnum__ << 7) ^
(__mac_randnum__ & 0x80)) |
(__mac_randnum__ >> 1);
wait = __mac_randnum__;
if (retries < 5)
wait %= (2 << (retries + 5));
else
wait %= (2 << 10);
while(wait--) wait_usecs(MAC_UNITTIME);
}
retries ++;
/* Sensa el estado del canal de comunicacin. */
chstatus = phy_sensechannel(MAC_THRBUSYCHANNEL, (MAC_HEADERSIZE +
MAC_PAYLOADSIZE + MAC_FCSSIZE) * 192UL);
if (chstatus == 0)
{
msgsize = 0;
break;
}
if (chstatus == 2) continue;
/* Introduce una espera en base a la prioridad del mensaje. */
do
{
wait_usecs(MAC_UNITTIME);
} while(--prio);

FernandoArielBeunza79156

603

Tesis de Grado en Ingeniera Informtica


/* Sensa el estado del canal de comunicacin. */
chstatus = phy_sensechannel(MAC_THRBUSYCHANNEL, MAC_UNITTIME);
if (chstatus == 0)
{
msgsize = 0;
break;
}
if (chstatus == 2) continue;
/* Si el mensaje es un mensaje de datos corto, se enva
directamente. */
if (msgsize <= MAC_SMSGSIZE)
{
/* Enva el mensaje corto. */
if (rsend)
result = phy_rsdframe();
else
result = __mac_sendmsg__(dest_addr, MAC_DATAMSG, prot, 0,
msgsize, msgsize, msg);
if (result)
{
if (__mac_sensechannel__(1)) break;
}
rsend = 1;
wait_usecs(MAC_IFS);
__mac_errors__ ++;
continue;
}
/* Envia mensaje de RTS para notificar a los destinatarios que se
enviar un mensaje largo de datos. */
if (rsend)
result = phy_rsdframe();
else
result = __mac_sendmsg__(dest_addr, MAC_RTSMSG, prot, 0, fragsize,
msgsize, NULL);
rsend = 1;
if (!result)
{
wait_usecs(MAC_IFS);
continue;
}
if (!__mac_sensechannel__(1))
{
__mac_errors__ ++;
continue;
}
rsend = 0;
/* Enva el mensaje largo por medio de uno o mas fragmentos. */
frag = 0;
retries = 0;
tosend = msgsize;
ptrmsg = (unsigned char *) msg;
while((tosend) && (retries < MAC_MAXRETRIES))
{
/* Verifica que el fragmento no sea mas pequeo que un mensaje de
datos corto. */
if (tosend < (MAC_SMSGSIZE * 2)) fragsize = MAC_SMSGSIZE * 2;
/* Verifica que el fragmento no sea mas grande que la cantidad de
bytes a enviar del mensaje de datos. */
if (tosend < fragsize) fragsize = tosend;
/* Enva el fragmento de mensaje de datos. */
if (rsend)
result = phy_rsdframe();
else
result = __mac_sendmsg__(dest_addr, MAC_DATAMSG, prot, frag,
fragsize, msgsize, ptrmsg);
if (result)

604

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
if (__mac_sensechannel__(1))
{
frag ++;
tosend -= fragsize;
ptrmsg += fragsize;
rsend = 0;
continue;
}
}
wait_usecs(MAC_IFS);
rsend = 1;
/* Si no se pudo enviar el fragmento, disminuye el tamao del
fragmento y reintenta el envo. */
if ((fragsize >> 1) > MAC_SMSGSIZE)
{
fragsize >>= 1;
rsend = 0;
}
retries ++;
__mac_errors__ ++;
}
if (!tosend) break;
}
if (retries >= MAC_MAXRETRIES)
msgsize = 0;
else
__mac_errors__ = 0;
/* Establece el modo captura. */
phy_clrbuffer();
phy_notify(__mac_procmsg__);
phy_capframe(MAC_HEADERSIZE + MAC_SMSGSIZE + MAC_FCSSIZE);
/* Devuelve el tamao del mensaje enviado. */
return msgsize;
}
/*
Funcin mac_receive:
Recibe un mensaje por medio de la subcapa MAC.
*/
short int mac_receive(mac_addr addr, unsigned char *prot, void *msg,
short int msgsize)
{
/* Verifica que el dispositivo no se haya desactivado por sobrepasar el
contador de errores. */
reset_watchdog();
if (__mac_errors__ > MAC_MAXERRORS) return 0;
/* Espera la llegada de un mensaje. */
while(!mac_poll());
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
phy_notify(NULL);
*prot = __mac_msg_protocol__;
if (addr) memcpy1(addr, __mac_msg_address__, sizeof(mac_addr));
if (msg) memcpy2(msg, msgsize, __mac_msg_buffer2__, __mac_msg_size2__);
if (msgsize > __mac_msg_size2__) msgsize = __mac_msg_size2__;
__mac_msg_size2__ = 0;
phy_notify(__mac_procmsg__);
/* Devuelve el tamao del mensaje recibido. */
return msgsize;
}
/*
Funcin mac_notify:
Define una funcin manejadora de mensajes recibidos.
*/

FernandoArielBeunza79156

605

Tesis de Grado en Ingeniera Informtica


void mac_notify(void (*func)(mac_addr, unsigned char, void *, short int))
{
reset_watchdog();
if (__mac_errors__ <= MAC_MAXERRORS) __mac_recfun__ = func;
}
/*
Funcin mac_poll:
Verifica la llegada de un nuevo mensaje.
*/
int mac_poll(void)
{
reset_watchdog();
if (__mac_errors__ > MAC_MAXERRORS) return 0;
return (__mac_msg_size2__ != 0);
}
/*
Funcin mac_acceptprotocol:
Establece la recepcin de mensajes cuyo identificador de protocolo coincide
con el especificado.
*/
int mac_acceptprotocol(unsigned char prot)
{
/* Verifica que el dispositivo no se haya desactivado por sobrepasar el
contador de errores. */
reset_watchdog();
if (__mac_errors__ > MAC_MAXERRORS) return 0;
/* Verifica que el identificador de protocolo sea vlido. */
if (!prot) return 0;
/* Desbloquea la recepcin de mensajes cuyo identificador de protocolo
coincide con el especificado. */
__mac_prot_block__[prot >> 3] &= (0xff ^ (1 << (prot & 0x07)));
return 1;
}
/*
Funcin mac_rejectprotocol:
Bloquea la recepcin de mensajes cuyo identificador de protocolo coincide
con el especificado.
*/
int mac_rejectprotocol(unsigned char prot)
{
/* Verifica que el dispositivo no se haya desactivado por sobrepasar el
contador de errores. */
reset_watchdog();
if (__mac_errors__ > MAC_MAXERRORS) return 0;
/* Verifica que el identificador de protocolo sea vlido. */
if (!prot) return 0;
/* Bloquea la recepcin de mensajes cuyo identificador de protocolo
coincide con el especificado. */
__mac_prot_block__[prot >> 3] |= (1 << (prot & 0x07));
return 1;
}
/*
Funcin mac_status:
Devuelve el estado del dispositivo.
*/
int mac_status(void)
{
reset_watchdog();
return (__mac_errors__ <= MAC_MAXERRORS);
}
/*
Funcin mac_getaddress:

606

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Devuelve la direccin fsica del dispositivo.
*/
void mac_getaddress(mac_addr addr)
{
memccpy1(addr, __mac_address__, sizeof(mac_addr));
}

/* Implementacin de funciones privadas. */


/*
Funcin __mac_procmsg__:
Procesa un mensaje recibido por medio de la capa fsica.
*/
static void __mac_procmsg__(void)
{
/* Variables. */
int error;
int recstatus;
short int msgsize;
short int totalsize;
unsigned char msgtype;
unsigned char protocol;
unsigned char fragment;
mac_addr src_addr;
mac_addr dest_addr;

/* Indicador de error. */
/* Resultado de la recepcin del
mensaje. */
/* Tamao del mensaje recibido. */
/* Tamao total del mensaje. */
/* Tipo del mensaje recibido. */
/* Identificador de protocolo. */
/* Nmero de fragmento. */
/* Direccin de origen del
mensaje. */
/* Direccin de destino del
mensaje. */

/* Procesa un mensaje recibido por medio de la capa fsica. */


error = 0;
while(1)
{
/* Recibe y desarma el mensaje recibido. */
recstatus = __mac_receivemsg__(__mac_msg_buffer1__ +
__mac_msg_size1__, src_addr,
dest_addr, &msgtype, &protocol,
&fragment, &msgsize, &totalsize);
/* Verifica la direccin destinataria. */
if (recstatus & 0x08)
{
msgsize = MAC_SMSGSIZE;
break;
}
/* A cualquier mensaje que sea recibido, se responde generando una
seal de ruido para ocupar el canal de comunicacin y notificar al
origen que se ha recibido el mensaje. */
error = 1;
phy_gennoisesignal();
wait_usecs(MAC_UNITTIME);
/* Verifica si el mensaje recibido es vlido. */
if (recstatus & 0x7f) break;
/* Verifica si el identificador de protocolo del mensaje se encuentra
bloqueado o no. */
if (__mac_prot_block__[protocol >> 3] & (1 << (protocol & 0x07)))
break;
/* Verifica si el tipo de mensaje es desconocido. */
if ((msgtype != MAC_RTSMSG) && (msgtype != MAC_DATAMSG)) break;
/* Sensa el estado del canal de comunicacin a la espera de alguna
notificacin de error de otro receptor. */
error = 0;
__mac_errors__ = 0;
if (!__mac_sensechannel__(0)) break;

FernandoArielBeunza79156

607

Tesis de Grado en Ingeniera Informtica


/* Verifica si el mensaje recibido es un RTS. */
if (msgtype == MAC_RTSMSG)
{
__mac_msg_size1__ = 0;
__mac_msg_last_frag__ = -1;
__mac_msg_last_frag_size__ = 0;
__mac_msg_protocol__ = 0;
break;
}
/* Verifica si el mensaje recibido es un mensaje de datos. */
if (msgtype == MAC_DATAMSG)
{
if ((__mac_msg_last_frag__ >= 0) &&
(__mac_msg_last_frag__ == ((short int) fragment)))
__mac_msg_size1__ -= __mac_msg_last_frag_size__;
__mac_msg_size1__ += msgsize;
__mac_msg_last_frag__ = (short int) fragment;
__mac_msg_last_frag_size__ = msgsize;
if (__mac_msg_size1__ < totalsize) break;
}
/* Acepta el mensaje recibido. */
__mac_msg_last_frag__ = -1;
__mac_msg_last_frag_size__ = 0;
__mac_msg_size2__ = __mac_msg_size1__;
__mac_msg_size1__ = 0;
__mac_msg_protocol__ = protocol;
memcpy1(__mac_msg_address__, src_addr, sizeof(mac_addr));
memcpy1(__mac_msg_buffer2__, __mac_msg_buffer1__, __mac_msg_size2__);
/* Invoca a la funcin manejadora de mensajes recibidos registrada. */
reset_watchdog();
if (__mac_recfun__)
{
__mac_recfun__(__mac_msg_address__, __mac_msg_protocol__,
__mac_msg_buffer2__, __mac_msg_size2__);
__mac_msg_size2__ = 0;
reset_watchdog();
}
msgsize = MAC_SMSGSIZE;
break;
}
/* Verifica si se ha detectado algun error en cuyo caso prolonga la
ocupacin del canal de comunicacin para notificar al origen el
error. */
if (error)
{
wait_usecs(MAC_UNITTIME * 150);
msgsize = MAC_FRAGMENTSIZE;
__mac_errors__ ++;
}
/* Verifica que el dispositivo no se haya desactivado por sobrepasar el
contador de errores. */
if (__mac_errors__ > MAC_MAXERRORS)
{
__mac_recfun__ = NULL;
return;
}
/* Reestablece el modo captura. */
phy_clrbuffer();
phy_capframe(MAC_HEADERSIZE + msgsize + MAC_FCSSIZE);
}
/*
Funcin __mac_sensechannel__:
Sensa el estado del canal de comunicacin para obtener la confirmacin de

608

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


recepcin de un mensaje.
*/
static int __mac_sensechannel__(int wait)
{
/* Variables. */
int chstatus;
short int i;

/* Estado del canal de


comunicacin. */
/* Contador. */

/* Verifica si se solicita espera previa. */


if (wait)
{
if (phy_sensechannel(MAC_THRBUSYCHANNEL, 200000UL) != 2) return 0;
}
/* Determina el tiempo de ocupacin de canal de comunicacin para
determinar la correcta recepcin de un mensaje o la recepcin errnea
del mismo. */
i = 0;
while(1)
{
chstatus = phy_sensechannel(MAC_THRBUSYCHANNEL, MAC_UNITTIME);
if (chstatus != 2) break;
i ++;
}
if ((chstatus == 0) || (i > 0)) return 0;
return 1;
}
/*
Funcin __mac_sendmsg__:
Arma y enva un mensaje por medio de la capa fsica.
*/
static int __mac_sendmsg__(mac_addr addr, unsigned char type,
unsigned char prot, unsigned char frag,
short int size, short int tsize, const void *msg)
{
/* Variables. */
short int msgsize;
/* Tamao del mensaje. */
__mac_header__ *mac_header;
/* Encabezado del mensaje. */
unsigned char buffer[MAC_HEADERSIZE +
MAC_FRAGMENTSIZE + MAC_FCSSIZE];
/* Buffer para el armado del
mensaje. */

/* Carga el encabezado del mensaje. */


reset_watchdog();
mac_header = (__mac_header__ *) buffer;
mac_header->delimiter = MAC_DELIMITERBYTE;
memccpy1(mac_header->src_addr, __mac_address__, sizeof(mac_addr));
memcpy1(mac_header->dest_addr, addr, sizeof(mac_addr));
mac_header->type = type;
mac_header->protocol = prot;
mac_header->fragment = frag;
mac_header->size = usl2b((unsigned short int) size);
mac_header->total_size = usl2b((unsigned short int) tsize);
/* Verifica que la direccin de destino no sea igual a la de origen. */
if (memcmp1(mac_header->dest_addr, mac_header->src_addr,
sizeof(mac_addr)))
return 0;
/* Carga los datos del mensaje. */
if (size)
{
if (msg)
memcpy1(buffer + MAC_HEADERSIZE, msg, size);
else
size = 0;
}

FernandoArielBeunza79156

609

Tesis de Grado en Ingeniera Informtica


/* Carga la suma de verificacin. */
reset_watchdog();
*((unsigned short int *) (buffer + MAC_HEADERSIZE + size)) =
usl2b(getfcs(buffer, MAC_HEADERSIZE + size));
/* Enva el mensaje de control. */
msgsize = MAC_HEADERSIZE + size + MAC_FCSSIZE;
if (phy_sndframe(buffer, msgsize) == msgsize) return 1;
return 0;
}
/*
Funcin __mac_receivemsg__:
Recibe y desarma un mensaje para ser enviado por medio de la capa fsica.
*/
static unsigned char __mac_receivemsg__(unsigned char *msg, mac_addr src_addr,
mac_addr dest_addr,
unsigned char *type,
unsigned char *prot,
unsigned char *frag, short int *size,
short int *tsize)
{
/* Variables. */
short int msgsize;
/* Tamao del mensaje recibido. */
short int datsize;
/* Tamao de los datos del mensaje
recibido. */
unsigned char msgtype;
/* Tipo del mensaje recibido. */
unsigned char recstatus;
/* Resultado de la recepcin del
mensaje. */
__mac_header__ *mac_header;
/* Encabezado del mensaje. */
unsigned char buffer[MAC_HEADERSIZE +
MAC_FRAGMENTSIZE + MAC_FCSSIZE];
/* Buffer para desarmado de
mensaje. */

/* Carga el encabezado del mensaje. */


recstatus = 0;
reset_watchdog();
phy_getframe(buffer, MAC_HEADERSIZE + MAC_SMSGSIZE + MAC_FCSSIZE);
mac_header = (__mac_header__ *) buffer;
msgtype = mac_header->type;
msgsize = usb2l(mac_header->size);
/* Busca el delimitador del mensaje recibido. */
if (mac_header->delimiter != MAC_DELIMITERBYTE) recstatus |= 0x01;
/* Verifica que el tamao del mensaje sea vlido. */
reset_watchdog();
if (msgsize > MAC_PAYLOADSIZE)
{
msgsize = MAC_PAYLOADSIZE;
recstatus |= 0x02;
}
datsize = 0;
if (msgtype == MAC_DATAMSG) datsize = msgsize;
/* Si no se detectaron errores, lee el mensaje y verifica su validez. */
if (!recstatus)
{
/* Lee el mensaje recibido. */
if (datsize)
phy_getframe(buffer, MAC_HEADERSIZE + datsize + MAC_FCSSIZE);
/* Verifica la validez del mensaje recibido. */
reset_watchdog();
if (getfcs(buffer, MAC_HEADERSIZE + datsize) !=
usb2l(*((unsigned short int *)
(buffer + MAC_HEADERSIZE + datsize))))
recstatus |= 0x04;
}

610

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Verifica si la direccin destinataria es la de broadcast. */
reset_watchdog();
if (memccmp1(mac_header->dest_addr, __mac_broadcastaddr__,
sizeof(mac_addr)))
recstatus |= 0x80;
else
{
/* Verifica la direccin destinataria. */
if (!memccmp1(mac_header->dest_addr, __mac_address__,
sizeof(mac_addr)))
recstatus |= 0x08;
}
/* Verifica si se han detectado errores. */
if (recstatus & 0x7f) return recstatus;
/* Devuelve el mensaje recibido. */
if (src_addr) memcpy1(src_addr, mac_header->src_addr, sizeof(mac_addr));
if (dest_addr) memcpy1(dest_addr, mac_header->dest_addr, sizeof(mac_addr));
if (type) *type = msgtype;
if (prot) *prot = mac_header->protocol;
if (frag) *frag = mac_header->fragment;
if (size) *size = msgsize;
if (tsize) *tsize = usb2l(mac_header->total_size);
if (msg && datsize) memcpy1(msg, buffer + MAC_HEADERSIZE, datsize);
return recstatus;
}

C.5.10. Archivo llc.h


/*
llc.h:
Declaracin de funciones referentes a la capa de enlace (subcapa LLC).
*/

#if !defined(__LLC_H__)
#define __LLC_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "mac.h"

/* Definicin de tipos. */
/* Direccin fsica de dispositivo. */
typedef mac_addr llc_addr;

/* Definicin de constantes. */
#define LLC_FCSSIZE
#define LLC_PAYLOADSIZE
#define __llc_broadcastaddr__

sizeof(unsigned short int)


(MAC_PAYLOADSIZE - LLC_FCSSIZE)
__mac_broadcastaddr__

/* Definicin de funciones pblicas. */


/*
Funcin llc_init:
Inicializa los recursos utilizados por la subcapa LLC.
*/
void llc_init(void);
/*
Funcin llc_release:

FernandoArielBeunza79156

611

Tesis de Grado en Ingeniera Informtica


Libera los recursos utilizados por la subcapa LLC.
*/
#define llc_release()\
mac_release()
/*
Funcin llc_open:
Abre una conexin por medio de la subcapa LLC.
*/
int llc_open(unsigned char);
/*
Funcin llc_close:
Cierra una conexin por medio de la subcapa LLC.
*/
int llc_close(int);
/*
Funcin llc_send:
Enva un mensaje por medio de la subcapa LLC.
*/
short int llc_send(int, llc_addr, unsigned char, const void *, short int);
/*
Funcin llc_receive:
Recibe un mensaje por medio de la subcapa LLC.
*/
short int llc_receive(int, llc_addr, void *, short int);
/*
Funcin llc_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int llc_notify(int, void (*func)(llc_addr, void *, short int));
/*
Funcin llc_poll:
Verifica la llegada de un nuevo mensaje.
*/
int llc_poll(int);
/*
Funcin llc_status:
Devuelve el estado del dispositivo.
*/
#define llc_status()\
mac_status()
/*
Funcin llc_getaddress:
Devuelve la direccin fsica del dispositivo.
*/
#define llc_getaddress(addr)\
mac_getaddress(addr)

#endif

C.5.11. Archivo llc.c


/*
llc.c:
Implementacin de funciones referentes a la capa de enlace (subcapa LLC).
*/

/* Archivos includos necesarios. */


#include "config.h"

612

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#include
#include
#include
#include

<string.h>
"common.h"
"mac.h"
"llc.h"

/* Variables globales. */
/* Tabla de conexiones. */
static volatile struct llc_table
{
unsigned char protocol;
llc_addr src_addr;
short int size;
unsigned char buffer[LLC_PAYLOADSIZE];
void (*recfun)
(llc_addr, void *, short int)
__reentrant;

/* Protocolo. */
/* Direccin de origen. */
/* Tamao del mensaje almacenado en
el buffer. */
/* Buffer de recepcin de
mensajes. */

/* Funcin manejadora de mensajes


recibidos.*/

} __llc_table__[LLC_CONNECTIONS];

/* Definicin de funciones privadas. */


static void __llc_procmsg__(mac_addr, unsigned char, void *, short int)
__reentrant;
static int __llc_validhandle__(int);
static int __llc_findconn__(unsigned char);

/* Implementacin de funciones pblicas. */


/*
Funcin llc_init:
Inicializa los recursos utilizados por la subcapa LLC.
*/
void llc_init(void)
{
/* Variables. */
unsigned char con;

/* Nmero de conexin. */

/* Inicializa los recursos utilizados por la subcapa MAC. */


mac_init();
/* Define un manejador de mensajes recibidos por la subcapa MAC. */
mac_notify(__llc_procmsg__);
/* Inicializa la tabla de conexiones. */
for(con = 0; con < LLC_CONNECTIONS; con++)
{
reset_watchdog();
__llc_table__[con].protocol = 0;
}
}
/*
Funcin llc_open:
Abre una conexin por medio de la subcapa LLC.
*/
int llc_open(unsigned char prot)
{
/* Variables. */
int con;

/* Nmero de conexin. */

/* Verifica que el protocolo sea vlido. */


if ((!prot) || (prot & 0xf0)) return -1;
/* Busca una conexin disponible. */

FernandoArielBeunza79156

613

Tesis de Grado en Ingeniera Informtica


for(con = 0; con < LLC_CONNECTIONS; con++)
{
/* Si encuentra la conexin se encuentra en uso, continua buscando. */
reset_watchdog();
if (__llc_table__[con].protocol == prot) return con;
if (__llc_table__[con].protocol) continue;
/* Si hay una conexin disponible, la asigna y finaliza la busqueda. */
__llc_table__[con].protocol = prot;
__llc_table__[con].size = 0;
__llc_table__[con].recfun = NULL;
mac_acceptprotocol(__llc_table__[con].protocol);
return con;
}
/* No se puede abrir la conexin. */
return -1;
}
/*
Funcin llc_close:
Cierra una conexin por medio de la subcapa LLC.
*/
int llc_close(int handle)
{
/* Verifica que el manejador de conexin sea vlido. */
if (!__llc_validhandle__(handle)) return 0;
/* Libera la conexin. */
mac_rejectprotocol(__llc_table__[handle].protocol);
__llc_table__[handle].protocol = 0;
return 1;
}
/*
Funcin llc_send:
Enva un mensaje por medio de la subcapa LLC.
*/
short int llc_send(int handle, llc_addr dest_addr, unsigned char prio,
const void *msg, short int msgsize)
{
/* Variables. */
short int size;
/* Cantidad de bytes a enviar. */
unsigned char buffer[LLC_PAYLOADSIZE +
LLC_FCSSIZE];
/* Buffer para armado de
mensaje. */

/* Verifica que el manejador de conexin sea vlido. */


if (!__llc_validhandle__(handle)) return 0;
/* Verifica que el tamao del mensaje no supere el mximo permitido. */
if (msgsize > LLC_PAYLOADSIZE) return 0;
/* Verifica que la prioridad del mensaje sea vlida. */
if (prio > 0xfe) return 0;
/* Carga los datos del mensaje. */
memcpy1(buffer, msg, msgsize);
/* Carga la suma de verificacin. */
reset_watchdog();
*((unsigned short int *) (buffer + msgsize)) =
usl2b(getfcs(buffer, msgsize));
/* Enva el mensaje. */
size = msgsize + LLC_FCSSIZE;
if (mac_send(dest_addr, prio + 1, __llc_table__[handle].protocol, buffer,
size) == size)
return msgsize;
return 0;

614

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/*
Funcin llc_receive:
Recibe un mensaje por medio de la subcapa LLC.
*/
short int llc_receive(int handle, llc_addr addr, void *msg, short int msgsize)
{
/* Verifica que el manejador de conexin sea vlido. */
if (!__llc_validhandle__(handle)) return 0;
/* Espera la llegada de un mensaje. */
while(!llc_poll(handle));
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
if (addr) memcpy1(addr, __llc_table__[handle].src_addr, sizeof(llc_addr));
if (msg)
memcpy2(msg, msgsize, __llc_table__[handle].buffer,
__llc_table__[handle].size);
if (msgsize > __llc_table__[handle].size)
msgsize = __llc_table__[handle].size;
__llc_table__[handle].size = 0;
mac_acceptprotocol(__llc_table__[handle].protocol);
/* Devuelve el tamao del mensaje recibido. */
return msgsize;
}
/*
Funcin llc_notify:
Define una funcin manejadora de mensajes recibidos.
*/
int llc_notify(int handle, void (*func)(llc_addr, void *, short int))
{
/* Verifica que el manejador de conexin sea vlido. */
if (!__llc_validhandle__(handle)) return -1;
/* Cambia el manejador de mensajes recibidos. */
__llc_table__[handle].recfun = func;
return 1;
}
/*
Funcin llc_poll:
Verifica la llegada de un nuevo mensaje.
*/
int llc_poll(int handle)
{
/* Verifica que el manejador de conexin sea vlido. */
if (!__llc_validhandle__(handle)) return -1;
/* Devuelve la llegada de un nuevo mensaje. */
return (__llc_table__[handle].size != 0);
}

/* Implementacin de funciones privadas. */


/*
Funcin __llc_procmsg__:
Procesa un mensaje recibido por medio de la subcapa MAC.
*/
static void __llc_procmsg__(mac_addr addr, unsigned char prot, void *msg,
short int msgsize) __reentrant
{
/* Variables. */
int con;
/* Nmero de conexin registrada. */
unsigned char *rmsg;
/* Puntero al mensaje recibido. */

/* Verifica que el tamao del mensaje sea vlido. */

FernandoArielBeunza79156

615

Tesis de Grado en Ingeniera Informtica


reset_watchdog();
rmsg = (unsigned char *) msg;
if (msgsize <= LLC_FCSSIZE) return;
msgsize -= LLC_FCSSIZE;
if (msgsize > LLC_PAYLOADSIZE) return;
/* Verifica la validez del mensaje recibido. */
if (getfcs(rmsg, msgsize) !=
usb2l(*((unsigned short int *) (rmsg + msgsize))))
return;
/* Busca la conexin destinataria. */
con = __llc_findconn__(prot);
if (con == -1) return;
/* Verifica si se puede aceptar el mensaje entrante. */
if (__llc_table__[con].size) return;
/* Invoca a la funcin manejadora de mensajes recibidos registrada. */
reset_watchdog();
if (__llc_table__[con].recfun)
{
__llc_table__[con].recfun(addr, rmsg, msgsize);
reset_watchdog();
return;
}
/* Almacena el mensaje en el buffer de recepcin. */
__llc_table__[con].size = msgsize;
memcpy1(__llc_table__[con].buffer, rmsg, msgsize);
memcpy1(__llc_table__[con].src_addr, addr, sizeof(llc_addr));
mac_rejectprotocol(prot);
}
/*
Funcin __llc_validhandle__:
Verifica que el manejador de conexin sea vlido.
*/
static int __llc_validhandle__(int handle)
{
reset_watchdog();
return ((handle >= 0) && (handle < LLC_CONNECTIONS));
}
/*
Funcin __llc_findconn__:
Devuelve el manejador de la conexin solicitada.
*/
static int __llc_findconn__(unsigned char prot)
{
/* Variables. */
unsigned char con;

/* Nmero de conexin. */

/* Busca la conexin solicitada. */


for(con = 0; con < LLC_CONNECTIONS; con++)
{
reset_watchdog();
if (__llc_table__[con].protocol == prot) return con;
}
/* Conexin no encontrada. */
return -1;
}

C.5.12. Archivo arp.h


/*

616

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


arp.h:
Declaracin de funciones referentes al protocolo de resolucin de
direcciones lgicas (ARP).
*/

#if !defined(__ARP_H__)
#define __ARP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "llc.h"

/* Definicin de tipos. */
typedef unsigned long int arp_logaddr;

/* Definicin de funciones pblicas. */


/*
Funcin arp_init:
Inicializa los recursos utilizados por ARP.
*/
void arp_init(void);
/*
Funcin arp_release:
Libera los recursos utilizados por ARP.
*/
void arp_release(void);
/*
Funcin arp_addaddress:
Agrega una nueva direccin lgica al dispositivo.
*/
int arp_addaddress(unsigned char, arp_logaddr);
/*
Funcin arp_deladdress:
Elimina una direccin lgica al dispositivo.
*/
int arp_deladdress(unsigned char, arp_logaddr);
/*
Funcin arp_getaddress:
Devuelve la direccin fsica asociada a la direccin lgica y protocolo.
*/
int arp_getaddress(unsigned char, arp_logaddr, llc_addr);

#endif

C.5.13. Archivo arp.c


/*
arp.c:
Implementacin de funciones referentes al protocolo de resolucin de
direcciones lgicas (ARP).
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "common.h"
#include <string.h>
#include "llc.h"

FernandoArielBeunza79156

617

Tesis de Grado en Ingeniera Informtica


#include "arp.h"

/* Definicin de tipos. */
/* Mensaje ARP. */
typedef struct
{
unsigned char type;
unsigned char protocol;
arp_logaddr address;
} __arp_msg__;

/* Tipos de mensaje. */
/* Protocolo. */
/* Direccin lgica. */

/* Variables globales. */
/* Manejador de conexin para ARP. */
static volatile int __arp_conn__;
/* Tabla de direcciones. */
static volatile struct arp_table
{
unsigned char protocol;
arp_logaddr address;
} __arp_table__[ARP_ADDRESS];

/* Protocolo. */
/* Direccin. */

/* Definicin de funciones privadas. */


static int __arp_findaddr__(unsigned char, arp_logaddr);
static void __arp_procmsg__(llc_addr, void *, short int) __reentrant;

/* Implementacin de funciones pblicas. */


/*
Funcin arp_init:
Inicializa los recursos utilizados por ARP.
*/
void arp_init(void)
{
/* Variables. */
unsigned char dir;

/* Nmero de direccin. */

/* Inicializa la tabla de direcciones. */


for(dir = 0; dir < ARP_ADDRESS; dir++)
{
reset_watchdog();
__arp_table__[dir].protocol = 0;
}
/* Inicializa los recursos utilizados por ARP. */
llc_init();
/* Abre una conexin para ARP. */
__arp_conn__ = llc_open(LLC_ARPPROT);
if (__arp_conn__ < 0) return;
/* Define un manejador de mensajes recibidos por la subcapa LLC. */
llc_notify(__arp_conn__, __arp_procmsg__);
}
/*
Funcin arp_release:
Libera los recursos utilizados por ARP.
*/
void arp_release(void)
{
/* Cierra la conexin utilizada para ARP. */
llc_close(__arp_conn__);

618

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Libera los recursos utilizados por la subcapa LLC. */
llc_release();
}
/*
Funcin arp_addaddress:
Agrega una nueva direccin lgica al dispositivo.
*/
int arp_addaddress(unsigned char prot, arp_logaddr addr)
{
/* Variables. */
unsigned char dir;

/* Nmero de direccin. */

/* Verifica que el protocolo sea vlido. */


if (!prot) return 0;
/* Busca un lugar libre en la tabla de direcciones. */
for(dir = 0; dir < ARP_ADDRESS; dir++)
{
/* Si el lugar no se encuentra libre, contina buscando. */
reset_watchdog();
if ((__arp_table__[dir].protocol == prot) &&
(__arp_table__[dir].address == addr))
return dir;
if (__arp_table__[dir].protocol) continue;
/* Agrega la direccin. */
llc_notify(__arp_conn__, NULL);
__arp_table__[dir].protocol = prot;
__arp_table__[dir].address = addr;
llc_notify(__arp_conn__, __arp_procmsg__);
return 1;
}
/* No se pudo agregar la direccin. */
return 0;
}
/*
Funcin arp_deladdress:
Elimina una direccin lgica al dispositivo.
*/
int arp_deladdress(unsigned char prot, arp_logaddr addr)
{
/* Variables. */
int dir;

/* Nmero de direccin. */

/* Verifica que el protocolo sea vlido. */


if (!prot) return 0;
/* Verifica si existe la direccin. */
dir = __arp_findaddr__(prot, addr);
if (dir == -1) return 0;
/* Elimina la direccin de la tabla. */
llc_notify(__arp_conn__, NULL);
__arp_table__[dir].protocol = 0;
llc_notify(__arp_conn__, __arp_procmsg__);
return 1;
}
/*
Funcin arp_getaddress:
Devuelve la direccin fsica asociada a la direccin lgica y protocolo.
*/
int arp_getaddress(unsigned char prot, arp_logaddr laddr, llc_addr paddr)
{
/* Variables. */
short int i;
/* Contador. */

FernandoArielBeunza79156

619

Tesis de Grado en Ingeniera Informtica


int dir;
int result;
unsigned char retries;

llc_addr src_addr;
llc_addr llc_address;
__arp_msg__ msg;

/* Nmero de direccin. */
/* Resultado de la solicitud de
direccin fsica. */
/* Cantidad de reintentos de
solicitud de direccin
fsica. */
/* Direccin de origen del mensaje
de respuesta. */
/* Direccin del dispositivo. */
/* Mensaje ARP. */

/* Verifica que el protocolo sea vlido. */


if (!prot) return 0;
/* Verifica si la direccin lgica corresponde a la direcccin fsica del
dispositivo. */
dir = __arp_findaddr__(prot, laddr);
if (dir != -1)
{
llc_getaddress(llc_address);
memcpy1(paddr, llc_address, sizeof(llc_addr));
return 1;
}
/* Solicita la direccin fsica asociada a la direccin lgica
especificada. */
result = 0;
msg.type = ARP_REQUESTMSG;
if (__arp_conn__ < 0) return 0;
llc_notify(__arp_conn__, NULL);
for(retries = 0; retries < ARP_MAXRETRIES; retries++)
{
/* Lee cualquier mensaje pendiente. */
if (llc_poll(__arp_conn__))
{
/* Lee el mensaje recibido. */
llc_receive(__arp_conn__, src_addr, &msg, sizeof(llc_addr));
/* Verifica la validez del mensaje recibido. */
if ((msg.type == ARP_REPLYMSG) && (msg.protocol == prot) &&
(msg.address == laddr))
{
/* Devuelve la direccin fsica asociada a la direccin
lgica.*/
memcpy(paddr, src_addr, sizeof(llc_addr));
result = 1;
break;
}
}
/* Enva el mensaje de peticin de la direccin fsica asociada a la
direccin lgica. */
msg.type = ARP_REQUESTMSG;
msg.protocol = prot;
msg.address = laddr;
if (llc_send(__arp_conn__, __llc_broadcastaddr__, 0, &msg,
sizeof(__arp_msg__)) != sizeof(__arp_msg__))
break;
/* Espera respuesta. */
for(i = 0; (i < 3000) && (!llc_poll(__arp_conn__)); i++)
wait_usecs(1000);
}
/* No se pudo obtener la direccin fsica asociada a la direccin
lgica. */
llc_notify(__arp_conn__, __arp_procmsg__);
return result;
}

620

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Implementacin de funciones privadas. */
/*
Funcin __arp_findaddr__:
Devuelve el nmero de direccin almacenada en la tabla.
*/
static int __arp_findaddr__(unsigned char prot, arp_logaddr addr)
{
/* Variables. */
int dir;
/* Nmero de direccin. */

/* Verifica si ya existe la direccin. */


for(dir = 0; dir < ARP_ADDRESS; dir++)
{
if (__arp_table__[dir].protocol != prot) continue;
if (__arp_table__[dir].address != addr) continue;
return dir;
}
/* Conexin no encontrada. */
return -1;
}
/*
Funcin __arp_procmsg__:
Procesa un mensaje recibido por medio de la subcapa LLC.
*/
static void __arp_procmsg__(llc_addr addr, void *msg, short int msgsize)
__reentrant
{
/* Variables. */
__arp_msg__ *amsg;
/* Mensaje ARP. */

/* Carga el mensaje recibido. */


amsg = msg;
/* Verifica la validez del mensaje. */
if (msgsize != sizeof(__arp_msg__)) return;
/* Verifica si es una consulta. */
if (amsg->type != ARP_REQUESTMSG) return;
/* Verifica si existe la direccin lgica en la tabla. */
if (__arp_findaddr__(amsg->protocol, amsg->address) == -1) return;
/* Enva respuesta a consulta. */
amsg->type = ARP_REPLYMSG;
llc_send(__arp_conn__, addr, 0, amsg, sizeof(__arp_msg__));
}

C.5.14. Archivo dl.h


/*
dl.h:
Declaracin de funciones referentes a la interfaz de la capa de enlace.
*/

#if !defined(__DL_H__)
#define __DL_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "llc.h"

FernandoArielBeunza79156

621

Tesis de Grado en Ingeniera Informtica


#include "arp.h"

/* Definicin de tipos. */
/* Direccin fsica de dispositivo. */
typedef llc_addr dl_addr;
/* Direccin lgica de dispositivo. */
typedef arp_logaddr dl_logaddr;

/* Definicin de constantes. */
#define DL_PAYLOADSIZE

LLC_PAYLOADSIZE

/* Definicin de funciones pblicas. */


/*
Funcin dl_init:
Inicializa los recursos utilizados por la capa de enlace.
*/
int dl_init(unsigned char);
/*
Funcin dl_release:
Libera los recursos utilizados por la capa de enlace.
*/
int dl_release(unsigned char);
/*
Funcin dl_open:
Abre una conexin por medio de la capa de enlace.
*/
int dl_open(unsigned char, unsigned char);
/*
Funcin dl_close:
Cierra una conexin por medio de la capa de enlace.
*/
#define dl_close(hd)\
llc_close(hd)
/*
Funcin dl_send:
Enva un mensaje por medio de la capa de enlace.
*/
#define dl_send(hd, paddr, prio, msg, size)\
llc_send(hd, paddr, prio, msg, size)
/*
Funcin dl_receive:
Recibe un mensaje por medio de la capa de enlace.
*/
#define dl_receive(hd, paddr, msg, size)\
llc_receive(hd, paddr, msg, size)
/*
Funcin dl_notify:
Define una funcin manejadora de mensajes recibidos.
*/
#define dl_notify(hd, func)\
llc_notify(hd, func)
/*
Funcin dl_poll:
Verifica la llegada de un nuevo mensaje.
*/
#define dl_poll(hd)\
llc_poll(hd)

622

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin dl_getaddress:
Devuelve la direccin fsica del dispositivo.
*/
int dl_getaddress(unsigned char, dl_addr);
/*
Funcin dl_addlogaddress:
Agrega una nueva direccin lgica al dispositivo.
*/
int dl_addlogaddress(unsigned char, unsigned char, dl_logaddr);
/*
Funcin dl_dellogaddress:
Elimina una direccin lgica al dispositivo.
*/
int dl_dellogaddress(unsigned char, unsigned char, dl_logaddr);
/*
Funcin dl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica y protocolo.
*/
int dl_getphyaddress(unsigned char, unsigned char, dl_logaddr, dl_addr);
/*
Funcin dl_status:
Devuelve el estado de la interfaz especificada del dispositivo.
*/
int dl_status(unsigned char);
/*
Funcin dl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje.
*/
short int dl_getpayloadsize(unsigned char);

#endif

C.5.15. Archivo dl.c


/*
dl.c:
Implementacin de funciones referentes a la interfaz de la capa de enlace.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <string.h>
#include "common.h"
#include "dl.h"

/* Implementacin de funciones pblicas. */


/*
Funcin dl_init:
Inicializa los recursos utilizados por la capa de enlace.
*/
int dl_init(unsigned char iface)
{
if (iface != 0) return -1;
arp_init();
return 1;
}
/*

FernandoArielBeunza79156

623

Tesis de Grado en Ingeniera Informtica


Funcin dl_release:
Libera los recursos utilizados por la capa de enlace.
*/
int dl_release(unsigned char iface)
{
if (iface != 0) return -1;
arp_release();
return 1;
}
/*
Funcin dl_open:
Abre una conexin por medio de la capa de enlace.
*/
int dl_open(unsigned char iface, unsigned char prot)
{
if (iface != 0) return -1;
return llc_open(prot + LLC_UNUSEDPROT);
}
/*
Funcin dl_getaddress:
Devuelve la direccin fsica del dispositivo.
*/
int dl_getaddress(unsigned char iface, dl_addr addr)
{
if (iface != 0) return -1;
llc_getaddress(addr);
return 1;
}
/*
Funcin dl_addlogaddress:
Agrega una nueva direccin lgica al dispositivo.
*/
int dl_addlogaddress(unsigned char iface, unsigned char prot, dl_logaddr laddr)
{
if (iface != 0) return -1;
return arp_addaddress(ARP_UNUSEDPROT + prot, laddr);
}
/*
Funcin dl_dellogaddress:
Elimina una direccin lgica al dispositivo.
*/
int dl_dellogaddress(unsigned char iface, unsigned char prot, dl_logaddr laddr)
{
if (iface != 0) return -1;
return arp_deladdress(ARP_UNUSEDPROT + prot, laddr);
}
/*
Funcin dl_getphyaddress:
Devuelve la direccin fsica asociada a la direccin lgica y protocolo.
*/
int dl_getphyaddress(unsigned char iface, unsigned char prot, dl_logaddr laddr,
dl_addr paddr)
{
if (iface != 0) return -1;
return arp_getaddress(ARP_UNUSEDPROT + prot, laddr, paddr);
}
/*
Funcin dl_status:
Devuelve el estado de la interfaz especificada del dispositivo.
*/
int dl_status(unsigned char iface)
{
if (iface != 0) return 0;
return llc_status();
}

624

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin dl_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje.
*/
short int dl_getpayloadsize(unsigned char iface)
{
if (iface != 0) return -1;
return DL_PAYLOADSIZE;
}

C.5.16. Archivo net.h


/*
net.h:
Declaracin de funciones referentes a la capa de red.
*/

#if !defined(__NET_H__)
#define __NET_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "dl.h"

/* Definicin de tipos. */
/* Identificador de mensaje. */
typedef unsigned char net_msgid;
/* Identificador de nodo. */
typedef unsigned long int net_nodeid;
/* Encabezado del mensaje. */
typedef struct
{
unsigned char version;
net_msgid msgid;
unsigned char protocol;
unsigned short int size;
} __net_header__;

/* Definicin de constantes. */
#define NET_HEADERSIZE
#define NET_FCSSIZE

/* Versin de protocolo. */
/* Identificador de mensaje. */
/* Protocolo del contenido del
mensaje. */
/* Tamao del mensaje. */

sizeof(__net_header__)
sizeof(unsigned short int)

/* Definicin de funciones pblicas. */


/*
Funcin net_init:
Inicializa los recursos utilizados por la capa de red.
*/
void net_init(void);
/*
Funcin net_release:
Libera los recursos utilizados por la capa de red.
*/
void net_release(void);
/*
Funcin net_send:

FernandoArielBeunza79156

625

Tesis de Grado en Ingeniera Informtica


Enva un mensaje por medio de la capa de red.
*/
short int net_send(net_nodeid, net_msgid, unsigned char, unsigned char,
const void *, short int);
/*
Funcin net_receive:
Recibe un mensaje por medio de la capa de red.
*/
short int net_receive(net_msgid *, unsigned char *, void *, short int);
/*
Funcin net_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void net_notify(void (*func)(net_msgid, unsigned char, void *, short int));
/*
Funcin net_poll:
Verifica la llegada de un nuevo mensaje.
*/
int net_poll(void);
/*
Funcin net_addaddr:
Agrega una nueva direccin de nodo.
*/
int net_addaddr(net_nodeid);
/*
Funcin net_deladdr:
Elimina una direccin de nodo existente.
*/
int net_deladdr(net_nodeid);
/*
Funcin net_addmsgid:
Agrega un nuevo identificador de mensaje.
*/
int net_addmsgid(net_msgid);
/*
Funcin net_delmsgid:
Elimina un identificador de mensaje.
*/
int net_delmsgid(net_msgid);
/*
Funcin net_status:
Devuelve el estado del dispositivo.
*/
int net_status(void);
/*
Funcin net_getpayloadsize:
Devuelve la cantidad mxima de bytes que debe contener un mensaje para
poder ser enviado por cualquier interfaz.
*/
short int net_getpayloadsize(void);

#endif

C.5.17. Archivo net.c


/*
net.c:
Implementacin de funciones referentes a la capa de red.

626

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/

/* Archivos includos necesarios. */


#include "config.h"
#include <string.h>
#include "common.h"
#include "dl.h"
#include "net.h"

/* Variables globales. */
/* Tamao del mensaje almacenado en el primer buffer. */
static volatile short int __net_msg_size__;
/* Identificador de mensaje recibido. */
static net_msgid __net_msg_id__;
/* Protocolo del mensaje almacenado recibido. */
static volatile unsigned char __net_msg_protocol__;
/* Tabla de interfaces. */
static struct net_interfacetable
{
int hd;
unsigned char msgfilter[32];
} __net_interfacetable__[NET_PHYINTERFACES];

/* Manejador de conexin. */
/* Filtro de mensajes. */

/* Buffer de recepcin de mensajes. */


static volatile unsigned char __net_msg_buffer__[NET_PAYLOADSIZE];
/* Funcin manejadora de mensajes recibidos. */
static void (*__net_recfun__)(net_msgid, unsigned char, void *, short int)
__reentrant;

/* Definicin de funciones privadas. */


static void __net_procmsg__(dl_addr, void *, short int) __reentrant;
static short int __net_send__(unsigned char, dl_addr, net_msgid, unsigned char,
unsigned char, short int, const void *);

/* Implementacin de funciones pblicas. */


/*
Funcin net_init:
Inicializa los recursos utilizados por la capa de red.
*/
void net_init(void)
{
/* Variables. */
unsigned char iface;
unsigned char filter;

/* Identificador de interface. */
/* ndice de filtro de mensajes. */

/* Inicializa la tabla de ruteo. */


for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
/* Inicializa los recursos de la capa de enlace. */
dl_init(iface);
/* Abre una conexin. */
__net_interfacetable__[iface].hd = dl_open(iface, NET_PROTID);
/* Define un manejador de mensajes recibidos por la capa de enlace. */
dl_notify(__net_interfacetable__[iface].hd, __net_procmsg__);
/* Inicializa el filtro de mensajes. */
for(filter = 0; filter < 32; filter++)
{

FernandoArielBeunza79156

627

Tesis de Grado en Ingeniera Informtica


reset_watchdog();
__net_interfacetable__[iface].msgfilter[filter] = 0x00;
}
}
/* Inicializa los buffers de mensajes. */
__net_msg_size__ = 0;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__net_recfun__ = NULL;
}
/*
Funcin net_release:
Libera los recursos utilizados por la capa de red.
*/
void net_release(void)
{
/* Variables. */
unsigned char iface;

/* Identificador de interface. */

/* Inicializa todas las interfaces fsicas disponibles. */


for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
/* Cierra la conexin de recepcin. */
if (__net_interfacetable__[iface].hd >= 0)
dl_close(__net_interfacetable__[iface].hd);
/* Libera los recursos utilizados por la capa de enlace. */
dl_release(iface);
}
}
/*
Funcin net_send:
Enva un mensaje por medio de la capa de red.
*/
short int net_send(net_nodeid nodeid, net_msgid msgid, unsigned char prio,
unsigned char prot, const void *msg, short int msgsize)
{
/* Variables. */
int ack;
/* Indicador de envo correcto. */
unsigned char iface;
/* Identificador de interface. */
dl_addr dest_addr;
/* Direccin fsica de destino. */

/* Verifica que el tamao del mensaje no supere el mximo permitido. */


reset_watchdog();
if (msgsize > NET_PAYLOADSIZE) return 0;
/* Enva el mensaje a travs de todas las interfaces fsicas
disponibles. */
ack = 0;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
/* Aplica el filtro de mensajes. */
if (!(__net_interfacetable__[iface].msgfilter[msgid >> 3] &
(1 << (msgid & 0x07))))
continue;
/* Obtiene la direccin fsica del destinatario del mensaje. */
if (nodeid)
{
if (!dl_getphyaddress(iface, NET_PROTID, (dl_logaddr) nodeid,
dest_addr))
continue;
}
else
{
dest_addr[0] = 0xff;

628

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


dest_addr[1]
dest_addr[2]
dest_addr[3]
dest_addr[4]
dest_addr[5]
dest_addr[6]
dest_addr[7]

=
=
=
=
=
=
=

0xff;
0xff;
0xff;
0xff;
0xff;
0xff;
0xff;

}
/* Verifica el tamao del mensaje. */
if (msgsize > (dl_getpayloadsize(iface) - NET_HEADERSIZE NET_FCSSIZE))
continue;
/* Enva el fragmento del mensaje. */
if (__net_send__(iface, dest_addr, msgid, prio, prot, msgsize, msg) ==
msgsize)
ack = 1;
}
/* Devuelve el tamao del mensaje enviado. */
if (ack) return msgsize;
return 0;
}
/*
Funcin net_receive:
Recibe un mensaje por medio de la capa de red.
*/
short int net_receive(net_msgid *msgid, unsigned char *prot, void *msg,
short int msgsize)
{
/* Variables. */
unsigned char iface;
/* Identificador de interface. */

/* Espera la llegada de un mensaje. */


while(!net_poll());
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
if (msgid) *msgid = __net_msg_id__;
if (prot) *prot = __net_msg_protocol__;
if (msg) memcpy2(msg, msgsize, __net_msg_buffer__, __net_msg_size__);
if (msgsize > __net_msg_size__) msgsize = __net_msg_size__;
__net_msg_size__ = 0;
/* Activa los manejadores de mensajes recibidos por la capa de enlace. */
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
dl_notify(__net_interfacetable__[iface].hd, __net_procmsg__);
/* Devuelve el tamao del mensaje recibido. */
return msgsize;
}
/*
Funcin net_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void net_notify(void (*func)(net_msgid, unsigned char, void *, short int))
{
/* Define la funcin manejadora de mensajes recibidos. */
reset_watchdog();
__net_recfun__ = func;
/* Invoca a la funcin manejadora de mensajes si hay un mensaje a la
espera de ser recibido. */
if (!net_poll()) return;
__net_recfun__(__net_msg_id__, __net_msg_protocol__, __net_msg_buffer__,
__net_msg_size__);
}

FernandoArielBeunza79156

629

Tesis de Grado en Ingeniera Informtica


/*
Funcin net_poll:
Verifica la llegada de un nuevo mensaje.
*/
int net_poll(void)
{
reset_watchdog();
return (__net_msg_size__ != 0);
}
/*
Funcin net_addaddr:
Agrega una nueva direccin de nodo.
*/
int net_addaddr(net_nodeid nodeid)
{
/* Variables. */
unsigned char iface;

/* Identificador de interface. */

/* Asigna el identificador de nodo. */


if (!nodeid) return 0;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
if (!dl_addlogaddress(iface, NET_PROTID, (dl_logaddr) nodeid))
{
while(1)
{
dl_dellogaddress(iface, NET_PROTID, (dl_logaddr) nodeid);
if (!iface) return 0;
iface --;
}
}
}
return 1;
}
/*
Funcin net_deladdr:
Elimina una direccin de nodo existente.
*/
int net_deladdr(net_nodeid nodeid)
{
/* Variables. */
unsigned char iface;

/* Identificador de interface. */

/* Asigna el identificador de nodo. */


if (!nodeid) return 0;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
if (!dl_dellogaddress(iface, NET_PROTID, (dl_logaddr) nodeid)) break;
}
return 1;
}
/*
Funcin net_addmsgid:
Agrega un nuevo identificador de mensaje.
*/
int net_addmsgid(net_msgid msgid)
{
/* Variables. */
int result;
unsigned char iface;

/* Resultado. */
/* Identificador de interface. */

/* Agrega el nuevo identificador de mensaje a cada una de las


interfaces. */
result = 0;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)

630

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
/* Verifica que la ruta se encuentre definida. */
reset_watchdog();
if (__net_interfacetable__[iface].hd < 0) continue;
/* Agrega el nuevo identificador de mensaje a la tabla de filtrado. */
result = 1;
__net_interfacetable__[iface].msgfilter[msgid >> 3] |=
(1 << (msgid & 0x07));
}
return result;
}
/*
Funcin net_delmsgid:
Elimina un identificador de mensaje.
*/
int net_delmsgid(net_msgid msgid)
{
/* Variables. */
int result;
unsigned char iface;

/* Resultado. */
/* Identificador de interface. */

/* Agrega el nuevo identificador de mensaje a cada una de las


interfaces. */
result = 0;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
/* Verifica que la ruta se encuentre definida. */
reset_watchdog();
if (__net_interfacetable__[iface].hd < 0) continue;
/* Elimina el identificador de mensaje a la tabla de filtrado. */
result = 1;
__net_interfacetable__[iface].msgfilter[msgid >> 3] &=
(0xff ^ (1 << (msgid & 0x07)));
}
return result;
}
/*
Funcin net_status:
Devuelve el estado del dispositivo.
*/
int net_status(void)
{
/* Variables. */
unsigned char iface;

/* Identificador de interface. */

/* Verifica el estado de cada interfaz fsica. */


for(iface = 0; iface < NET_PHYINTERFACES; iface++)
if (dl_status(iface)) return 1;
return 0;
}
/*
Funcin net_getpayloadsize:
Devuelve la cantidad mxima de bytes que debe contener un mensaje para
poder ser enviado por cualquier interfaz.
*/
short int net_getpayloadsize(void)
{
/* Variables. */
short int payload;
unsigned char iface;

/* Capacidad mxima del mensaje. */


/* Identificador de interface. */

/* Obtiene la interfaz con la menor capacidad mxima de bytes que puede


contener un mensaje. */

FernandoArielBeunza79156

631

Tesis de Grado en Ingeniera Informtica


payload = NET_PAYLOADSIZE;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
{
if (payload > dl_getpayloadsize(iface))
payload = dl_getpayloadsize(iface);
}
return payload - NET_HEADERSIZE - NET_FCSSIZE;
}

/* Implementacin de funciones privadas. */


/*
Funcin __net_procmsg__:
Procesa un mensaje recibido por medio de la capa de enlace.
*/
static void __net_procmsg__(dl_addr addr, void *msg, short int msgsize)
__reentrant
{
/* Variables. */
short int size;
/* Tamao del mensaje recibido. */
unsigned char iface;
/* Identificador de interface. */
unsigned char msgid;
/* Identificador de mensaje. */
unsigned char filter;
/* Filto de mensajes. */
unsigned char version;
/* Versin del protocolo de red. */
unsigned char protocol;
/* Protocolo del mensaje. */
unsigned char *rmsg;
/* Puntero al mensaje recibido. */
__net_header__ *net_header;
/* Encabezado del mensaje. */

/* Inicia la carga del encabezado del mensaje. */


reset_watchdog();
rmsg = (unsigned char *) msg;
net_header = (__net_header__ *) msg;
/* Verifica la versin del protocolo de red del mensaje recibido */
version = net_header->version;
if (version > NET_VERSION) return;
/* Obtiene la cantidad de bytes que contiene el fragmento. */
msgsize -= (NET_HEADERSIZE + NET_FCSSIZE);
/* Verifica la validez del mensaje recibido. */
reset_watchdog();
if (getfcs(rmsg, NET_HEADERSIZE + msgsize) !=
usb2l(*((unsigned short int *) (rmsg + NET_HEADERSIZE + msgsize))))
return;
/* Carga el resto del encabezado del mensaje. */
msgid = net_header->msgid;
protocol = net_header->protocol;
size = (short int) usb2l(net_header->size);
/* Aplica el filtro de mensajes. */
filter = 0;
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
filter |= __net_interfacetable__[iface].msgfilter[msgid >> 3];
if (!(filter & (1 << (msgid & 0x07)))) return;
/* Verifica que el buffer no se encuentre lleno. */
if (__net_msg_size__) return;
/* Invoca a la funcin manejadora de mensajes recibidos registrada. */
reset_watchdog();
rmsg += NET_HEADERSIZE;
if (__net_recfun__)
{
__net_recfun__(msgid, protocol, rmsg, size);
reset_watchdog();
return;
}

632

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Almacena el mensaje recibido. */
__net_msg_id__ = msgid;
__net_msg_size__ = size;
__net_msg_protocol__ = protocol;
memcpy1(__net_msg_buffer__, rmsg, __net_msg_size__);
addr[0] = 0x00;
/* Desactiva los manejadores de mensajes recibidos por la capa de
enlace. */
for(iface = 0; iface < NET_PHYINTERFACES; iface++)
dl_notify(__net_interfacetable__[iface].hd, NULL);
}
/*
Funcin __net_send__:
Enva un mensaje por medio de la capa de red.
*/
static short int __net_send__(unsigned char iface, dl_addr addr,
net_msgid msgid, unsigned char prio,
unsigned char prot, short int msgsize,
const void *msg)
{
/* Variables. */
short int size;
/* Cantidad de bytes a enviar. */
__net_header__ *net_header;
/* Encabezado del mensaje. */
unsigned char buffer[NET_HEADERSIZE +
NET_PAYLOADSIZE + NET_FCSSIZE];
/* Buffer para armado de
mensaje. */

/* Carga el encabezado del mensaje. */


reset_watchdog();
net_header = (__net_header__ *) buffer;
net_header->version = NET_VERSION;
net_header->msgid = msgid;
net_header->protocol = prot;
net_header->size = usl2b((unsigned short int) msgsize);
/* Carga los datos del mensaje. */
memcpy1(buffer + NET_HEADERSIZE, msg, msgsize);
/* Carga la suma de verificacin. */
reset_watchdog();
*((unsigned short int *) (buffer + NET_HEADERSIZE + msgsize)) =
usl2b(getfcs(buffer, NET_HEADERSIZE + msgsize));
/* Enva el mensaje. */
size = NET_HEADERSIZE + msgsize + NET_FCSSIZE;
if (dl_send(__net_interfacetable__[iface].hd, addr, prio, buffer,
size) == size)
return msgsize;
return 0;
}

C.5.18. Archivo tp.h


/*
tp.h:
Declaracin de funciones referentes a la capa de transporte.
*/

#if !defined(__TP_H__)
#define __TP_H__

/* Archivos includos necesarios. */

FernandoArielBeunza79156

633

Tesis de Grado en Ingeniera Informtica


#include "config.h"
#include "net.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char tp_grpid;
/* Encabezado del mensaje. */
typedef struct
{
unsigned char version;
char sequence;

/* Versin del protocolo. */


/* Nmero de secuencia del
mensaje. */

} __tp_header__;

/* Definicin de constantes. */
#define TP_HEADERSIZE
#define TP_PAYLOADSIZE

sizeof(__tp_header__)
(NET_PAYLOADSIZE - TP_HEADERSIZE)

/* Definicin de funciones pblicas. */


/*
Funcin tp_init:
Inicializa los recursos utilizados por la capa de transporte.
*/
void tp_init(void);
/*
Funcin tp_release:
Libera los recursos utilizados por la capa de transporte.
*/
void tp_release(void);
/*
Funcin tp_send:
Enva un mensaje por medio de la capa de transporte.
*/
short int tp_send(tp_grpid, unsigned char, const void *, short int);
/*
Funcin tp_receive:
Recibe un mensaje por medio de la capa de transporte.
*/
short int tp_receive(tp_grpid *, void *, short int);
/*
Funcin tp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void tp_notify(void (*func)(tp_grpid, void *, short int));
/*
Funcin tp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int tp_poll(void);
/*
Funcin tp_setownergrp:
Establece el nodo como propietario del grupo especificado.
*/
int tp_setownergrp(tp_grpid);
/*
Funcin tp_setmembergrp:
Establece el nodo como miembro del grupo especificado.
*/

634

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int tp_setmembergrp(tp_grpid);
/*
Funcin tp_leavegrp:
Desvincula el nodo del grupo especificado.
*/
int tp_leavegrp(tp_grpid);
/*
Funcin tp_status:
Devuelve el estado del dispositivo.
*/
int tp_status(void);
/*
Funcin tp_getpayloadsize:
Devuelve la cantidad mxima de bytes que debe contener un mensaje para
poder ser enviado por cualquier interfaz.
*/
short int tp_getpayloadsize(void);

#endif

C.5.19. Archivo tp.c


/*
tp.c:
Implementacin de funciones referentes a la capa de transporte.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <string.h>
#include "common.h"
#include "net.h"
#include "tp.h"

/* Definicin de tipos. */
/* Tipo cola de mensajes. */
typedef struct
{
void *next;
tp_grpid grpid;
short int size;
} __tp_msg_fifo__;

/* Puntero al siguiente mensaje. */


/* Identificador de grupo. */
/* Tamao del mensaje. */

/* Variables globales. */
/* Estado del nodo. */
static volatile unsigned char __tp_status__;
/* Tabla de grupos del cual el nodo es propietario. */
static volatile unsigned char __tp_ownergrptable__[32];
/* Buffer de recepcin de mensajes. */
static volatile unsigned char __tp_msg_buffer__[TP_BUFFERSIZE];
/* Puntero al mensaje a despachar. */
static volatile __tp_msg_fifo__ *__tp_msg__;
/* Tabla de nmeros de secuencia. */
static volatile char __tp_sectable__[256];

FernandoArielBeunza79156

635

Tesis de Grado en Ingeniera Informtica


/* Funcin manejadora de mensajes recibidos. */
static void (*__tp_recfun__)(tp_grpid, void *, short int) __reentrant;

/* Definicin de funciones privadas. */


static void __tp_procmsg__(net_msgid, unsigned char, void *, short int)
__reentrant;
static short int __tp_send__(net_nodeid, net_msgid, unsigned char, char,
short int, const void *);

/* Implementacin de funciones pblicas. */


/*
Funcin tp_init:
Inicializa los recursos utilizados por la capa de transporte.
*/
void tp_init(void)
{
/* Variables. */
unsigned char i;

/* Contador. */

/* Inicializa los recursos utilizados por la capa de red. */


net_init();
/* Define un manejador de mensajes recibidos por la capa de red. */
net_notify(__tp_procmsg__);
/* Inicializa la tabla de grupos. */
for(i = 0; i < 32; i++)
{
reset_watchdog();
__tp_ownergrptable__[i] = 0x00;
}
/* Inicializa los buffers de mensajes. */
__tp_msg__ = NULL;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__tp_recfun__ = NULL;
/* Inicializa el nodo como operativo. */
__tp_status__ = 1;
}
/*
Funcin tp_release:
Libera los recursos utilizados por la capa de transporte.
*/
void tp_release(void)
{
net_notify(NULL);
net_release();
}
/*
Funcin tp_send:
Enva un mensaje por medio de la capa de transporte.
*/
short int tp_send(tp_grpid grpid, unsigned char nosec, const void *msg,
short int msgsize)
{
/* Verifica que el tamao del mensaje no supere el mximo permitido. */
reset_watchdog();
if (msgsize > tp_getpayloadsize()) return 0;
/* Verifica si el nodo es propietario del grupo. */
if (!(__tp_ownergrptable__[grpid >> 3] & (1 << (grpid & 0x07))))
return 0;

636

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Enva el mensaje. */
if (nosec) return __tp_send__(0, grpid, TP_MAXPRIOMSG, -1, msgsize, msg);
if (__tp_send__(0, grpid, TP_MINPRIOMSG, __tp_sectable__[grpid], msgsize,
msg) == msgsize)
{
__tp_sectable__[grpid] ++;
if (__tp_sectable__[grpid] < 0) __tp_sectable__[grpid] = 0;
return msgsize;
}
return 0;
}
/*
Funcin tp_receive:
Recibe un mensaje por medio de la capa de transporte.
*/
short int tp_receive(tp_grpid *grpid, void *msg, short int msgsize)
{
/* Espera la llegada de un mensaje. */
while(!tp_poll());
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
if (grpid) *grpid = __tp_msg__->grpid;
if (msg)
memcpy2(msg, msgsize, __tp_msg__ + sizeof(__tp_msg_fifo__),
__tp_msg__->size);
if (msgsize > __tp_msg__->size) msgsize = __tp_msg__->size;
__tp_msg__ = __tp_msg__->next;
/* Activa el manejador de mensajes recibidos por la capa de red. */
net_notify(__tp_procmsg__);
/* Devuelve el tamao del mensaje recibido. */
return msgsize;
}
/*
Funcin tp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void tp_notify(void (*func)(tp_grpid, void *, short int))
{
/* Define la funcin manejadora de mensajes recibidos. */
reset_watchdog();
__tp_recfun__ = func;
/* Invoca a la funcin manejadora de mensajes si hay un mensaje a la
espera de ser recibido. */
while(tp_poll() && __tp_recfun__)
{
__tp_recfun__(__tp_msg__->grpid, __tp_msg__ + sizeof(__tp_msg_fifo__),
__tp_msg__->size);
__tp_msg__ = __tp_msg__->next;
}
}
/*
Funcin tp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int tp_poll(void)
{
reset_watchdog();
return (__tp_msg__ != NULL);
}
/*
Funcin tp_setownergrp:
Establece el nodo como propietario del grupo especificado.
*/
int tp_setownergrp(tp_grpid grpid)

FernandoArielBeunza79156

637

Tesis de Grado en Ingeniera Informtica


{
/* Agrega la direccin. */
if (!net_addaddr(((net_nodeid) grpid) | 0x0100)) return 0;
/* Agrega el identificador de mensaje. */
if (!net_addmsgid((net_msgid) grpid))
net_deladdr(((net_nodeid) grpid) | 0x0100);
/* Agrega el grupo a la tabla. */
__tp_ownergrptable__[grpid >> 3] |= (1 << (grpid & 0x07));
/* Inicializa el nmero de secuencia de mensaje. */
__tp_sectable__[grpid] = 0;
return 1;
}
/*
Funcin tp_setmembergrp:
Establece el nodo como miembro del grupo especificado.
*/
int tp_setmembergrp(tp_grpid grpid)
{
/* Verifica que el nodo no sea propietario y miembro simultneamente. */
if (__tp_ownergrptable__[grpid >> 3] & (1 << (grpid & 0x07)))
return 0;
/* Inicializa el nmero de secuencia de mensaje. */
__tp_sectable__[grpid] = -1;
/* Agrega el identificador de mensaje. */
return net_addmsgid((net_msgid) grpid);
}
/*
Funcin tp_leavegrp:
Desvincula el nodo del grupo especificado.
*/
int tp_leavegrp(tp_grpid grpid)
{
/* Elimina la direccin. */
net_deladdr(((net_nodeid) grpid) | 0x0100);
/* Elimina el identificador de mensaje. */
if (!net_delmsgid((net_msgid) grpid)) return 0;
/* Elimina el grupo a la tabla. */
__tp_ownergrptable__[grpid >> 3] &= (0xff ^ (1 << (grpid & 0x07)));
return 1;
}
/*
Funcin tp_status:
Devuelve el estado del dispositivo.
*/
int tp_status(void)
{
reset_watchdog();
if (!__tp_status__) return 0;
return net_status();
}
/*
Funcin tp_getpayloadsize:
Devuelve la cantidad mxima de bytes que debe contener un mensaje para
poder ser enviado por cualquier interfaz.
*/
short int tp_getpayloadsize(void)
{
return net_getpayloadsize() - TP_HEADERSIZE;
}

638

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

/* Implementacin de funciones privadas. */


/*
Funcin __tp_procmsg__:
Procesa un mensaje recibido por medio de la capa de red.
*/
static void __tp_procmsg__(net_msgid msgid, unsigned char prot, void *msg,
short int msgsize) __reentrant
{
/* Variables. */
char sequence;
/* Nmero de secuencia del
mensaje. */
unsigned char *rmsg;
/* Puntero al mensaje recibido. */
__tp_header__ *tp_header;
/* Encabezado del mensaje. */
__tp_msg_fifo__ *ptrmsg;
/* Puntero al mensaje. */

/* Inicia la carga del encabezado del mensaje. */


reset_watchdog();
rmsg = (unsigned char *) msg;
tp_header = (__tp_header__ *) msg;
/* Verifica el identificador de protocolo. */
if (prot > TP_PROTID) return;
/* Verifica la versin del protocolo de red del mensaje recibido */
if (tp_header->version > TP_VERSION) return;
/* Obtiene la cantidad de bytes que contiene el mensage recibido. */
msgsize -= TP_HEADERSIZE;
if (msgsize > TP_PAYLOADSIZE) return;
/* Carga el resto del encabezado del mensaje. */
sequence = tp_header->sequence;
/* Verifica la validez del nmero de sencuencia del mensaje recibido. */
if ((sequence >= 0) && (__tp_sectable__[msgid] >= 0))
{
/* Si el nmero de secuencia recibido supera al ltimo recibido
significa que se perdieron mensajes. */
if (sequence > (__tp_sectable__[msgid] + 1))
{
__tp_status__ = 0;
net_notify(NULL);
return;
}
/* Si el nmero de secuencia recibido es menor al ltimo recibido
significa que el mensaje ya fue recibido con anterioridad. */
if (sequence <= __tp_sectable__[msgid]) return;
}
/* Busca un lugar en el buffer para almacenar el mensaje recibido. */
if (__tp_msg__)
{
ptrmsg = __tp_msg__;
while(ptrmsg->next)
{
reset_watchdog();
ptrmsg = ptrmsg->next;
}
ptrmsg->next = ((unsigned char *) ptrmsg) + sizeof(__tp_msg_fifo__) +
ptrmsg->size;
if ((((unsigned char *) ptrmsg->next) + sizeof(__tp_msg_fifo__) +
msgsize) >= (__tp_msg_buffer__ + TP_BUFFERSIZE))
{
ptrmsg->next = __tp_msg_buffer__;
if ((((unsigned char *) ptrmsg->next) + sizeof(__tp_msg_fifo__) +
msgsize) >= ((unsigned char *) __tp_msg__))

FernandoArielBeunza79156

639

Tesis de Grado en Ingeniera Informtica


{
ptrmsg->next = NULL;
return;
}
}
ptrmsg = ptrmsg->next;
}
else
{
__tp_msg__ = (__tp_msg_fifo__ *) __tp_msg_buffer__;
ptrmsg = __tp_msg__;
}
/* Almacena el mensaje recibido. */
rmsg += TP_HEADERSIZE;
ptrmsg->next = NULL;
ptrmsg->grpid = (tp_grpid) msgid;
ptrmsg->size = msgsize;
memcpy1(ptrmsg + sizeof(__tp_msg_fifo__), rmsg, msgsize);
if (sequence >= 0) __tp_sectable__[msgid] = sequence;
/* Invoca a la funcin manejadora de mensajes recibidos registrada. */
reset_watchdog();
if (__tp_recfun__)
{
__tp_recfun__(__tp_msg__->grpid, ptrmsg + sizeof(__tp_msg_fifo__),
__tp_msg__->size);
reset_watchdog();
__tp_msg__ = __tp_msg__->next;
return;
}
}
/*
Funcin __tp_send__:
Enva un mensaje por medio de la capa de transporte.
*/
static short int __tp_send__(net_nodeid nodeid, net_msgid msgid,
unsigned char prio, char sec,
short int msgsize, const void *msg)
{
/* Variables. */
short int size;
/* Cantidad de bytes a enviar. */
__tp_header__ *tp_header;
/* Encabezado del mensaje. */
unsigned char buffer[TP_HEADERSIZE +
TP_PAYLOADSIZE];
/* Buffer para armado de
mensaje. */

/* Carga el encabezado del mensaje. */


reset_watchdog();
tp_header = (__tp_header__ *) buffer;
tp_header->version = TP_VERSION;
tp_header->sequence = sec;
/* Carga los datos del mensaje. */
memcpy1(buffer + TP_HEADERSIZE, msg, msgsize);
/* Enva el mensaje. */
size = TP_HEADERSIZE + msgsize;
if (net_send(nodeid, msgid, prio, TP_PROTID, buffer, size) == size)
return msgsize;
return 0;
}

C.5.20. Archivo sp.h


/*

640

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


sp.h:
Declaracin de funciones referentes a la capa de sesin.
*/

#if !defined(__SP_H__)
#define __SP_H__

/* Archivos includos necesarios. */


#include "config.h"
#include "tp.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char sp_grpid;
/* Encabezado del mensaje. */
typedef struct
{
unsigned char version;
} __sp_header__;

/* Definicin de constantes. */
#define SP_HEADERSIZE
#define SP_PAYLOADSIZE

/* Versin del protocolo. */

sizeof(__sp_header__)
(TP_PAYLOADSIZE - SP_HEADERSIZE)

/* Definicin de funciones pblicas. */


/*
Funcin sp_init:
Inicializa los recursos utilizados por la capa de sesin.
*/
void sp_init(void);
/*
Funcin sp_release:
Libera los recursos utilizados por la capa de sesin.
*/
void sp_release(void);
/*
Funcin sp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int sp_publish(sp_grpid);
/*
Funcin sp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int sp_subscribe(sp_grpid);
/*
Funcin sp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int sp_leave(sp_grpid);
/*
Funcin sp_send:
Enva un mensaje por medio de la capa de sesin.
*/
short int sp_send(sp_grpid, unsigned char, const void *, short int);
/*
Funcin sp_receive:

FernandoArielBeunza79156

641

Tesis de Grado en Ingeniera Informtica


Recibe un mensaje por medio de la capa de sesin.
*/
short int sp_receive(sp_grpid *, void *, short int);
/*
Funcin sp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void sp_notify(void (*func)(sp_grpid, void *, short int));
/*
Funcin sp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int sp_poll(void);
/*
Funcin sp_status:
Devuelve el estado del dispositivo.
*/
int sp_status(void);
/*
Funcin sp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje.
*/
short int sp_getpayloadsize(void);

#endif

C.5.21. Archivo sp.c


/*
sp.c:
Implementacin de funciones referentes a la capa de sesin.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "common.h"
#include <string.h>
#include "tp.h"
#include "sp.h"

/* Variables globales. */
/* Tamao del mensaje almacenado en el buffer. */
static volatile short int __sp_msg_size__;
/* Identificador de grupo al que pertenece el mensaje recibido. */
static sp_grpid __sp_msg_grpid__;
/* Buffer de recepcin de mensajes. */
static volatile unsigned char __sp_msg_buffer__[SP_PAYLOADSIZE];
/* Funcin manejadora de mensajes recibidos. */
static void (*__sp_recfun__)(sp_grpid, void *, short int) __reentrant;

/* Definicin de funciones privadas. */


static void __sp_procmsg__(tp_grpid, void *, short int) __reentrant;

/* Implementacin de funciones pblicas. */

642

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin sp_init:
Inicializa los recursos utilizados por la capa de sesin.
*/
void sp_init(void)
{
/* Inicializa los recursos utilizados por la capa de transporte. */
tp_init();
/* Define un manejador de mensajes recibidos por la capa de transporte. */
tp_notify(__sp_procmsg__);
/* Inicializa los buffers de mensajes. */
__sp_msg_size__ = 0;
/* Inicializa la funcin manejadora de mensajes recibidos. */
__sp_recfun__ = NULL;
}
/*
Funcin sp_release:
Libera los recursos utilizados por la capa de sesin.
*/
void sp_release(void)
{
tp_notify(NULL);
tp_release();
}
/*
Funcin sp_publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
int sp_publish(sp_grpid grpid)
{
return tp_setownergrp(grpid);
}
/*
Funcin sp_subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
int sp_subscribe(sp_grpid grpid)
{
return tp_setmembergrp(grpid);
}
/*
Funcin sp_leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int sp_leave(sp_grpid grpid)
{
return tp_leavegrp(grpid);
}
/*
Funcin sp_send:
Enva un mensaje por medio de la capa de sesin.
*/
short int sp_send(sp_grpid grpid, unsigned char nosec, const void *msg,
short int msgsize)
{
/* Variables. */
short int size;
/* Cantidad de bytes a enviar. */
__sp_header__ *sp_header;
/* Encabezado del mensaje. */
unsigned char buffer[SP_HEADERSIZE +
SP_PAYLOADSIZE];
/* Buffer para armado de
mensaje. */

FernandoArielBeunza79156

643

Tesis de Grado en Ingeniera Informtica


/* Verifica que el tamao del mensaje no supere el mximo permitido. */
reset_watchdog();
if (msgsize > sp_getpayloadsize()) return 0;
/* Carga el encabezado del mensaje. */
sp_header = (__sp_header__ *) buffer;
sp_header->version = SP_VERSION;
/* Carga los datos del mensaje. */
memcpy1(buffer + SP_HEADERSIZE, msg, msgsize);
/* Enva el mensaje. */
size = SP_HEADERSIZE + msgsize;
if (tp_send(grpid, nosec, buffer, size) == size) return msgsize;
return 0;
}
/*
Funcin sp_receive:
Recibe un mensaje por medio de la capa de sesin.
*/
short int sp_receive(sp_grpid *grpid, void *msg, short int msgsize)
{
/* Espera la llegada de un mensaje. */
while(!sp_poll());
/* Devuelve el mensaje almacenado en el buffer de recepcin. */
if (grpid) *grpid = __sp_msg_grpid__;
if (msg) memcpy2(msg, msgsize, __sp_msg_buffer__, __sp_msg_size__);
if (msgsize > __sp_msg_size__) msgsize = __sp_msg_size__;
__sp_msg_size__ = 0;
/* Activa el manejador de mensajes recibidos por la capa de transporte. */
tp_notify(__sp_procmsg__);
/* Devuelve el tamao del mensaje recibido. */
return msgsize;
}
/*
Funcin sp_notify:
Define una funcin manejadora de mensajes recibidos.
*/
void sp_notify(void (*func)(sp_grpid, void *, short int))
{
/* Define la funcin manejadora de mensajes recibidos. */
reset_watchdog();
__sp_recfun__ = func;
/* Invoca a la funcin manejadora de mensajes si hay un mensaje a la
espera de ser recibido. */
if (!sp_poll()) return;
__sp_recfun__(__sp_msg_grpid__, __sp_msg_buffer__, __sp_msg_size__);
}
/*
Funcin sp_poll:
Verifica la llegada de un nuevo mensaje.
*/
int sp_poll(void)
{
reset_watchdog();
return (__sp_msg_size__ != 0);
}
/*
Funcin sp_status:
Devuelve el estado del dispositivo.
*/
int sp_status(void)
{

644

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


return tp_status();
}
/*
Funcin sp_getpayloadsize:
Devuelve la cantidad mxima de bytes que puede contener un mensaje.
*/
short int sp_getpayloadsize(void)
{
return tp_getpayloadsize() - SP_HEADERSIZE;
}

/* Implementacin de funciones privadas. */


/*
Funcin __sp_procmsg__:
Procesa un mensaje recibido por medio de la capa de transporte.
*/
static void __sp_procmsg__(tp_grpid grpid, void *msg, short int msgsize)
__reentrant
{
/* Variables. */
unsigned char *rmsg;
/* Puntero al mensaje recibido. */
__sp_header__ *sp_header;
/* Encabezado del mensaje. */

/* Inicia la carga del encabezado del mensaje. */


reset_watchdog();
rmsg = (unsigned char *) msg;
sp_header = (__sp_header__ *) msg;
/* Verifica la versin del protocolo de red del mensaje recibido */
if (sp_header->version > SP_VERSION) return;
/* Obtiene la cantidad de bytes que contiene el mensage recibido. */
msgsize -= SP_HEADERSIZE;
if (msgsize > SP_PAYLOADSIZE) return;
/* Verifica que el buffer no se encuentre lleno. */
if (__sp_msg_size__) return;
/* Invoca a la funcin manejadora de mensajes recibidos registrada. */
reset_watchdog();
rmsg += SP_HEADERSIZE;
if (__sp_recfun__)
{
__sp_recfun__(grpid, rmsg, msgsize);
reset_watchdog();
return;
}
/* Almacena el mensaje recibido. */
__sp_msg_size__ = msgsize;
__sp_msg_grpid__ = (sp_grpid) grpid;
memcpy1(__sp_msg_buffer__, rmsg, __sp_msg_size__);
/* Desactiva el manejador de mensajes recibidos por la capa de
transporte. */
tp_notify(NULL);
}

C.5.22. Archivo modem.c


/*
modem.c:
Firmware del modem PLC.
*/

FernandoArielBeunza79156

645

Tesis de Grado en Ingeniera Informtica

/* Archivos includos necesarios. */


#include <stdio.h>
#include <string.h>
#include <at89x52.h>
#include "serial.h"
#include "common.h"
#include "phy.h"
#include "dl.h"
#include "sp.h"

/* Declaracin de funciones privadas. */


static void modem_phymode(void);
static void modem_dlmode(void);
static void modem_spmode(void);
static void modem_outputbyte(unsigned char);
static void modem_outputint(short int);
static void modem_outputstream(const void *, short int);
static void modem_inputstream(void *, short int);

/*
Funcin main:
Funcin principal.
*/
void main(void)
{
/* Variables. */
char line[MODPLC_CMDLINESIZE];

/* Lnea de comandos. */

/* Inicializacin del microcontrolador. */


initports();
inituart(0xff);
init_watchdog(1);
/* Recibe el modo de comunicacin con el modem. */
printf("\
Modem PLC test\r\n\n\
0 = reset\r\n\
1 = physical layer\r\n\
2 = datalink layer\r\n\
3 = session layer\r\n\n\
");
while(1)
{
/* Recibe opcin. */
reset_watchdog();
putchar(MODPLC_LAYPROMPT);
gets(line);
if (strceq(line, "")) continue;
/* Verifica si se solicita la reinicializacin del dispositivo. */
if (strceq(line, MODPLC_NORMRESET)) break;
/* Verifica si se solicita la inicializacin de la capa fsica. */
if (strceq(line, MODPLC_PHYSICALLAYER))
{
printf("\r\n");
modem_phymode();
break;
}
/* Verifica si se solicita la inicializacin de la capa de enlace. */
if (strceq(line, MODPLC_DATALINKLAYER))
{
printf("\r\n");
modem_dlmode();
break;

646

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Verifica si se solicita la inicializacin de la capa de sesin. */
if (strceq(line, MODPLC_SESSIONLAYER))
{
printf("\r\n");
modem_spmode();
break;
}
}
reset();
}

/* Implementacin de funciones privadas. */


/*
Funcin modem_phymode:
Recibe y procesa comandos de la capa fsica.
*/
static void modem_phymode(void)
{
/* Variables. */
short int size;
long int waittime;
unsigned char sig;
unsigned char level;
unsigned char iface;
unsigned char *ptrval;
char line[MODPLC_CMDLINESIZE];
unsigned char str[PHY_PAYLOADSIZE];

/*
/*
/*
/*
/*

Tamao del mensaje. */


Tiempo de espera. */
Tipo de seal. */
Nivel de seal. */
Identificador de interfaz
fsica. */
/* Puntero al tiempo de espera. */
/* Lnea de comandos. */
/* Mensaje de prueba. */

/* Inicializa los recursos utilizados por la capa fsica. */


phy_init();
/* Recibe y procesa los comandos recibidos. */
while(1)
{
/* Recibe comandos. */
reset_watchdog();
putchar(MODPLC_NORMPROMPT);
gets(line);
if (strceq(line, "")) continue;
/* Verifica si el comando solicita la operacin de reinicio del
dispositivo. */
else if (strceq(line, MODPLCPHY_RESET)) break;
/* Verifica si el comando solicita la operacin de envo de trama. */
else if (strceq(line, MODPLCPHY_SNDFRAME))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
modem_inputstream(str, size);
if (iface == 0)
modem_outputint(phy_sndframe(str, size));
else
modem_outputint(0);
}
/* Verifica si el comando solicita la operacin de captura de trama. */
else if (strceq(line, MODPLCPHY_CAPFRAME))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
if (iface == 0)
modem_outputbyte(phy_capframe(size) != 0);

FernandoArielBeunza79156

647

Tesis de Grado en Ingeniera Informtica


else
modem_outputbyte(0);
}
/* Verifica si el comando solicita la operacin de obtencin de una
trama capturada previamente. */
else if (strceq(line, MODPLCPHY_GETFRAME))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
size = phy_getframe(str, size);
if (iface == 0)
{
modem_outputint(size);
modem_outputstream(str, size);
}
else
modem_outputint(0);
}
/* Verifica si el comando solicita la operacin de notificacin de
recepcin de trama. */
else if (strceq(line, MODPLCPHY_POLL))
{
modem_inputstream(&iface, sizeof(iface));
if (iface == 0)
modem_outputbyte(phy_poll() != 0);
else
modem_outputbyte(0);
}
/* Verifica si el comando solicita la operacin de reenvio de trama. */
else if (strceq(line, MODPLCPHY_RSDFRAME))
{
modem_inputstream(&iface, sizeof(iface));
if (iface == 0)
modem_outputbyte(phy_rsdframe() != 0);
else
modem_outputbyte(0);
}
/* Verifica si el comando solicita la operacin de limpieza del buffer
de captura de tramas. */
else if (strceq(line, MODPLCPHY_CLRBUFFER))
{
modem_inputstream(&iface, sizeof(iface));
if (iface == 0)
modem_outputbyte(phy_clrbuffer() != 0);
else
modem_outputbyte(0);
}
/* Verifica si el comando solicita la operacin de sensado del estado
del canal de comunicacin. */
else if (strceq(line, MODPLCPHY_SENSECHANNEL))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&level, sizeof(level));
modem_inputstream(str, sizeof(unsigned long int));
ptrval = (unsigned char *) &waittime;
ptrval[0] = str[3];
ptrval[1] = str[2];
ptrval[2] = str[1];
ptrval[3] = str[0];
if (iface == 0)
modem_outputbyte(phy_sensechannel(level, waittime));
else
modem_outputbyte(0);
}

648

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Verifica si el comando solicita la operacin de generacin de una
seal de prueba. */
else if (strceq(line, MODPLCPHY_GENSIGNAL))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&sig, sizeof(sig));
if (iface == 0)
{
if (sig == MODPLCPHY_NOISESIGNAL)
modem_outputbyte(phy_gennoisesignal() != 0);
else if (sig == MODPLCPHY_TESTSIGNAL1)
modem_outputbyte(phy_tstsignal1() != 0);
else if (sig == MODPLCPHY_TESTSIGNAL2)
modem_outputbyte(phy_tstsignal2() != 0);
}
else
modem_outputbyte(0);
}
/* Verifica si el comando solicita la operacin de prueba de
recepcin. */
else if (strceq(line, MODPLCPHY_TSTRECEIVE))
{
modem_inputstream(&iface, sizeof(iface));
if (iface == 0)
modem_outputbyte(phy_tstreceive() != 0);
else
modem_outputbyte(0);
}

/* Verifica si el comando solicita la operacin de solicitud de


tamao mximo de trama. */
else if (strceq(line, MODPLCPHY_GETPAYLOADSIZE))
{
modem_inputstream(&iface, sizeof(iface));
if (iface == 0)
modem_outputint(PHY_PAYLOADSIZE);
else
modem_outputint(0);
}
/* Comando desconocido. */
else
continue;
printf("\r\n");
}
/* Libera los recursos utilizados por la capa fsica. */
phy_release();
}
/*
Funcin modem_dlmode:
Recibe y procesa comandos de la capa de enlace.
*/
static void modem_dlmode(void)
{
/* Variables. */
short int hd;
short int size;
dl_addr dladdr;
dl_logaddr logaddr;
unsigned char prio;
unsigned char prot;
unsigned char iface;
unsigned char *ptrval;
char line[MODPLC_CMDLINESIZE];

FernandoArielBeunza79156

/*
/*
/*
/*
/*
/*
/*

Manejador de conexin. */
Tamao del mensaje. */
Direccin DL. */
Direccin lgica. */
Prioridad del mensaje. */
Identificador de protocolo. */
Identificador de interfaz
fsica. */
/* Puntero a la direccin
lgica. */
/* Lnea de comandos. */

649

Tesis de Grado en Ingeniera Informtica


unsigned char str[DL_PAYLOADSIZE];

/* Mensaje de prueba. */

/* Inicializa los recursos utilizados por la capa de enlace. */


for(iface = 0; iface < NET_PHYINTERFACES; iface++) dl_init(0);
/* Recibe y procesa los comandos recibidos. */
while(1)
{
/* Verifica el estado del dispositivo. */
if (!dl_status(0)) break;
/* Recibe comandos. */
reset_watchdog();
putchar(MODPLC_NORMPROMPT);
gets(line);
if (strceq(line, "")) continue;
/* Verifica si el comando solicita la operacin de reinicio del
dispositivo. */
else if (strceq(line, MODPLCDL_RESET)) break;
/* Verifica si el comando solicita la operacin de apertura de
conexin. */
else if (strceq(line, MODPLCDL_OPEN))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&prot, sizeof(prot));
modem_outputint(dl_open(iface, prot));
}
/* Verifica si el comando solicita la operacin de cierre de
conexin. */
else if (strceq(line, MODPLCDL_CLOSE))
{
modem_inputstream(&hd, sizeof(hd));
hd = usl2b((unsigned short int) hd);
modem_outputbyte(dl_close(hd) != 0);
}
/* Verifica si el comando solicita la operacin de envo de mensaje. */
else if (strceq(line, MODPLCDL_SEND))
{
modem_inputstream(&hd, sizeof(hd));
hd = usl2b((unsigned short int) hd);
modem_inputstream(dladdr, sizeof(dladdr));
modem_inputstream(&prio, sizeof(prio));
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
modem_inputstream(str, size);
modem_outputint(dl_send(hd, dladdr, prio, str, size));
}
/* Verifica si el comando solicita la operacin lectura de mensaje. */
else if (strceq(line, MODPLCDL_RECEIVE))
{
modem_inputstream(&hd, sizeof(hd));
hd = usl2b((unsigned short int) hd);
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
if (dl_poll(hd))
size = dl_receive(hd, dladdr, str, size);
else
size = 0;
modem_outputstream(dladdr, sizeof(dladdr));
modem_outputint(size);
modem_outputstream(str, size);
}
/* Verifica si el comando solicita la operacin de notificacin de
recepcin de mensaje. */

650

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


else if (strceq(line, MODPLCDL_POLL))
{
modem_inputstream(&hd, sizeof(hd));
hd = usl2b((unsigned short int) hd);
modem_outputbyte(dl_poll(hd) != 0);
}
/* Verifica si el comando solicita la operacin de solicitud de
direccin fsica del dispositivo. */
else if (strceq(line, MODPLCDL_GETADDRESS))
{
modem_inputstream(&iface, sizeof(iface));
if (dl_getaddress(iface, dladdr))
modem_outputstream(dladdr, sizeof(dladdr));
}
/* Verifica si el comando solicita la operacin de agregado de una
direccin lgica. */
else if (strceq(line, MODPLCDL_ADDLOGADDRESS))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&prot, sizeof(prot));
modem_inputstream(str, sizeof(logaddr));
ptrval = (unsigned char *) &logaddr;
ptrval[0] = str[3];
ptrval[1] = str[2];
ptrval[2] = str[1];
ptrval[3] = str[0];
modem_outputbyte(dl_addlogaddress(iface, prot, logaddr) != 0);
}
/* Verifica si el comando solicita la operacin de eliminacin de una
direccin lgica. */
else if (strceq(line, MODPLCDL_DELLOGADDRESS))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&prot, sizeof(prot));
modem_inputstream(str, sizeof(logaddr));
ptrval = (unsigned char *) &logaddr;
ptrval[0] = str[3];
ptrval[1] = str[2];
ptrval[2] = str[1];
ptrval[3] = str[0];
modem_outputbyte(dl_dellogaddress(iface, prot, logaddr) != 0);
}
/* Verifica si el comando solicita la operacin de solicitud de
direccin fsica asociada. */
else if (strceq(line, MODPLCDL_GETPHYADDRESS))
{
modem_inputstream(&iface, sizeof(iface));
modem_inputstream(&prot, sizeof(prot));
modem_inputstream(str, sizeof(logaddr));
ptrval = (unsigned char *) &logaddr;
ptrval[0] = str[3];
ptrval[1] = str[2];
ptrval[2] = str[1];
ptrval[3] = str[0];
if (dl_getphyaddress(iface, prot, logaddr, dladdr))
modem_outputstream(dladdr, sizeof(dladdr));
}
/* Verifica si el comando solicita la operacin de solicitud de
tamao mximo de mensaje. */
else if (strceq(line, MODPLCDL_GETPAYLOADSIZE))
{
modem_inputstream(&iface, sizeof(iface));
modem_outputint(dl_getpayloadsize(iface));
}
/* Comando desconocido. */

FernandoArielBeunza79156

651

Tesis de Grado en Ingeniera Informtica


else
continue;
printf("\r\n");
}
/* Libera los recursos utilizados por la capa de enlace. */
for(iface = 0; iface < NET_PHYINTERFACES; iface++) dl_release(iface);
}
/*
Funcin modem_spmode:
Recibe y procesa comandos de la capa de la capa de sesin.
*/
static void modem_spmode(void)
{
/* Variables. */
unsigned char nosec;
short int size;
sp_grpid grpid;
char line[MODPLC_CMDLINESIZE];
unsigned char str[SP_PAYLOADSIZE];

/* Indicador de mensaje fuera de


secuencia. */
/* Tamao del mensaje. */
/* Identificador de grupo. */
/* Lnea de comandos. */
/* Mensaje de prueba. */

/* Inicializa los recursos utilizados por la capa de sesin. */


sp_init();
/* Recibe y procesa los comandos recibidos. */
while(1)
{
/* Verifica el estado del dispositivo. */
if (!sp_status()) break;
/* Recibe comandos. */
reset_watchdog();
putchar(MODPLC_NORMPROMPT);
gets(line);
if (strceq(line, "")) continue;
/* Verifica si el comando solicita la operacin de reinicio del
dispositivo. */
else if (strceq(line, MODPLCSP_RESET)) break;
/* Verifica si el comando solicita la operacin de establece la
propiedad del grupo. */
else if (strceq(line, MODPLCSP_PUBLISH))
{
modem_inputstream(&grpid, sizeof(grpid));
modem_outputbyte(sp_publish(grpid) != 0);
}
/* Verifica si el comando solicita la operacin de suscripcin a un
grupo. */
else if (strceq(line, MODPLCSP_SUBSCRIBE))
{
modem_inputstream(&grpid, sizeof(grpid));
modem_outputbyte(sp_subscribe(grpid) != 0);
}
/* Verifica si el comando solicita la operacin de desvinculacin a un
grupo. */
else if (strceq(line, MODPLCSP_LEAVE))
{
modem_inputstream(&grpid, sizeof(grpid));
modem_outputbyte(sp_leave(grpid) != 0);
}
/* Verifica si el comando solicita la operacin de envo de mensaje. */
else if (strceq(line, MODPLCSP_SEND))
{

652

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


modem_inputstream(&grpid, sizeof(grpid));
modem_inputstream(&nosec, sizeof(nosec));
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
modem_inputstream(str, size);
size = sp_send(grpid, nosec, str, size);
modem_outputint(size);
}
/* Verifica si el comando solicita la operacin lectura de mensaje. */
else if (strceq(line, MODPLCSP_RECEIVE))
{
modem_inputstream(&size, sizeof(size));
size = usl2b((unsigned short int) size);
if (sp_poll())
size = sp_receive(&grpid, str, size);
else
{
size = 0;
grpid = 0;
}
modem_outputbyte((unsigned char) grpid);
modem_outputint(size);
modem_outputstream(str, size);
}
/* Verifica si el comando solicita la operacin de notificacin de
recepcin de mensaje. */
else if (strceq(line, MODPLCSP_POLL))
modem_outputbyte(sp_poll() != 0);
/* Verifica si el comando solicita la operacin de solicitud de
tamao mximo de mensaje. */
else if (strceq(line, MODPLCSP_GETPAYLOADSIZE))
modem_outputint(sp_getpayloadsize());
/* Comando desconocido. */
else
continue;
printf("\r\n");
}
/* Libera los recursos utilizados por la capa de sesin. */
sp_release();
}
/*
Funcin modem_outputbyte:
Enva un byte de datos.
*/
static void modem_outputbyte(unsigned char b)
{
reset_watchdog();
printf("\\%02X\r\n", b);
}
/*
Funcin modem_outputint:
Enva un entero de 16 bits de datos.
*/
static void modem_outputint(short int intval)
{
/* Variables. */
unsigned char *ptr;

/* Puntero a los datos. */

/* Enva los datos. */


reset_watchdog();
ptr = (char *) &intval;
printf("\\%02X\\%02X\r\n", ptr[1], ptr[0]);

FernandoArielBeunza79156

653

Tesis de Grado en Ingeniera Informtica


}
/*
Funcin modem_outputstream:
Enva una trama de datos.
*/
static void modem_outputstream(const void *str, short int size)
{
/* Variables. */
short int i;
/* Contador. */
unsigned char *ptr;
/* Puntero a los datos. */

/* Carga el puntero a los datos a enviar. */


ptr = (unsigned char *) str;
/* Enva los datos. */
reset_watchdog();
for(i = 0; i < size; )
{
reset_watchdog();
if ((*ptr >= 0x20) && (*ptr <= 0x7e) &&
(*ptr != ((unsigned char) '\\')) &&
(*ptr != ((unsigned char) MODPLC_INITPROMPT)) &&
(*ptr != ((unsigned char) MODPLC_LAYPROMPT)) &&
(*ptr != ((unsigned char) MODPLC_NORMPROMPT)) &&
(*ptr != ((unsigned char) MODPLC_PARAMPROMPT)))
putchar(*ptr);
else
printf("\\%02X", *ptr);
ptr ++;
if ((++ i) & 0x000f) continue;
printf("\r\n");
}
reset_watchdog();
if ((i & 0x000f) && (size)) printf("\r\n");
}
/*
Funcin modem_inputstream:
Recibe una trama de datos.
*/
static void modem_inputstream(void *stream, short int size)
{
/* Variables. */
int i;
/* Contador. */
char c;
/* Caracter ledo. */
unsigned char dat;
/* Byte ledo. */
unsigned char *ptrdat;
/* Puntero a los datos. */
unsigned char *ptrline;
/* Puntero a la lnea recibida. */
char line[MODPLC_CMDLINESIZE];
/* Lnea de comandos. */

/* Carga el puntero a los datos a enviar. */


ptrdat = (unsigned char *) stream;
/* Recibe los datos. */
dat = 0;
while(size)
{
/* Lee una lnea. */
putchar(MODPLC_PARAMPROMPT);
gets(line);
/* Procesa la lnea leda. */
ptrline = (unsigned char *) line;
while(*ptrline)
{
/* Verifica si se solicita reiniciar el dispositivo. */
if (*ptrline == ((unsigned char) MODPLC_PARAMRESET))
{

654

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


reset();
return;
}
/* Procesa un caracter de la lnea. */
if (*ptrline != ((unsigned char) '\\'))
dat = *(ptrline ++);
else
{
ptrline ++;
for(i = 0; i < 2; i++)
{
dat <<= 4;
c = *(ptrline ++);
if ((c >= '0') && (c <= '9'))
dat += c - '0';
else if ((c >= 'a') && (c <= 'f'))
dat += c - 'a' + 0x0a;
else if ((c >= 'A') && (c <= 'F'))
dat += c - 'A' + 0x0a;
}
}
/* Almacena y devuelve el byte recibido. */
reset_watchdog();
if (!size) continue;
*(ptrdat ++) = dat;
size --;
}
}
reset_watchdog();
}

C.6. Especificacin del cdigo fuente del firmware


procesador de seales
En esta seccin se detalla el cdigo fuente del firmware del procesador de seales
compuesto por los siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin del cargador


que no pueden ser modificados, tales como el tamao del smbolo, etc.

Archivo phy.h: en este archivo se declaran primitivas con funcionalidades referentes a la


envo y recepcin de seales de informacin.

Archivo phy.c: en este archivo se encuentran implementadas las primitivas declaradas en


el archivo phy.h.

Archivo main.c: en este archivo se encuentra implementada la rutina principal del


firmware procesador de seales.

C.6.1. Archivo config.h


/*
config.h:
Definicin de parmetros de configuracin.

FernandoArielBeunza79156

655

Tesis de Grado en Ingeniera Informtica


*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Frecuencia de reloj del microcontrolador. */


#define F_CPU

11059200UL

/* Capa de fsica. */
/* Mxima cantidad de bytes que puede almacenar el buffer. */
#define PHY_PAYLOADSIZE
400
/* Cdigo de operacin de envo de trama. */
#define PHY_SNDFRMOP

0xa9

/* Cdigo de operacin de obtencin de trama capturada. */


#define PHY_GETFRMOP
0xaa
/* Cdigo de operacin de captura de trama. */
#define PHY_CAPFRMOP

0xab

/* Cdigo de operacin de reenvo de trama. */


#define PHY_RSDFRMOP

0xac

/* Cdigo de operacin de sensado del canal de comunicacin. */


#define PHY_SENSCHOP
0xad
/* Cdigo de operacin de generacin de seal de ruido. */
#define PHY_GENNOISEOP
0xae
/* Cdigo de limpieza del buffer. */
#define PHY_CRBUFFOP

0xaf

/* Cdigo de generacin de seal de prueba 1. */


#define PHY_TSTSIGOP1

0xba

/* Cdigo de generacin de seal de prueba 2. */


#define PHY_TSTSIGOP2

0xbb

/* Cdigo de prueba de recepcin. */


#define PHY_TSTRCVOP

0xbc

#endif

C.6.2. Archivo phy.h


/*
phy.h:
Declaracin de funciones referentes a la capa fsica.
*/

#if !defined(__PHY_H__)
#define __PHY_H__

/* Archivos includos necesarios. */


#include "config.h"
#include <inttypes.h>

/* Definicin de funciones pblicas. */

656

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin phy_init:
Inicializa los recursos utilizados por la capa fsica.
*/
void phy_init(void);
/*
Funcin phy_exec:
Espera y ejecuta la operaciones solicitadas a la capa fsica.
*/
void phy_exec(void);

#endif

C.6.3. Archivo phy.c


/*
phy.c:
Implementacin de funciones referentes a la capa fsica.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>

/* Definicin de constantes. */
/* Nivel de tensin por defecto del generador de seal. */
#define PHY_SIGGENLEVEL
0x07
/* Nivel de tensin por defecto del umbral de deteccin. */
#define PHY_THGENLEVEL
0x09
/* Tiempo mximo de espera entre bytes recibidos. */
#define PHY_TIMEOUTBITS

24

/* Caracter utilizado para calibrar el umbral de deteccin. */


#define PHY_CALTHRBYTE
0x55
/* Caracter utilizado como delimitador de patrn de inicio. */
#define PHY_DELBYTE
0xdb

/* Patrn de bytes de inicio. */


static const uint8_t __phy_startpattern__[] = {
0xff,
0xff,
0x7f,
0xff,
0xff,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
PHY_CALTHRBYTE,
0xff,
0xff,
PHY_DELBYTE
};

FernandoArielBeunza79156

657

Tesis de Grado en Ingeniera Informtica


/* Patrn de bytes de fin. */
static const uint8_t __phy_endpattern__[] = {
0xff,
0xff
};

/* Variables globales. */
/* Cdigo de operacin. */
static volatile uint8_t __phy_buffop__;
/* Cantidad de bytes almacenados en el buffer. */
static volatile uint16_t __phy_buffsize__;
/* Puntero al contenido del buffer. */
static volatile uint8_t *__phy_buffdata__;
/* Buffer de trama. */
static volatile uint8_t __phy_buffer__[PHY_PAYLOADSIZE +
sizeof(__phy_startpattern__) +
sizeof(__phy_endpattern__)];

/* Declaracin de funciones privadas. */


static uint8_t __phy_recvbyte__(void);
static uint8_t __phy_sendbyte__(uint8_t);
static void __phy_sndframe__(void);
static void __phy_calthreshold__(void);
static int __phy_capframe__(void);
static int __phy_sensechannel__(uint8_t);
static void __phy_gennoisesignal__(void);
static void __phy_tstsignal1__(void);
static void __phy_tstsignal2__(void);
static void __phy_tstreceive__(void);

/* Implementacin de funciones pblicas. */


/*
Funcin phy_init:
Inicializa los recursos utilizados por la capa fsica.
*/
void phy_init(void)
{
/* Variables. */
uint16_t i;

/* Posicin dentro del buffer. */

/* Desactiva las interrupciones. */


cli();
/* Inicializa los DACs. */
DDRA = 0xff;
PORTA = ((PHY_SIGGENLEVEL & 0x0f) << 4) | (PHY_THGENLEVEL & 0x0f);
/* Inicializa salida de datos recibidos y comparador analgico. */
DDRB = 0x83;
ACSR = 0x00;
PORTB = 0x03;
/* Inicializa entrada de recepcin seal. */
DDRC = 0x00;
PORTC = 0x00;
/* Inicializa integrador. */
DDRD = 0xff;
PORTD = 0x00;
/* Inicializa entrada de datos a enviar. */
DDRE = 0x04;

658

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


PORTE = 0x03;
/* Inicializa el buffer. */
__phy_buffop__ = 0x00;
__phy_buffsize__ = 0;
__phy_buffdata__ = __phy_buffer__ + sizeof(__phy_startpattern__);
for(i = 0; i < sizeof(__phy_startpattern__); i++)
__phy_buffer__[i] = __phy_startpattern__[i];
/* Inicializa la interrupcin INT2. */
EMCUCR &= (0xff ^ (1 << ISC2));
GICR |= (1 << INT2);
}
/*
Funcin phy_exec:
Espera y ejecuta la operaciones solicitadas a la capa fsica.
*/
void phy_exec(void)
{
sei();
while(1) PORTA = ((PHY_SIGGENLEVEL & 0x0f) << 4) | (PHY_THGENLEVEL & 0x0f);
}

/* Implementacin de funciones privadas. */


/*
Interrupcin INT2:
Recibe solicitudes de operacin.
*/
ISR(INT2_vect, ISR_BLOCK)
{
/* Variables. */
uint16_t i;
uint16_t buffsize;
uint8_t thrlevel;

/* Posicin dentro del buffer. */


/* Cantidad de bytes almacenados en
el buffer. */
/* Umbral de deteccin de ocupacin
del canal de comunicacin. */

/* Desactiva las interrupciones. */


cli();
/* Verifica el estado de la solicitud de interrupcin. */
if (PINE & 0x01)
{
sei();
return;
}
/* Recibe la operacin requerida. */
__phy_buffop__ = __phy_recvbyte__();
/* Verifica si es la envo de trama. */
if (__phy_buffop__ == PHY_SNDFRMOP)
{
/* Almacena la trama recibida en el buffer. */
i = 0;
PORTB |= 0x01;
while((!(PINE & 0x01)) && (i < PHY_PAYLOADSIZE))
__phy_buffdata__[i++] = __phy_recvbyte__();
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
PORTB |= 0x01;
__phy_buffsize__ = i;
for(i = 0; i < sizeof(__phy_endpattern__); i++)
__phy_buffdata__[i + __phy_buffsize__] = __phy_endpattern__[i];
/* Enva la trama almacenada en el buffer. */
PORTB &= 0xfe;

FernandoArielBeunza79156

659

Tesis de Grado en Ingeniera Informtica


__phy_sndframe__();
PORTB |= 0x01;
}
/* Verifica si es la operacin de obtencin de trama capturada. */
else if (__phy_buffop__ == PHY_GETFRMOP)
{
i = 0;
PORTB |= 0x01;
while((!(PINE & 0x01)) && (i < __phy_buffsize__))
__phy_sendbyte__(__phy_buffdata__[i++]);
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
}
/* Verifica si es la operacin de captura de trama. */
else if (__phy_buffop__ == PHY_CAPFRMOP)
{
PORTB |= 0x01;
buffsize = __phy_buffsize__;
if (!(PINE & 0x01))
__phy_buffsize__ = __phy_recvbyte__() << 8;
if (!(PINE & 0x01))
__phy_buffsize__ |= __phy_recvbyte__();
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
PORTB |= 0x01;
if (__phy_buffsize__ > PHY_PAYLOADSIZE)
__phy_buffsize__ = PHY_PAYLOADSIZE;
if (__phy_buffsize__)
{
__phy_calthreshold__();
if (__phy_capframe__())
PORTB &= 0xfe;
else
__phy_buffsize__ = buffsize;
}
}
/* Verifica si es la operacin de reenvo de trama. */
else if (__phy_buffop__ == PHY_RSDFRMOP)
{
PORTB |= 0x01;
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
PORTB |= 0x01;
if (__phy_buffsize__)
{
for(i = 0; i < sizeof(__phy_endpattern__); i++)
__phy_buffdata__[i + __phy_buffsize__] = __phy_endpattern__[i];
PORTB &= 0xfe;
__phy_sndframe__();
PORTB |= 0x01;
}
}
/* Verifica si es la operacin de sensado del canal de comunicacin. */
else if (__phy_buffop__ == PHY_SENSCHOP)
{
/* Obtiene el umbral de deteccin de ocupacin del canal de
comunicacin. */
PORTB |= 0x01;
if (!(PINE & 0x01))
thrlevel = __phy_recvbyte__();
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
/* Sensa el estado del canal de comunicacin. */
if (__phy_sensechannel__(thrlevel)) PORTB &= 0xfe;
}
/* Verifica si es la operacin de generacin de seal de ruido. */
else if (__phy_buffop__ == PHY_GENNOISEOP)
{
PORTB |= 0x01;
while(!(PINE & 0x01))

660

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


__phy_sendbyte__(0xff);
__phy_gennoisesignal__();
}
/* Verifica si es la operacin de limpieza del buffer. */
else if (__phy_buffop__ == PHY_CRBUFFOP)
{
PORTB |= 0x01;
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
__phy_buffsize__ = 0;
}
/* Verifica si es la operacin de generacin de seal de prueba 1. */
else if (__phy_buffop__ == PHY_TSTSIGOP1)
{
PORTB |= 0x01;
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
__phy_tstsignal1__();
}
/* Verifica si es la operacin de generacin de seal de prueba 2. */
else if (__phy_buffop__ == PHY_TSTSIGOP2)
{
PORTB |= 0x01;
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
__phy_tstsignal2__();
}
/* Verifica si es la operacin de prueba de recepcin. */
else if (__phy_buffop__ == PHY_TSTRCVOP)
{
PORTB |= 0x01;
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
__phy_tstreceive__();
}
/* Operacin desconocida. */
else
{
PORTB |= 0x01;
while(!(PINE & 0x01))
__phy_sendbyte__(0xff);
}
/* Activa las interrupciones. */
sei();
}
/*
Funcin __phy_recvbyte__:
Recibe un byte del mdulo procesamiento.
*/
static uint8_t __phy_recvbyte__(void)
{
/* Variables. */
static uint8_t dat;

/* Byte recibido. */

/* Recibe un byte. */
asm volatile("\
push
push
push
push
clr
ldi
L_wait1%=:
in
andi
out
sbis
rjmp
nop

;
;
;
;
;
;
;
;
;
;
;
;

r16
r17
r18
r19
r19
r18, 0x08
r16, %0
r16, (1 << %1) | (1 << %2)
%3, r16
%0, %1
L_wait1%=

FernandoArielBeunza79156

Guarda contenido de los


registros utilizados.

Inicializa el buffer de
bits recibidos.
Espera comienzo de pulso
de sincronismo

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

661

Tesis de Grado en Ingeniera Informtica

L_wait2%=:

L_end0%=:

L_end1%=:

in
andi
nop
nop
nop
out
andi
lsr
or
clz
ldi
nop
nop
nop
nop
nop
nop
breq
dec
nop
nop
nop
nop
nop
nop
sbic
rjmp
dec
breq
lsl
rjmp
st
ldi
out
pop
pop
pop
pop
:
:

r16, %0
r16, (1 << %1) | (1 << %2)

%3, r16
r16, (1 << %2)
r16
r19, r16
r17, %4

L_end0%=
r17

%0, %1
L_wait2%=
r18
L_end1%=
r19
L_wait1%=
x, r19
r16, (1 << %1) | (1 << %2)
%3, r16
r19
r18
r17
r16
"I"
"I"
"I"
"I"
"M"
"x"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Recibe un nuevo bit.

Guarda el bit recibido.

Espera fin de pulso de


sincronismo.

Verifica si se completo
el byte.

Guarda el byte recibido.

Recupera contenido de los


registros utilizados.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

_SFR_IO_ADDR(PINE),
(0),
(1),
_SFR_IO_ADDR(PORTB),
((PHY_TIMEOUTBITS * 5)),
(&dat)

);
/* Devuelve el byte recibido. */
return dat;
}
/*
Funcin __phy_sendbyte__:
Enva un byte al mdulo procesamiento.
*/
static uint8_t __phy_sendbyte__(uint8_t b)
{
/* Variables. */
static uint8_t dat;

/* Byte a enviar. */

/* Enva un byte. */
dat = b;
asm volatile("\
push
push
push
push
ld
ldi
L_wait1%=:
in

;
;
;
;
;
;
;

662

r16
r17
r18
r19
r19, x
r18, 0x08
r16, %0

Guarda contenido de los


registros utilizados.

Inicializa el buffer de
bits recibidos.
Espera comienzo de pulso

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_sndbit0%=:

L_wait2%=:

L_end0%=:

L_end1%=:

andi
out
sbis
rjmp
nop
in
andi
rol
brcc
ori
out
clz
ldi
nop
nop
nop
nop
nop
nop
nop
nop
breq
dec
nop
nop
nop
nop
nop
nop
sbic
rjmp
dec
breq
nop
rjmp
ldi
out
pop
pop
pop
pop
:
:

r16, (1 << %1) | (1 << %2)


%3, r16
%0, %1
L_wait1%=
r16, %0
r16, (1 << %1)
r19
L_sndbit0%=
r16, (1 << %2)
%3, r16
r17, %4

L_end0%=
r17

%0, %1
L_wait2%=
r18
L_end1%=
L_wait1%=
r16, (1 << %1) | (1 << %2)
%3, r16
r19
r18
r17
r16
"I"
"I"
"I"
"I"
"M"
"x"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

de sincronismo

Enva un nuevo bit.

Espera fin de pulso de


sincronismo.

Verifica si se completo
el byte.

Recupera contenido de los


registros utilizados.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

_SFR_IO_ADDR(PINE),
(0),
(1),
_SFR_IO_ADDR(PORTB),
((PHY_TIMEOUTBITS * 5)),
(&dat)

);
/* Devuelve el byte envado. */
return dat;
}
/*
Funcin __phy_sndframe__:
Enva la trama almacenada en el buffer.
*/
static void __phy_sndframe__(void)
{
asm volatile("\
push
r2
push
r3
push
r4
push
r5
push
r6
push
r7
push
r8
push
r9
push
r10
push
r11

FernandoArielBeunza79156

; Guarda contenido de los


; registros utilizados.
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

663

Tesis de Grado en Ingeniera Informtica

L_init%=:

664

push
push
push
push
push
push
push
push
push
in
mov
andi
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
or
cp
cpc
brne
rjmp
ldi
ld
sbi
nop
nop
nop
nop
nop
nop
nop
nop

r12
r13
r14
r15
r16
r17
r18
r19
r20
r19, %0
r20, r19
r19, 0x0f
r16, 0x90
r2, r16
r2, r19
r16, 0x40
r3, r16
r3, r19
r16, 0x10
r4, r16
r4, r19
r16, 0x20
r5, r16
r5, r19
r16, 0x50
r6, r16
r6, r19
r16, 0x70
r7, r16
r7, r19
r16, 0x60
r8, r16
r8, r19
r16, 0x80
r9, r16
r9, r19
r16, 0x30
r10, r16
r10, r19
r16, 0xa0
r11, r16
r11, r19
r16, 0x00
r12, r16
r12, r19
r16, 0xc0
r13, r16
r13, r19
r16, 0xb0
r14, r16
r14, r19
r16, 0xd0
r15, r16
r15, r19
r16, 0xe0
r16, r19
r30, r26
r31, r27
L_init%=
L_end%=
r17, 0x07
r18, z+
%1, %2

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Carga los valores de las
\n\t\
muestras.
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Verifica si ya se
\n\t\
procesaron todos los datos \n\t\
almacenados en el buffer.
\n\t\
\n\t\
\n\t\
\n\t\
Activa el transmisor.
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_sndbit0_06_0%=:

nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
sbrc
rjmp
nop
out

r18, 7
L_sndbit1_06_0%=
%0, r8

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Enva los primeros 7 bits
; de un byte de los datos.
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

665

Tesis de Grado en Ingeniera Informtica

L_sndbit0_06_1%=:

666

out
out
out
out
out
nop
out
nop
nop
out
out
out
lsl
dec
out
out
out
out
out
nop
out
out
out
out
out
out
out
out
out
out
out
out
out
out
nop
nop
out
out
out
out
out
nop
out
out
out
nop
out
out
out
out
out
nop
out
out
out
out
out
out
out
out
out
cpi
breq
nop
out
out
out
out
out
out
out

%0,
%0,
%0,
%0,
%0,

r14
r16
r15
r11
r9

%0, r2

%0,
%0,
%0,
r18
r17
%0,
%0,
%0,
%0,
%0,

r9
r7
r8

%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r14
r9
r6
r8
r13
r16
r11
r10
r3
r9
r2
r6
r10
r3

%0,
%0,
%0,
%0,
%0,

r8
r13
r16
r2
r5

r9
r13
r16
r13
r11

%0, r7
%0, r11
%0, r14
%0,
%0,
%0,
%0,
%0,

r13
r14
r9
r7
r11

%0, r6
%0, r12
%0, r3
%0, r11
%0, r13
%0, r9
%0, r10
%0, r5
%0, r3
r17, 0x00
L_sndbit0_06_2%=
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r6
r9
r14
r11
r8
r3
r8

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_sndbit0_06_2%=:

L_sndbit1_06_0%=:

L_sndbit1_06_1%=:

out
nop
out
out
out
sbrs
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
out
out
out
out
out
out
out
out
nop
out
out
out
sbrs
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
out
out
out
out
out
out
nop
out
nop
nop
out
out
out
lsl
dec
out
out
out
out
out
nop
out
out
out
out
out
out
out
out
out

%0, r14
%0, r8
%0, r4
%0, r5
r18, 7
L_sndbit1_06_0%=
%0,
%0,
%0,
%0,
%0,
%0,

r8
r14
r16
r15
r11
r9

%0, r2
L_sndbit0_06_1%=
%0, r6
%0, r9
%0, r14
%0, r11
%0, r8
%0, r3
%0, r8
%0, r14
%0, r8
%0, r4
%0, r5
r18, 7
L_sndbit1_7_0%=
%0,
%0,
%0,
%0,
%0,
%0,

r8
r14
r16
r15
r11
r9

%0, r2
L_sndbit0_7_1%=
%0, r2
%0, r3
%0, r4
%0, r5
%0, r6
%0, r7
%0, r8

%0,
%0,
%0,
r18
r17
%0,
%0,
%0,
%0,
%0,

r7
r9
r2

%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r3
r7
r11
r2
r10
r12
r6
r13
r14

FernandoArielBeunza79156

r7
r10
r4
r10
r6

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

667

Tesis de Grado en Ingeniera Informtica

L_sndbit1_06_2%=:

668

out
out
out
out
out
nop
nop
out
out
out
out
out
nop
out
out
out
nop
out
out
out
out
out
nop
out
out
out
out
out
out
out
out
out
cpi
breq
nop
out
out
out
out
out
out
out
out
nop
out
out
out
sbrs
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
out
out
out
out
out
out
out
out
nop
out
out
out

%0,
%0,
%0,
%0,
%0,

r7
r8
r11
r13
r14

%0,
%0,
%0,
%0,
%0,

r2
r10
r4
r8
r15

%0, r9
%0, r6
%0, r3
%0,
%0,
%0,
%0,
%0,

r10
r3
r7
r9
r6

%0, r11
%0, r16
%0, r14
%0, r6
%0, r10
%0, r7
%0, r13
%0, r15
%0, r14
r17, 0x00
L_sndbit1_06_2%=
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r11
r7
r3
r6
r2
r14
r2
r3

%0, r2
%0, r16
%0, r15
r18, 7
L_sndbit0_06_0%=
%0,
%0,
%0,
%0,
%0,
%0,

r2
r3
r4
r5
r6
r7

%0, r8
L_sndbit1_06_1%=
%0, r11
%0, r7
%0, r3
%0, r6
%0, r2
%0, r14
%0, r2
%0, r3
%0, r2
%0, r16
%0, r15

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_sndbit0_7_0%=:

L_sndbit0_7_1%=:

sbrs
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
out
out
out
out
out
out
nop
out
nop
nop
out
out
out
ld
out
out
out
out
out
ldi
out
out
out
out
out
out
out
out
out
out
out
out
out
out
nop
nop
out
out
out
out
out
nop
out
out
out
cp
out
out
out
out
out
cpc
out
out
out
out
out
out
out

r18, 7
L_sndbit0_7_0%=
%0,
%0,
%0,
%0,
%0,
%0,

r2
r3
r4
r5
r6
r7

%0, r8
L_sndbit1_7_1%=
%0, r8
%0, r14
%0, r16
%0, r15
%0, r11
%0, r9
%0, r2

%0, r9
%0, r7
%0, r8
r18, z+
%0, r9
%0, r13
%0, r16
%0, r13
%0, r11
r17, 0x07
%0, r14
%0, r9
%0, r6
%0, r8
%0, r13
%0, r16
%0, r11
%0, r10
%0, r3
%0, r9
%0, r2
%0, r6
%0, r10
%0, r3

%0,
%0,
%0,
%0,
%0,

r8
r13
r16
r2
r5

%0, r7
%0, r11
%0, r14
r30, r26
%0, r13
%0, r14
%0, r9
%0, r7
%0, r11
r31, r27
%0, r6
%0, r12
%0, r3
%0, r11
%0, r13
%0, r9
%0, r10

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
; Enva el ltimo bit de un
; byte de los datos.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

669

Tesis de Grado en Ingeniera Informtica

L_sndbit0_7_2%=:

L_sndbit1_7_0%=:

L_sndbit1_7_1%=:

670

out
out
breq
nop
nop
out
out
out
out
out
out
out
out
nop
out
out
out
sbrs
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
nop
out
out
out
out
out
out
out
out
nop
out
out
out
nop
rjmp
out
out
out
out
out
out
nop
out
nop
nop
out
out
out
ld
out
out
out
out
out
ldi
out
out
out
out
out
out
out

%0, r5
%0, r3
L_sndbit0_7_2%=

%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r6
r9
r14
r11
r8
r3
r8
r14

%0, r8
%0, r4
%0, r5
r18, 7
L_sndbit1_06_0%=
%0,
%0,
%0,
%0,
%0,
%0,

r8
r14
r16
r15
r11
r9

%0, r2
L_sndbit0_06_1%=
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r6
r9
r14
r11
r8
r3
r8
r14

%0, r8
%0, r4
%0, r5
L_end%=
%0, r2
%0, r3
%0, r4
%0, r5
%0, r6
%0, r7
%0, r8

%0, r7
%0, r9
%0, r2
r18, z+
%0, r7
%0, r10
%0, r4
%0, r10
%0, r6
r17, 0x07
%0, r3
%0, r7
%0, r11
%0, r2
%0, r10
%0, r12
%0, r6

;
;
; Verifica si ya se
; procesaron todos los datos
; almacenados en el buffer.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_sndbit1_7_2%=:

out
out
out
out
out
out
out
nop
nop
out
out
out
out
out
nop
out
out
out
cp
out
out
out
out
out
cpc
out
out
out
out
out
out
out
out
out
breq
nop
nop
out
out
out
out
out
out
out
out
nop
out
out
out
sbrs
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
nop
out
out
out
out
out
out
out
out
nop

%0,
%0,
%0,
%0,
%0,
%0,
%0,

r13
r14
r7
r8
r11
r13
r14

%0,
%0,
%0,
%0,
%0,

r2
r10
r4
r8
r15

%0, r9
%0, r6
%0, r3
r30, r26
%0, r10
%0, r3
%0, r7
%0, r9
%0, r6
r31, r27
%0, r11
%0, r16
%0, r14
%0, r6
%0, r10
%0, r7
%0, r13
%0, r15
%0, r14
L_sndbit1_7_2%=

%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r11
r7
r3
r6
r2
r14
r2
r3

%0, r2
%0, r16
%0, r15
r18, 7
L_sndbit0_06_0%=
%0,
%0,
%0,
%0,
%0,
%0,

r2
r3
r4
r5
r6
r7

%0, r8
L_sndbit1_06_1%=
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

FernandoArielBeunza79156

r11
r7
r3
r6
r2
r14
r2
r3

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Verifica si ya se
; procesaron todos los datos
; almacenados en el buffer.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

671

Tesis de Grado en Ingeniera Informtica


out
out
out
nop
nop
nop
cbi
out
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop

L_end%=:

:
:

%0, r2
%0, r16
%0, r15

%1, %2
%0, r19
r20
r19
r18
r17
r16
r15
r14
r13
r12
r11
r10
r9
r8
r7
r6
r5
r4
r3
r2

;
;
;
;
;
;
; Desactiva el transmisor.
;
; Recupera contenido de los
; registros utilizados.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

"I"
"I"
"I"
"x"

_SFR_IO_ADDR(PORTA),
_SFR_IO_ADDR(PORTE),
(2),
(__phy_buffer__ + sizeof(__phy_startpattern__) +
__phy_buffsize__ + sizeof(__phy_endpattern__)),
"z" (__phy_buffer__)

);
}
/*
Funcin __phy_calthreshold__:
Calibra el umbral de deteccin utilizado para determinar el valor de los
bits recibidos.
*/
static void __phy_calthreshold__(void)
{
/* Variables. */
uint8_t b;
uint8_t thl;
uint8_t sbyte;
uint8_t thlevel;
uint8_t thlevels;

/* Inicializa el integrador. */
PORTD = 0x00;
PORTB |= 0x80;
PORTB &= 0x7f;
asm volatile("\
push
r16
ldi
r16, 0x19
L_continue%=:
dec
r16
brne
L_continue%=
nop
pop
r16
:
:
);

/*
/*
/*
/*

Cantidad de bits. */
Umbral de deteccin. */
Valor del byte sensado. */
Acumulador de umbrales
vlidos. */
/* Cantidad de umbrales vlidos. */

;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

/* Determina el umbral de deteccin. */


thlevel = 0;
thlevels = 0;

672

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


for(thl = 0;
{
sbyte
PORTA
for(b
{

thl < 0x10; thl++)


= 0x00;
= ((PHY_SIGGENLEVEL & 0x0f) << 4) | thl;
= 0; b < 8; b++)
/* Genera un bit de prueba. */
if (PHY_CALTHRBYTE & (0x80 >> b))
PORTD = 0xff;
else
PORTD = 0x00;
/* Espera. */
asm volatile("\
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
:
:
);

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

/* Sensa el valor del bit. */


sbyte <<= 1;
if (ACSR & 0x20) sbyte |= 0x01;
/* Espera. */
asm volatile("\
push
r16
ldi
r16, 0x13
dec
r16
brne
L_continue%=
nop
nop
pop
r16
:
:
);

L_continue%=:

}
/* Verifica si el umbral es vlido. */
if (sbyte == PHY_CALTHRBYTE)
{
thlevel += thl;
thlevels ++;
}
}
/* Ajusta el umbral de deteccin. */
if (thlevels)
thlevel /= thlevels;
else
thlevel = PHY_THGENLEVEL;
PORTA = ((PHY_SIGGENLEVEL & 0x0f) << 4) | thlevel;
/* Reinicia el integrador. */
PORTB |= 0x80;
PORTB &= 0x7f;
}

FernandoArielBeunza79156

673

Tesis de Grado en Ingeniera Informtica


/*
Funcin __phy_capframe__:
Captura una trama y la almacena en el buffer.
*/
static int __phy_capframe__(void)
{
/* Variables. */
uint8_t sreg;
int capstatus;

/* Contenido del registro de


estado. */
/* Estado de la captura. */

/* Guarda el contenido del registro de estado. */


sreg = SREG;
/* Realiza la captura. */
asm volatile("\
push
r2
push
r3
push
r4
push
r5
push
r6
push
r7
push
r8
push
r9
push
r10
push
r11
push
r16
push
r17
push
r18
push
r19
push
r20
push
r21
ldi
r16, 0x00
out
%1, r16
mov
r2, r16
mov
r3, r16
mov
r4, r16
mov
r5, r16
mov
r6, r16
mov
r7, r16
mov
r8, r16
mov
r9, r16
mov
r10, r16
mov
r11, r16
L_init_rx%=:
ldi
r17, 0x00
ldi
r18, %9
sbi
%2, %3
clr
r19
ldi
r16, 0x1a
L_wait_rx_0%=:
dec
r16
brne
L_wait_rx_0%=
in
r21, %8
cbi
%2, %3
L_sense_rx%=:
in
r16, %0
com
r16
out
%1, r16
nop
nop
sbis
%4, %5
rjmp
L_calth_rx_0%=
nop
in
r16, %0
com
r16
out
%1, r16
nop
nop
sbis
%4, %5
rjmp
L_calth_rx_0%=
nop

674

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Guarda contenido de los


registros utilizados.

Inicializa la lnea de
retardo.

Inicializa el integrador.

Sensa el canal de
comunicacin a la espera
de registrar actividad.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_calth_rx_0%=:

in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
nop
sbis
rjmp
nop
in
com
out
nop
sbis
rjmp
rjmp
in
eor
out
mov
sbis
clr
sbic
inc

r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16

%4, %5
L_calth_rx_0%=
r16, %0
r16
%1, r16
%6, %7
L_end_0%=
L_sense_rx%=
r16, %0
r2, r16
%1, r2
r2, r16
%4, %5
r19
%4, %5
r19

FernandoArielBeunza79156

;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
; Inicia reajuste del umbral \n\t\
; de deteccin.
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\

675

Tesis de Grado en Ingeniera Informtica

L_calth_rx_1%=:

676

in
eor
out
mov
lsl
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo
ori
clr
in
eor
out
mov
nop
sbis
rjmp
nop
in
eor
out
mov
cpse
rjmp
nop
nop
in
eor
out
mov
ldi
out
rjmp

r16, %0
r3, r16
%1, r3
r3, r16
r17

r16, %0
r4, r16
%1, r4
r4, r16

r16, %0
r5, r16
%1, r5
r5, r16

r16, %0
r6, r16
%1, r6
r6, r16

r16, %0
r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_calth_rx_1%=
r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16
%6, %7
L_end_0%=
r16, %0
r10, r16
%1, r10
r10, r16
r17, r18
L_calth_rx_2%=

r16, %0
r11, r16
%1, r11
r11, r16
r20, 0x0f
%8, r20
L_calth_rx_3%=

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Detecta el valor del bit
; recibido.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


L_calth_rx_2%=:

L_calth_rx_3%=:

L_calth_rx_4%=:

nop
in
eor
out
mov
nop
nop
rjmp
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
lsl
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo
ori
clr
in
eor
out
mov
nop
nop
nop

r16, %0
r11, r16
%1, r11
r11, r16

L_calth_rx_0%=
r16, %0
r2, r16
%1, r2
r2, r16
%4, %5
r19
%4, %5
r19
r16, %0
r3, r16
%1, r3
r3, r16
r17

r16, %0
r4, r16
%1, r4
r4, r16

r16, %0
r5, r16
%1, r5
r5, r16

r16, %0
r6, r16
%1, r6
r6, r16

r16, %0
r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_calth_rx_4%=
r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Reajuste del umbral de


deteccin.

Detecta el valor del bit


recibido.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

677

Tesis de Grado en Ingeniera Informtica


nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
lsl
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
cpse
rjmp
nop
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo

678

r16, %0
r10, r16
%1, r10
r10, r16

r16, %0
r11, r16
%1, r11
r11, r16

r16, %0
r2, r16
%1, r2
r2, r16
%4, %5
r19
%4, %5
r19
r16, %0
r3, r16
%1, r3
r3, r16
r17

r16, %0
r4, r16
%1, r4
r4, r16

r16, %0
r5, r16
%1, r5
r5, r16

r16, %0
r6, r16
%1, r6
r6, r16
r20, 0x00
L_calth_rx_7%=
r16, %0
r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_calth_rx_5%=

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Detecta el valor del bit
; recibido.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


L_calth_rx_5%=:

L_calth_rx_6%=:

L_calth_rx_7%=:

L_calth_rx_8%=:

ori
clr
in
eor
out
mov
nop
sbis
rjmp
nop
in
eor
out
mov
cpse
rjmp
nop
nop
in
eor
out
mov
nop
out
rjmp
nop
in
eor
out
mov
mov
out
rjmp
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo
ori
clr
in
eor
out
mov
nop
sbis
rjmp
nop
in
eor
out
mov
cpse
rjmp
nop
nop
eor
out
mov
dec
out
rjmp

r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16
%6, %7
L_end_0%=
r16, %0
r10, r16
%1, r10
r10, r16
r17, r18
L_calth_rx_6%=

r16, %0
r11, r16
%1, r11
r11, r16
%8, r20
L_calth_rx_10%=
r16, %0
r11, r16
%1, r11
r11, r16
r20, r21
%8, r20
L_init_rx%=
r16, %0
r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_calth_rx_8%=
r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16
%6, %7
L_end_0%=
r16, %0
r10, r16
%1, r10
r10, r16
r17, r18
L_calth_rx_9%=

r11, r16
%1, r11
r11, r16
r20
%8, r20
L_calth_rx_10%=

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Verifica si el ajuste es
vlido.

Detecta el valor del


segundo bit recibido.

Verifica si el ajuste es
vlido.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

679

Tesis de Grado en Ingeniera Informtica


L_calth_rx_9%=:

L_calth_rx_10%=:

L_calth_rx_11%=:

680

nop
in
eor
out
mov
dec
out
rjmp
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
lsl
ldi
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo
ori
clr
in
eor
out
mov
nop
sbis
rjmp

r16, %0
r11, r16
%1, r11
r11, r16
r20
%8, r20
L_calth_rx_3%=
r16, %0
r2, r16
%1, r2
r2, r16
%4, %5
r19
%4, %5
r19
r16, %0
r3, r16
%1, r3
r3, r16
r17
r18, 0xff

r16, %0
r4, r16
%1, r4
r4, r16

r16, %0
r5, r16
%1, r5
r5, r16

r16, %0
r6, r16
%1, r6
r6, r16

r16, %0
r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_calth_rx_11%=
r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16
%6, %7
L_end_0%=

;
;
;
;
;
;
;
;
; Fin de reajuste.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Detecta el valor del bit
; recibido.
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_calth_rx_12%=:

L_calth_rx_13%=:

L_start_rx_0%=:

nop
in
eor
out
mov
cpse
rjmp
nop
nop
in
eor
out
mov
inc
out
rjmp
nop
in
eor
out
mov
nop
nop
rjmp
sbi
ldi
nop
nop
nop
cbi
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
lsl
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in

r16, %0
r10, r16
%1, r10
r10, r16
r17, r18
L_calth_rx_12%=

r16, %0
r11, r16
%1, r11
r11, r16
r20
%8, r20
L_calth_rx_13%=
r16, %0
r11, r16
%1, r11
r11, r16

L_calth_rx_10%=
%2, %3
r18, %10

%2, %3
r16, %0
r2, r16
%1, r2
r2, r16
%4, %5
r19
%4, %5
r19
r16, %0
r3, r16
%1, r3
r3, r16
r17

r16, %0
r4, r16
%1, r4
r4, r16

r16, %0
r5, r16
%1, r5
r5, r16

r16, %0
r6, r16
%1, r6
r6, r16

r16, %0

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Verifica el fin del


proceso de ajuste.

Reinicia el integrador.

Espera el delimitador.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

681

Tesis de Grado en Ingeniera Informtica

L_setbit_rx_0%=:

L_cont_rx_0%=:

L_start_rx_1%=:

682

eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo
ori
clr
in
eor
out
mov
nop
sbis
rjmp
nop
in
eor
out
mov
cpse
rjmp
nop
nop
in
eor
out
mov
nop
ldi
rjmp
nop
in
eor
out
mov
nop
nop
rjmp
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
lsl
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in

r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_setbit_rx_0%=
r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16
%6, %7
L_end_0%=
r16, %0
r10, r16
%1, r10
r10, r16
r17, r18
L_cont_rx_0%=

r16, %0
r11, r16
%1, r11
r11, r16
r18, 0x08
L_start_rx_1%=
r16, %0
r11, r16
%1, r11
r11, r16

L_start_rx_0%=
r16, %0
r2, r16
%1, r2
r2, r16
%4, %5
r19
%4, %5
r19
r16, %0
r3, r16
%1, r3
r3, r16
r17

r16, %0
r4, r16
%1, r4
r4, r16

r16, %0

;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
; Detecta el valor del bit
\n\t\
; recibido.
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
; Recibe los bytes restantes \n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\
;
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_setbit_rx_1%=:

L_cont_rx_1%=:

L_cont_rx_2%=:

L_end_0%=:
L_end_1%=:
L_end_2%=:

L_wait_rx_2%=:

eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
nop
nop
nop
nop
in
eor
out
mov
sbis
clr
sbic
inc
in
eor
out
mov
cpi
brlo
ori
clr
in
eor
out
mov
cp
cpc
brne
rjmp
in
eor
out
mov
dec
brne
ldi
nop
in
eor
out
mov
st
rjmp
nop
in
eor
out
mov
nop
nop
rjmp
clt
rjmp
set
ldi
out
sbi
nop
ldi
dec
brne

r5, r16
%1, r5
r5, r16

r16, %0
r6, r16
%1, r6
r6, r16

r16, %0
r7, r16
%1, r7
r7, r16
%4, %5
r19
%4, %5
r19
r16, %0
r8, r16
%1, r8
r8, r16
r19, 0x01
L_setbit_rx_1%=
r17, 0x01
r19
r16, %0
r9, r16
%1, r9
r9, r16
r30, r26
r31, r27
L_cont_rx_1%=
L_end_1%=
r16, %0
r10, r16
%1, r10
r10, r16
r18
L_cont_rx_2%=
r18, 0x08
r16, %0
r11, r16
%1, r11
r11, r16
z+, r17
L_start_rx_1%=
r16, %0
r11, r16
%1, r11
r11, r16

L_start_rx_1%=
L_end_2%=
r16, 0x00
%1, r16
%2, %3
r16, 0x1a
r16
L_wait_rx_2%=

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Detecta el valor del bit


recibido.

Verifica si la captura se
encuentra completa.

Interrupcin de captura.
Fin de captura.

Reinicia el integrador.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

683

Tesis de Grado en Ingeniera Informtica


nop
cbi
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
:
:

"I"
"I"
"I"
"I"
"I"
"I"
"I"
"I"
"I"
"M"
"M"
"x"
"z"

%2, %3
r21
r20
r19
r18
r17
r16
r11
r10
r9
r8
r7
r6
r5
r4
r3
r2

;
;
; Recupera contenido de los
; registros utilizados.
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

_SFR_IO_ADDR(PINC),
_SFR_IO_ADDR(PORTD),
_SFR_IO_ADDR(PORTB),
(7),
_SFR_IO_ADDR(ACSR),
(5),
_SFR_IO_ADDR(PINE),
(0),
_SFR_IO_ADDR(PORTA),
(PHY_CALTHRBYTE),
(PHY_DELBYTE),
(__phy_buffdata__ + __phy_buffsize__),
(__phy_buffdata__)

);
/* Obtiene el resultado de la captura. */
capstatus = 0;
if (SREG & 0x40) capstatus = 1;
/* Recupera el contenido del registro de estado. */
SREG = sreg;
/* Devuelve el resultado de la captura. */
return capstatus;
}
/*
Funcin __phy_sensechannel__:
Sensa la actividad del canal de comunicacin.
*/
static int __phy_sensechannel__(uint8_t thrlevel)
{
/* Variables. */
uint8_t sreg;
uint8_t thrstatus;
int capstatus;

/* Contenido del registro de


estado. */
/* Estado del canal de
comunicacin. */
/* Estado de la captura. */

/* Guarda el contenido del registro de estado. */


sreg = SREG;
/* Guarda el umbral de deteccin actual. */
thrstatus = PORTA;
/* Modifica el umbral de deteccin. */
PORTA = (PORTA & 0xf0) | (thrlevel & 0x0f);
/* Sensa el canal de comunicacin. */
asm volatile("\
push
r16

684

\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_wait_0%=:

L_sense_ch%=:

ldi
out
sbi
ldi
dec
brne
cbi
ldi
in
com
out
nop
sbis
rjmp
nop
nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
nop
nop
nop

r16, 0x00
%1, r16
%2, %3
r16, 0x1a
r16
L_wait_0%=
%2, %3
r17, 0xff
r16, %0
r16
%1, r16
%4, %5
L_end_1%=

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Inicializa el integrador.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Inicia el sensado de canal \n\t\
de comunicacin.
\n\t\
\n\t\
\n\t\
Verifica el alcance del
\n\t\
umbral de deteccin.
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

685

Tesis de Grado en Ingeniera Informtica

L_end_0%=:
L_end_1%=:
L_end_2%=:

L_wait_1%=:

nop
in
com
out
nop
nop
nop
nop
nop
in
com
out
nop
sbis
rjmp
rjmp
clt
rjmp
set
ldi
out
sbi
nop
ldi
dec
brne
nop
cbi
pop
:
:

r16, %0
r16
%1, r16

r16, %0
r16
%1, r16
%6, %7
L_end_0%=
L_sense_ch%=
L_end_2%=
r16, 0x00
%1, r16
%2, %3
r16, 0x1a
r16
L_wait_1%=
%2, %3
r16
"I"
"I"
"I"
"I"
"I"
"I"
"I"
"I"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Verifica solicitud de fin
\n\t\
de sensado de canal de
\n\t\
comunicacin.
\n\t\
Interrupcin de captura.
\n\t\
\n\t\
Deteccin de ocupacin del \n\t\
canal de comunicacin.
\n\t\
\n\t\
Reinicia el integrador.
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

_SFR_IO_ADDR(PINC),
_SFR_IO_ADDR(PORTD),
_SFR_IO_ADDR(PORTB),
(7),
_SFR_IO_ADDR(ACSR),
(5),
_SFR_IO_ADDR(PINE),
(0)

);
/* Restaura el umbral de deteccin anterior. */
PORTA = thrstatus;
/* Obtiene el resultado de la captura. */
capstatus = 0;
if (SREG & 0x40) capstatus = 1;
/* Recupera el contenido del registro de estado. */
SREG = sreg;
/* Devuelve el resultado de la captura. */
return capstatus;
}
/*
Funcin __phy_gennoisesignal__:
Genera una seal de ruido.
*/
static void __phy_gennoisesignal__(void)
{
asm volatile("\
push
r2
push
r3
push
r4
push
r5
push
r6
push
r7
push
r8
push
r9
push
r16
push
r17

686

; Guarda contenido de los


; registros utilizados.
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


push
push
in
mov
andi
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
or
ldi
sbi
mov
ori
clc
ror
ror
eor
ror
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop

r18
r19
r17, %0
r20, r17
r17, 0x0f
r16, 0x90
r2, r16
r2, r17
r16, 0x40
r3, r16
r3, r17
r16, 0x10
r4, r16
r4, r17
r16, 0x20
r5, r16
r5, r17
r16, 0x50
r6, r16
r6, r17
r16, 0x70
r7, r16
r7, r17
r16, 0x60
r8, r16
r8, r17
r16, 0x80
r9, r16
r9, r17
r16, 0x30
r10, r16
r10, r17
r16, 0xa0
r11, r16
r11, r17
r16, 0x00
r12, r16
r12, r17
r16, 0xc0
r13, r16
r13, r17
r16, 0xb0
r14, r16
r14, r17
r16, 0xd0
r15, r16
r15, r17
r16, 0xe0
r16, r17
r18, 0x00
%1, %2
r19, r18
r19, 0x80
r19
r19
r18, r19
r18

FernandoArielBeunza79156

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Carga los valores de las


muestras.

Inicializa la semilla.
Activa el transmisor.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

687

Tesis de Grado en Ingeniera Informtica

L_genbit0_0%=:

L_genbit0_1%=:

688

nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
sbrc
rjmp
nop
out
out
out
out
out
out
nop
out
nop
nop
out
out
out

r18, 7
L_genbit1%=
%0,
%0,
%0,
%0,
%0,
%0,

r8
r14
r16
r15
r11
r9

%0, r2

%0, r9
%0, r7
%0, r8

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Genera la seal de ruido
; pseudoaleatorio.
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_genbit1%=:

mov
ori
out
out
out
out
out
clc
out
out
out
out
out
out
out
out
out
out
out
out
out
out
ror
ror
out
out
out
out
out
eor
out
out
out
ror
out
out
out
out
out
nop
out
out
out
out
out
out
out
out
out
nop
sbis
rjmp
out
out
out
out
out
out
out
out
nop
out
out
out
sbrs
rjmp
nop
out
out
out
out

r19, r18
r19, 0x80
%0, r9
%0, r13
%0, r16
%0, r13
%0, r11
%0, r14
%0, r9
%0, r6
%0, r8
%0, r13
%0, r16
%0, r11
%0, r10
%0, r3
%0, r9
%0, r2
%0, r6
%0, r10
%0, r3
r19
r19
%0, r8
%0, r13
%0, r16
%0, r2
%0, r5
r18, r19
%0, r7
%0, r11
%0, r14
r18
%0, r13
%0, r14
%0, r9
%0, r7
%0, r11
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r6
r12
r3
r11
r13
r9
r10
r5
r3

%3, %4
L_end%=
%0, r6
%0, r9
%0, r14
%0, r11
%0, r8
%0, r3
%0, r8
%0, r14
%0, r8
%0, r4
%0, r5
r18, 7
L_genbit0_0%=
%0,
%0,
%0,
%0,

FernandoArielBeunza79156

r2
r3
r4
r5

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Verifica solicitud de fin
; de generacin de ruido.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

689

Tesis de Grado en Ingeniera Informtica


out
out
nop
out
nop
nop
out
out
out
mov
ori
out
out
out
out
out
clc
out
out
out
out
out
out
out
out
out
out
out
out
out
out
ror
ror
out
out
out
out
out
eor
out
out
out
ror
out
out
out
out
out
nop
out
out
out
out
out
out
out
out
out
nop
sbis
rjmp
out
out
out
out
out
out
out
out
nop
out

690

%0, r6
%0, r7
%0, r8

%0, r7
%0, r9
%0, r2
r19, r18
r19, 0x80
%0, r7
%0, r10
%0, r4
%0, r10
%0, r6
%0, r3
%0, r7
%0, r11
%0, r2
%0, r10
%0, r12
%0, r6
%0, r13
%0, r14
%0, r7
%0, r8
%0, r11
%0, r13
%0, r14
r19
r19
%0, r2
%0, r10
%0, r4
%0, r8
%0, r15
r18, r19
%0, r9
%0, r6
%0, r3
r18
%0, r10
%0, r3
%0, r7
%0, r9
%0, r6
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,
%0,

r11
r16
r14
r6
r10
r7
r13
r15
r14

%3, %4
L_end%=
%0, r11
%0, r7
%0, r3
%0, r6
%0, r2
%0, r14
%0, r2
%0, r3
%0, r2

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Verifica solicitud de fin
; de generacin de ruido.
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_end%=:

out
out
sbrc
rjmp
nop
out
out
out
out
out
out
nop
out
rjmp
cbi
out
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
:
:

%0, r16
%0, r15
r18, 7
L_genbit1%=
%0,
%0,
%0,
%0,
%0,
%0,

r8
r14
r16
r15
r11
r9

%0, r2
L_genbit0_1%=
%1, %2
%0, r17
r19
r18
r17
r16
r9
r8
r7
r6
r5
r4
r3
r2
"I"
"I"
"I"
"I"
"I"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
; Desactiva el transmisor.
;
; Recupera contenido de los
; registros utilizados.
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

_SFR_IO_ADDR(PORTA),
_SFR_IO_ADDR(PORTE),
(2),
_SFR_IO_ADDR(PINE),
(0)

);
}
/*
Funcin __phy_tstsignal1__:
Genera una seal de prueba.
*/
static void __phy_tstsignal1__(void)
{
asm volatile("\
push
r2
push
r3
push
r4
push
r5
push
r6
push
r7
push
r8
push
r9
push
r16
push
r17
push
r18
in
r17, %0
mov
r18, r17
andi
r17, 0x0f
ldi
r16, 0x00
mov
r2, r16
or
r2, r17
ldi
r16, 0x10
mov
r3, r16
or
r3, r17
ldi
r16, 0x20
mov
r4, r16
or
r4, r17
ldi
r16, 0x30
mov
r5, r16
or
r5, r17
ldi
r16, 0x40

FernandoArielBeunza79156

Guarda contenido de los


registros utilizados.

Carga los valores de las


muestras.

691

Tesis de Grado en Ingeniera Informtica

L_continue%=:

692

mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
sbi
out
nop
out
nop
nop
nop
out
nop
nop
nop
nop
out
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
out
nop
nop
nop
nop
out
nop
nop
nop
out
nop
nop
out
nop
nop
nop
out
nop
nop
nop
nop
out
nop
nop
nop
nop
nop
nop
nop

r6, r16
r6, r17
r16, 0x50
r7, r16
r7, r17
r16, 0x60
r8, r16
r8, r17
r16, 0x70
r9, r16
r9, r17
%1, %2
%0, r6
%0, r7

%0, r8

%0, r9

%0, r8

%0, r7

%0, r6

%0, r5

%0, r4

%0, r3

;
;
;
;
;
;
;
;
;
;
;
; Activa el transmisor.
; Genera la seal de prueba.
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

L_end%=:

nop
out
out
nop
nop
nop
nop
nop
nop
nop
nop
out
nop
nop
nop
nop
out
sbis
rjmp
nop
out
rjmp
out
cbi
out
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
:
:

%0, r2
%0, r3

%0, r4

%0, r5
%3, %4
L_end%=
%0, r6
L_continue%=
%0, r6
%1, %2
%0, r18
r18
r17
r16
r9
r8
r7
r6
r5
r4
r3
r2
"I"
"I"
"I"
"I"
"I"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Detiene la seal de prueba \n\t\
si hay una nueva solicitud \n\t\
de operacin.
\n\t\
\n\t\
\n\t\
\n\t\
Desactiva el transmisor.
\n\t\
\n\t\
Recupera contenido de los
\n\t\
registros utilizados.
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Guarda contenido de los


registros utilizados.

_SFR_IO_ADDR(PORTA),
_SFR_IO_ADDR(PORTE),
(2),
_SFR_IO_ADDR(PINE),
(0)

);
}
/*
Funcin __phy_tstsignal2__:
Genera una seal de prueba.
*/
static void __phy_tstsignal2__(void)
{
asm volatile("\
push
r2
push
r3
push
r4
push
r5
push
r6
push
r7
push
r8
push
r9
push
r16
push
r17
push
r18
in
r17, %0
mov
r18, r17
andi
r17, 0x0f
ldi
r16, 0x00
mov
r2, r16
or
r2, r17
ldi
r16, 0x10
mov
r3, r16

FernandoArielBeunza79156

Carga los valores de las


muestras.

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\

693

Tesis de Grado en Ingeniera Informtica

L_continue%=:

L_end%=:

or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
ldi
mov
or
sbi
out
out
out
out
nop
nop
sbis
rjmp
out
out
out
out
out
out
out
out
out
out
out
out
out
out
out
out
rjmp
cbi
out
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
pop
:
:

r3, r17
r16, 0x20
r4, r16
r4, r17
r16, 0x30
r5, r16
r5, r17
r16, 0x40
r6, r16
r6, r17
r16, 0x50
r7, r16
r7, r17
r16, 0x60
r8, r16
r8, r17
r16, 0x70
r9, r16
r9, r17
%1, %2
%0, r6
%0, r7
%0, r8
%0, r9

%3, %4
L_end%=
%0, r8
%0, r7
%0, r6
%0, r5
%0, r4
%0, r3
%0, r3
%0, r2
%0, r3
%0, r3
%0, r4
%0, r5
%0, r6
%0, r7
%0, r8
%0, r9
L_continue%=
%1, %2
%0, r18
r18
r17
r16
r9
r8
r7
r6
r5
r4
r3
r2
"I"
"I"
"I"
"I"
"I"

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Activa el transmisor.
\n\t\
Genera la seal de prueba. \n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Detiene la seal de prueba \n\t\
si hay una nueva operacin \n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
Desactiva el transmisor.
\n\t\
\n\t\
Recupera contenido de los
\n\t\
registros utilizados.
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
\n\t\
"

_SFR_IO_ADDR(PORTA),
_SFR_IO_ADDR(PORTE),
(2),
_SFR_IO_ADDR(PINE),
(0)

);
}
/*
Funcin __phy_tstreceive__:
Realiza una prueba de recepcin.
*/

694

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


static void __phy_tstreceive__(void)
{
asm volatile("\
push
r16
L_continue%=:
in
r16, %0
out
%1, r16
nop
sbis
%2, %3
rjmp
L_end%=
nop
rjmp
L_continue%=
L_end%=:
pop
r16
:
:
"I" _SFR_IO_ADDR(PINC),
"I" _SFR_IO_ADDR(PORTD),
"I" _SFR_IO_ADDR(PINE),
"I" (0)
);
}

;
;
;
;
;
;
;
;
;

\n\t\
Repite en el integrador la \n\t\
seal recibida.
\n\t\
\n\t\
Detiene la prueba si hay
\n\t\
una nueva operacin.
\n\t\
\n\t\
\n\t\
"

C.6.4. Archivo main.c


/*
main.c:
Procesador de seales del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include "phy.h"

/*
Funcin main:
Funcin principal.
*/
int main(void)
{
/* Inicializa los recursos utilizados por la capa fsica. */
phy_init();
/* Espera y ejecuta la operaciones solicitadas a la capa fsica. */
phy_exec();
/* Fin. */
return 0;
}

C.7. Especificacin del cdigo fuente del firmware


cargador
En esta seccin se detalla el cdigo fuente del firmware del cargador compuesto por los
siguientes archivos:

Archivo config.h: en este archivo se definen parmetros de configuracin del cargador


que no pueden ser modificados, tales como la posicin de la memoria donde se debe
instalar el firmware del modem PLC, el tamao mximo de dicho firmware, etc.

FernandoArielBeunza79156

695

Tesis de Grado en Ingeniera Informtica

Archivo common.h: en este archivo se declaran primitivas con funcionalidades generales.

Archivo common.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo common.h.

Archivo serial.h: en este archivo se declaran primitivas con funcionalidades referentes a


la entrada y salida va puerto RS232.

Archivo serial.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo serial.c.

Archivo interrupts.h: en este archivo se declaran primitivas de redireccin de las


interrupciones.

Archivo interrupts.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo interrupts.h.

Archivo memory.h: en este archivo se declaran primitivas con funcionalidades referentes


a la manipulacin de la memoria donde reside el firmware del modem PLC.

Archivo memory.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo memory.h.

Archivo boot.c: en este archivo se encuentra implementado el interprete de comandos del


cargador, con el cual se interacta por medio del puerto RS232.

C.7.1. Archivo config.h


/*
config.h:
Definicin de parmetros de configuracin.
*/

#if !defined(__CONFIG_H__)
#define __CONFIG_H__

/* Tamao de la lnea de comandos. */


#define LINE_SIZE

80

/* Cantidad de bytes mxima de cada registro en formato hexadecimal Intel. */


#define RECORD_SIZE
16
/* Comienzo del rea destinada a la memoria de datos del modem PLC. */
#define START_DATA
0x0000
/* Fin del rea destinada a la memoria de datos del modem PLC. */
#define END_DATA
0x7fff
/* Comienzo del rea destinada al firmware del modem PLC. */
#define START_FIRMWARE
0x8000
/* Fin del rea destinada al firmware del modem PLC. */
#define END_FIRMWARE

696

0xffff

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#endif

C.7.2. Archivo common.h


/*
common.h:
Declaracin de funciones comunes.
*/

#include "../common/common.h"

C.7.3. Archivo common.c


/*
common.c:
Implementacin de funciones comunes.
*/

#include "../common/common.c"

C.7.4. Archivo serial.h


/*
serial.h:
Declaracin de funciones referentes a la UART.
*/

#include "../common/serial.h"

C.7.5. Archivo serial.c


/*
serial.c:
Implementacin de funciones referentes a la UART.
*/

#include "../common/serial.c"

C.7.6. Archivo interrupts.h


/*
interrupts.h:
Declaracin de funciones comunes.
*/

#if !defined(__INTERRUPTS__H__)
#define __INTERRUPTS_H__

/* Declaracin de funciones publicas. */


/*

FernandoArielBeunza79156

697

Tesis de Grado en Ingeniera Informtica


Funcin int0:
Redirecciona la interrupcin 0.
*/
extern void int0(void) __interrupt 0 __naked;
/*
Funcin int1:
Redirecciona la interrupcin 1.
*/
extern void int1(void) __interrupt 1 __naked;
/*
Funcin int2:
Redirecciona la interrupcin 2.
*/
extern void int2(void) __interrupt 2 __naked;
/*
Funcin int3:
Redirecciona la interrupcin 3.
*/
extern void int3(void) __interrupt 3 __naked;
/*
Funcin int4:
Redirecciona la interrupcin 4.
*/
extern void int4(void) __interrupt 4 __naked;
/*
Funcin int5:
Redirecciona la interrupcin 5.
*/
extern void int5(void) __interrupt 5 __naked;

#endif

C.7.7. Archivo interrupts.c


/*
interrupts.c:
Implementacin de redirecciones de interrupcin.
*/

/* Archivos includos necesarios. */


#include "config.h"

/* Implementacin de funciones pblicas. */


/*
Funcin int0:
Redirecciona la interrupcin 0.
*/
void int0(void) __interrupt 0 __naked
{
__asm ljmp START_FIRMWARE+0x0003 __endasm;
}
/*
Funcin int1:
Redirecciona la interrupcin 1.
*/
void int1(void) __interrupt 1 __naked
{
__asm ljmp START_FIRMWARE+0x000b __endasm;

698

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/*
Funcin int2:
Redirecciona la interrupcin 2.
*/
void int2(void) __interrupt 2 __naked
{
__asm ljmp START_FIRMWARE+0x0013 __endasm;
}
/*
Funcin int3:
Redirecciona la interrupcin 3.
*/
void int3(void) __interrupt 3 __naked
{
__asm ljmp START_FIRMWARE+0x001b __endasm;
}
/*
Funcin int4:
Redirecciona la interrupcin 4.
*/
void int4(void) __interrupt 4 __naked
{
__asm ljmp START_FIRMWARE+0x0023 __endasm;
}
/*
Funcin int5:
Redirecciona la interrupcin 5.
*/
void int5(void) __interrupt 5 __naked
{
__asm ljmp START_FIRMWARE+0x002b __endasm;
}

C.7.8. Archivo memory.h


/*
memory.h:
Declaracin de funciones referentes al manejo de la memoria destinada al
firmware del modem PLC.
*/

#if !defined(__MEMORY_H__)
#define __MEMORY_H__

/* Declaracin de funciones pblicas. */


/*
Funcin init:
Inicia la ejecucin del firmware del modem PLC.
*/
void init(void);
/*
Funcin erase:
Borra la memoria destinada al firmware del modem PLC.
*/
void erase(void);
/*
Funcin read:
Lee la memoria que contiene el firmware del modem PLC.

FernandoArielBeunza79156

699

Tesis de Grado en Ingeniera Informtica


*/
void read(void);
/*
Funcin write:
Escribe en la memoria el firmware del modem PLC.
*/
void write(void);
/*
Funcin verify:
Verifica el contenido del rea de memoria destinada al firmware del modem
PLC.
*/
void verify(void);
/*
Funcin test:
Evala el funcionamiento de banco de memoria del modem PLC.
*/
void test(void);

#endif

C.7.9. Archivo memory.c


/*
memory.c:
Implementacin de funciones referentes al manejo de la memoria destinada al
firmware del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <at89x52.h>
#include "serial.h"
#include "common.h"

/* Definicin de SFR necesarias. */


__sfr __at (0xa7) WDTPRG;
__sfr __at (0xa6) WDTRST;

/* Configuracin del watchdog. */


/* Control del watchdog. */

/* Declaracin de funciones privadas. */


static int writemem(unsigned short int, unsigned char);
static unsigned char hex2val(char *);
static static void write_verify(int);

/* Implementacin de funciones pblicas. */


/*
Funcin init:
Inicia la ejecucin del firmware del modem PLC.
*/
void init(void)
{
/* Activa el watchdog. */
init_watchdog(1);
/* Salta al rea de memoria donde se encuentra almacenado el firmware del
modem PLC. */
__asm ljmp START_FIRMWARE __endasm;
}

700

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Funcin erase:
Borra la memoria destinada al firmware del modem PLC.
*/
void erase(void)
{
/* Variables. */
unsigned short int address;

/* Posicin de memoria. */

/* Borra la memoria donde se almacena el firmware del modem PLC. */


address = START_FIRMWARE;
while(1)
{
/* Devuelve el estado de la operacin de borrado. */
if ((address == START_FIRMWARE) || (!(address % 0x10)))
printf("%04X - %04X\r\n", address, (address + 0x0f));
/* Borra la posicin de memoria. */
if (!writemem(address, 0x00))
{
printf("Error at %04X\r\n", address);
return;
}
/* Verifica si se borraron todas las posiciones de memoria. */
if (address == END_FIRMWARE) break;
address ++;
}
}
/*
Funcin read:
Lee la memoria que contiene el firmware del modem PLC.
*/
void read(void)
{
/* Variables. */
unsigned short int rbytes;
unsigned short int toread;
unsigned short int address;
unsigned char j;
unsigned char checksum;

/* Cantidad de bytes a leer por


registro. */
/* Cantidad de bytes a leer en
total. */
/* Posicin de memoria. */
/* Contador de bytes ledos. */
/* Suma de verificacin. */

/* Lee el contenido de la memoria que contiene el firmware del modem


PLC. */
toread = END_FIRMWARE - START_FIRMWARE;
address = START_FIRMWARE;
do
{
/* Calcula la cantidad de bytes a leer. */
if (toread > RECORD_SIZE)
{
rbytes = RECORD_SIZE;
toread -= RECORD_SIZE;
}
else
{
rbytes = toread + 1;
toread = 0;
}
/* Inicializa el clculo de la suma de verificacin. */
checksum = rbytes;
checksum += (unsigned char) (address >> 8);
checksum += (unsigned char) (address & 0xff);

FernandoArielBeunza79156

701

Tesis de Grado en Ingeniera Informtica


/* Devuelve el contenido de la memoria en formato hexadecimal Intel. */
printf(":%02X%04X00", rbytes, address);
for(j = 0; j < rbytes; j++)
{
checksum += *((__xdata unsigned char *) address);
printf("%02X", *((__xdata unsigned char *) address));
address ++;
}
checksum = ((checksum ^ 0xff) + 1) & 0xff;
printf("%02X\r\n", checksum);
} while(toread);
printf(":00000001FF\r\n");
}
/*
Funcin write:
Escribe en la memoria el firmware del modem PLC.
*/
void write(void)
{
write_verify(1);
}
/*
Funcin verify:
Verifica el contenido del rea de memoria destinada al firmware del modem
PLC.
*/
void verify(void)
{
write_verify(0);
}
/*
Funcin test:
Evala el funcionamiento de banco de memoria del modem PLC.
*/
void test(void)
{
/* Variables. */
unsigned short int errors;
unsigned short int address;
unsigned char dat;
unsigned char read;

/* Cantidad de errores
encontrados. */
/* Posicin de memoria. */
/* Dato original de la posicin de
memoria. */
/* Dato ledo de la posicin de
memoria. */

/* Evala el funcionamiento de banco de memoria del modem PLC. */


errors = 0;
address = START_DATA;
while(1)
{
/* Lee el dato almacenado. */
dat = *((__xdata unsigned char *) address);
/* Escribe todos los bits con valor 0. */
writemem(address, 0x00);
read = *((__xdata unsigned char *) address);
if (read != 0x00)
{
printf("Error at %04X: write 00 read %02X\r\n", address, read);
errors ++;
}
/* Escribe todos los bits con valor 1. */
writemem(address, 0xff);
read = *((__xdata unsigned char *) address);
if (read != 0xff)
{

702

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


printf("Error at %04X: write FF read %02X\r\n", address, read);
errors ++;
}
/* Restaura el dato almacenado originalmente. */
writemem(address, dat);
read = *((__xdata unsigned char *) address);
if (read != dat)
{
printf("Error at %04X: write %02X read %02X\r\n",
address, dat, read);
errors ++;
}
else
printf("%04X: OK\r\n", address);
/* Verifica si evalu todas las posiciones de memoria. */
if (address == END_FIRMWARE) break;
address ++;
}
/* Devuelve el resultado de la operacin. */
if (errors) printf("%i error(s)\r\n", errors);
}

/* Implementacin de funciones privadas. */


/*
Funcin writemem:
Modifica el contenido de la posicin de memoria especificada.
*/
static int writemem(unsigned short int addr, unsigned char dat)
{
/* Varaibles. */
unsigned int i;
/* Contador. */
unsigned short int j;
/* Contador. */

/* Modifica el contenido de la memoria. */


*((__xdata unsigned char *) addr) = dat;
for(i = 0; i < 0x20; i++)
{
for(j = 0; j < 0x4000; j++)
{
if (*((__xdata unsigned char *) addr) == dat) return 1;
}
}
return 1;
}
/*
Funcin hex2val:
Convierte una cadena de caracteres que contiene un nmero hexadecimal de
dos digitos en su correspondiente valor numrico entre 0 y 255.
*/
static unsigned char
{
/* Variables.
char d;
unsigned char
unsigned char

hex2val(char *v)
*/
i;
val;

/* Dgito. */
/* Cantidad de digitos. */
/* Valor numrico. */

/* Convierte cada digito hexadecimal en su correspondiente valor. */


val = 0;
for(i = 0; i < 2; i++)
{
#if defined SDCC_MODEL_SMALL
d = *((__data char *) (v + i));
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)

FernandoArielBeunza79156

703

Tesis de Grado en Ingeniera Informtica


d = *((__xdata char *) (v + i));
#else
#error "hex2val(): unknow memory model"
#endif
val <<= 4;
if ((d >= '0') && (d <= '9'))
val += d - '0';
else if ((d >= 'a') && (d <= 'f'))
val += d - 'a' + 0x0a;
else if ((d >= 'A') && (d <= 'F'))
val += d - 'A' + 0x0a;
else
{
val = 0;
break;
}
}
/* Devuelve el valor nmerico obtenido. */
return val;
}
/*
Funcin write_verify:
Escribe o verifica la memoria que contiene el firmware del modem PLC.
*/
static void write_verify(int op)
{
/* Variables. */
short int errors;
unsigned short int address;
length_t length;
unsigned char i;
unsigned char val;
unsigned char lstr;
unsigned char type;
char *ptr;
char *ptr2;
unsigned char checksum;
char str[(RECORD_SIZE * 2) + 12];

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

Contador de errores. */
Direccin de memoria. */
Tamao del registro. */
Nmero de bytes del registro. */
Valor ledo. */
Longitud de la cadena
ingresada. */
Tipo de registro. */
Puntero a registro. */
Puntero a registro. */
Suma de verificacin. */
Registro recibido. */

/* Procesa cada registro recibido. */


errors = 0;
while(1)
{
/* Lee un registro. */
printf(">");
gets(str);
/* Verifica si el registro se encuentra vaca. */
if (streq(str, "")) continue;
/* Verifica que el registro corresponda al formato hexadecimal
Intel. */
lstr = strlen1(str);
if (lstr < 11)
{
printf("Invalid record\r\n\n");
continue;
}
if (!(lstr & 0x01))
{
printf("Invalid record\r\n\n");
continue;
}
if (*str != ':')
{
printf("Invalid record\r\n\n");
continue;

704

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* Obtiene la cantidad de bytes que tiene el registro. */
ptr = str + 1;
val = hex2val(ptr);
ptr += 2;
length = val;
checksum = val;
/* Verifica que la cantidad de bytes que contiene el registro sea
vlida. */
if (length > RECORD_SIZE)
{
printf("Invalid record\r\n\n");
continue;
}
/* Obtiene la posicin de memoria. */
val = hex2val(ptr);
ptr += 2;
address = val;
address <<= 8;
checksum += val;
val = hex2val(ptr);
ptr += 2;
address |= val;
checksum += val;
/* Obtiene el tipo de registro. */
val = hex2val(ptr);
ptr += 2;
type = val;
checksum += val;
/* Verifica si es el registro fin. */
if (type == 0x01) break;
/* Verifica que el tipo de registro sea vlido. */
if ((type != 0x00) && (type != 0x01))
{
printf("Invalid record\r\n\n");
continue;
}
/* Obtiene los bytes a escribir o verificar. */
ptr2 = ptr;
for(i = 0; i < length; i++)
{
val = hex2val(ptr);
ptr += 2;
checksum += val;
}
/* Verifica la suma de verificacin. */
checksum += hex2val(ptr);
ptr += 2;
if (checksum)
{
printf("Checksum error\r\n\n");
continue;
}
/* Escribe o verifica cada byte del registro. */
for(i = 0; i < length; i++)
{
/* Verifica que la posicin de memoria sea vlida. */
if ((((unsigned long int) address) <
((unsigned long int) START_FIRMWARE)) ||
(((unsigned long int) address) >
((unsigned long int) END_FIRMWARE)))
{

FernandoArielBeunza79156

705

Tesis de Grado en Ingeniera Informtica


printf("Invalid address\r\n\n");
continue;
}
/* Escribe un byte del registro. */
val = hex2val(ptr2);
ptr2 += 2;
if (op) writemem(address, val);
/* Verifica un byte del registro. */
if (*((__xdata unsigned char *) address) != val)
{
printf("Error at %04X\r\n", address);
errors ++;
}
/* Actualiza la posicin de memoria. */
address ++;
}
};
/* Devuelve el resultado de la operacin. */
if (errors) printf("%i error(s)\r\n", errors);
}

C.7.10. Archivo boot.c


/*
boot.c:
Cargador del firmware del modem PLC.
*/

/* Archivos includos necesarios. */


#include "config.h"
#include <stdio.h>
#include <at89x52.h>
#include "memory.h"
#include "interrupts.h"
#include "serial.h"
#include "common.h"

/*
Funcin main:
Funcin principal.
*/
void main(void)
{
char str[LINE_SIZE];

/* Lnea de comandos. */

/* Inicializacin del microcontrolador. */


cli();
initports();
inituart(0xff);
init_watchdog(0);
/* Recibe de comandos recibidos por medio de la UART. */
printf("Modem PLC boot\r\n\n");
while(1)
{
/* Lee la lnea de comandos. */
printf("#");
gets(str);
/* Verifica si la lnea de comandos se encuentra vaca. */
if (strceq(str, "")) continue;

706

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Verifica si el comando recibido corresponde
ejecucin del firmware del modem PLC. */
if (strceq(str, "init"))
{
printf("OK\r\n\n");
init();
continue;
}
/* Verifica si el comando recibido corresponde
del cargador del firmware del modem PLC. */
else if (strceq(str, "reset"))
{
printf("OK\r\n\n");
reset();
continue;
}
/* Verifica si el comando recibido corresponde
del modem PLC. */
else if (strceq(str, "erase"))
erase();
/* Verifica si el comando recibido corresponde
firmware del modem PLC. */
else if (strceq(str, "read"))
read();
/* Verifica si el comando recibido corresponde
firmware del modem PLC.*/
else if (strceq(str, "write"))
write();
/* Verifica si el comando recibido corresponde
firmware del modem PLC. */
else if (strceq(str, "verify"))
verify();
/* Verifica si el comando recibido corresponde
memoria. */
else if (strceq(str, "test"))
test();
else
printf("Invalid command\r\n");
printf("OK\r\n");

al inicio de la

a la reinicializacin

al borrado del firmware

a la lectura del

a la escritura del

a la verificacin del

a la prueba del banco de

}
}

C.8. Especificacin del cdigo fuente comn


utilizado por el firmware del modem PLC y el
firmware cargador
En esta seccin se detalla el cdigo fuente comn utilizado por el firmware del modem PLC
y el firmware del cargador compuesto por los siguientes archivos:

Archivo common.h: en este archivo se declaran primitivas con funcionalidades generales.

Archivo common.c: en este archivo se encuentran implementadas las primitivas


declaradas en el archivo common.h.

Archivo serial.h: en este archivo se declaran primitivas con funcionalidades referentes a


la entrada y salida va puerto RS232.

FernandoArielBeunza79156

707

Tesis de Grado en Ingeniera Informtica

Archivo serial.c: en este archivo se encuentran implementadas las primitivas declaradas


en el archivo serial.c.

C.8.1. Archivo common.h


/*
common.h:
Declaracin de funciones comunes.
*/

#if !defined(__COMMON_H__)
#define __COMMON_H__

/* Archivos includos necesarios. */


#include <stdlib.h>

/* Definicin de tipos. */
/* Tipo longitud. */
typedef short int length_t;

/* Definicin de funciones pblicas. */


/*
Funcin usl2b:
Convierte un entero sin signo de 16 bits codificado little endian en otro
codificado en big endian.
*/
unsigned short int usl2b(unsigned short int);
/*
Funcin usb2l:
Convierte un entero sin signo de 16 bits codificado big endian en otro
codificado en little endian.
*/
#define usb2l(val)\
usl2b(val)
/*
Funcin getfcs:
Calcula la suma de verificacin.
*/
unsigned short int getfcs(const void *, length_t);
/*
Funcin memcpy1:
Copia el contenido de la memoria de datos.
*/
void memcpy1(void *, const void *, length_t);
/*
Funcin memccpy1:
Copia el contenido de la memoria de cdigo a la memoria de datos.
*/
void memccpy1(void *, const void *, length_t);
/*
Funcin memcpy2:
Copia el contenido de la memoria de datos.
*/
void memcpy2(void *, length_t, const void *, length_t);
/*

708

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Funcin memccpy2:
Copia el contenido de la memoria de datos.
*/
void memccpy2(void *, length_t, const void *, length_t);
/*
Funcin memcmp1:
Compara el contenido de la memoria de datos.
*/
int memcmp1(const void *, const void *, length_t);
/*
Funcin memccmp1:
Compara el contenido de la memoria de cdigo a la memoria de datos.
*/
int memccmp1(const void *, const void *, length_t);
/*
Funcin streq:
Verifica si dos cadenas de caracteres en memoria de datos son iguales.
*/
int streq(const char *, const char *);
/*
Funcin strceq:
Verifica si una cadena de caracteres en memoria de datos y una cadena de
caracteres en memoria de cdigo son iguales.
*/
int strceq(const char *, const char *);
/*
Funcin strlen1:
Devuelve la longitud de una cadena de caracteres en memoria de datos.
*/
length_t strlen1(const char *);
/*
Funcin strlen1:
Devuelve la longitud de una cadena de caracteres en memoria de cdigo.
*/
length_t strclen1(const char *);
/*
Funcin sei:
Activa interrupciones.
*/
#define sei()\
__asm setb EA __endasm
/*
Funcin cli:
Desactiva interrupciones.
*/
#define cli()\
__asm clr EA __endasm
/*
Funcin reset:
Reinicia la ejecucin del cargador de firmware del modem PLC.
*/
void reset(void);
/*
Funcin initports:
Inicializa los puertos.
*/
void initports(void);
/*
Funcin idle:
Detiene la ejecucin del firmware del modem PLC.

FernandoArielBeunza79156

709

Tesis de Grado en Ingeniera Informtica


*/
#define idle()\
PCON |= 0x01
/*
Funcin init_watchdog:
Inicializa el watchdog del microcontrolador.
*/
void init_watchdog(unsigned char);
/*
Funcin reset_watchdog:
Reinicia el watchdog del microcontrolador.
*/
void reset_watchdog(void);
/*
Funcin status_watchdog:
Devuelve el estado del watchdog del microcontrolador.
*/
unsigned char status_watchdog(void);

#endif

C.8.2. Archivo common.c


/*
common.c:
Implementacin de funciones comunes.
*/

/* Archivos includos necesarios. */


#include <string.h>
#include <stdlib.h>
#include "common.h"

/* Definicin de SFR necesarias. */


__sfr __at (0xa7) WDTPRG;
__sfr __at (0xa6) WDTRST;

/* Configuracin del watchdog. */


/* Control del watchdog. */

/* Definicin de constantes. */
#define WATCHDOG_PERIOD

0x000f

/* Variables globales. */
/* Estado del watchdog. */
static unsigned char __wdt_status__;

/* Declaracin de funciones privadas. */


static unsigned short int crc16_update(unsigned short int, unsigned char);
static void memcpy3(unsigned char *, length_t, const unsigned char *,
length_t);
static void memccpy3(unsigned char *, length_t, const unsigned char *,
length_t);
static int memcmp2(const unsigned char *, const unsigned char *, length_t);
static int memccmp2(const unsigned char *, const unsigned char *, length_t);

/* Implementacin de funciones pblicas. */


/*
Funcin usl2b:
Convierte un entero sin signo de 16 bits codificado little endian en otro

710

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


codificado en big endian.
*/
unsigned short int usl2b(unsigned short int val)
{
return (val << 8) | (val >> 8);
}
/*
Funcin getfcs:
Calcula la suma de verificacin.
*/
unsigned short int getfcs(const void *dat, length_t len)
{
/* Variables. */
unsigned short int fcs;
unsigned char *ptr;

/* Suma de verificacin. */
/* Puntero a los datos. */

/* Calcula la suma de verificacin. */


fcs = 0;
ptr = (unsigned char *) dat;
#if defined SDCC_MODEL_SMALL
while(len--)
{
fcs = crc16_update(fcs, *((__data unsigned char *) (ptr++)));
reset_watchdog();
}
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
while(len--)
{
fcs = crc16_update(fcs, *((__xdata unsigned char *) (ptr++)));
reset_watchdog();
}
#else
#error "getfcs(): unknow memory model"
#endif
/* Devuelve la suma de verificacin. */
return fcs;
}
/*
Funcin memcpy1:
Copia el contenido de la memoria de datos.
*/
void memcpy1(void *dest, const void *src, length_t ssrc)
{
memcpy2(dest, ssrc, src, ssrc);
}
/*
Funcin memccpy1:
Copia el contenido de la memoria de cdigo a la memoria de datos.
*/
void memccpy1(void *dest, const void *src, length_t ssrc)
{
memccpy2(dest, ssrc, src, ssrc);
}
/*
Funcin memcpy2:
Copia el contenido de la memoria de datos.
*/
void memcpy2(void *dest, length_t sdest, const void *src, length_t ssrc)
{
memcpy3(dest, sdest, src, ssrc);
}
/*
Funcin memccpy2:
Copia el contenido de la memoria de cdigo a la memoria de datos.

FernandoArielBeunza79156

711

Tesis de Grado en Ingeniera Informtica


*/
void memccpy2(void *dest, length_t sdest, const void *src, length_t ssrc)
{
memccpy3(dest, sdest, src, ssrc);
}
/*
Funcin memcmp1:
Compara el contenido de la memoria de datos.
*/
int memcmp1(const void *mem1, const void *mem2, length_t size)
{
return memcmp2(mem1, mem2, size);
}
/*
Funcin memccmp1:
Compara el contenido de la memoria de cdigo a la memoria de datos.
*/
int memccmp1(const void *mem1, const void *mem2, length_t size)
{
return memccmp2(mem1, mem2, size);
}
/*
Funcin streq:
Verifica si dos cadenas de caracteres en memoria de datos son iguales.
*/
int streq(const char *str1, const char *str2)
{
/* Variables. */
int result;
length_t i;
char b1;
char b2;

/*
/*
/*
/*

Resultado de la comparacin. */
Contador. */
Caracter de la primer cadena. */
Caracter de la segunda
cadena. */

/* Compara ambas cadenas de caracteres. */


result = 0;
for(i = 0;; i++)
{
#if defined SDCC_MODEL_SMALL
b1 = *((__data char *) (str1 + i));
b2 = *((__data char *) (str2 + i));
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
b1 = *((__xdata char *) (str1 + i));
b2 = *((__xdata char *) (str2 + i));
#else
#error "streq(): unknow memory model"
#endif
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
if ((b1 == 0) && (b2 == 0))
{
result = 1;
break;
}
if ((b1 == 0) || (b2 == 0)) break;
if (b1 != b2) break;
}
reset_watchdog();
return result;
}
/*
Funcin strceq:
Verifica si una cadena de caracteres en memoria de datos y una cadena de
caracteres en memoria de cdigo son iguales.
*/
int strceq(const char *strd, const char *strc)
{

712

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Variables. */
int result;
char bd;
char bc;
length_t i;

/* Resultado de la comparacin. */
/* Caracter de la cadena en memoria
de datos. */
/* Caracter de la cadena en memoria
de cdigo. */
/* Contador. */

/* Compara ambas cadenas de caracteres. */


result = 0;
for(i = 0;; i++)
{
#if defined SDCC_MODEL_SMALL
bd = *((__data char *) (strd + i));
bc = *((__code char *) (strc + i));
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
bd = *((__xdata char *) (strd + i));
bc = *((__code char *) (strc + i));
#else
#error "strceq(): unknow memory model"
#endif
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
if ((bd == 0) && (bc == 0))
{
result = 1;
break;
}
if ((bd == 0) || (bc == 0)) break;
if (bd != bc) break;
}
reset_watchdog();
return result;
}
/*
Funcin strlen1:
Devuelve la longitud de una cadena de caracteres en memoria de datos.
*/
length_t strlen1(const char *str)
{
/* Variables. */
length_t len;

/* Longitud de la cadena de
caracteres. */

/* Obtiene la longitud de la cadena de caracteres. */


len = 0;
#if defined SDCC_MODEL_SMALL
while(*((__data char *) (str + len)) != 0)
{
if (!(len & WATCHDOG_PERIOD)) reset_watchdog();
len ++;
}
reset_watchdog();
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
while(*((__xdata char *) (str + len)) != 0)
{
if (!(len & WATCHDOG_PERIOD)) reset_watchdog();
len ++;
}
reset_watchdog();
#else
#error "strlen1(): unknow memory model"
#endif
/* Devuelve la longitud de la cadena de caracteres. */
return len;
}
/*

FernandoArielBeunza79156

713

Tesis de Grado en Ingeniera Informtica


Funcin strlen1:
Devuelve la longitud de una cadena de caracteres en memoria de cdigo.
*/
length_t strclen1(const char *str)
{
/* Variables. */
length_t len;

/* Longitud de la cadena de
caracteres. */

/* Obtiene la longitud de la cadena de caracteres. */


len = 0;
while(*((__code char *) (str + len)) != 0)
{
len ++;
if (!(len & WATCHDOG_PERIOD)) reset_watchdog();
}
/* Devuelve la longitud de la cadena de caracteres. */
return len;
}
/*
Funcin reset:
Reinicia la ejecucin del cargador de firmware del modem PLC.
*/
void reset(void)
{
init_watchdog(1);
while(1);
}
/*
Funcin initports:
Inicializa los puertos.
*/
void initports(void)
{
__asm
mov
mov
mov
mov

p0,
p1,
p2,
p3,

#0xff
#0xff
#0xff
#0xff

;
;
;
;

__endasm;
}
/*
Funcin init_watchdog:
Inicializa el watchdog del microcontrolador.
*/
void init_watchdog(unsigned char s)
{
if (!s)
{
__wdt_status__ = 0;
return;
}
__wdt_status__ = 1;
__asm
push
IE
clr
EA
orl
_WDTPRG, #0x07
mov
_WDTRST, #0x1e
mov
_WDTRST, #0xe1
pop
IE
__endasm;
}

;
;
;
;
;
;

/*
Funcin reset_watchdog:
Reinicia el watchdog del microcontrolador.

714

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/
void reset_watchdog(void)
{
if (!__wdt_status__) return;
__asm
push
IE
clr
EA
mov
_WDTRST, #0x1e
mov
_WDTRST, #0xe1
pop
IE
__endasm;
}

;
;
;
;
;

/*
Funcin status_watchdog:
Devuelve el estado del watchdog del microcontrolador.
*/
unsigned char status_watchdog(void)
{
if (__wdt_status__) return 1;
return 0;
}

/* Implementacin de funciones privadas. */


/*
Funcin crc16_update:
Calcula el CRC-16.
*/
static unsigned short int crc16_update(unsigned short int crc, unsigned char a)
{
/* Variables. */
int i;
/* Contador. */

/* Calcula el CRC-16. */
crc ^= a;
for (i = 0; i < 8; i++)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
/* Devuelve el CRC-16. */
return crc;
}
/*
Funcin memcpy3:
Copia el contenido de la memoria de datos.
*/
void memcpy3(unsigned char *dest, length_t sdest, const unsigned char *src,
length_t ssrc)
{
/* Variables. */
length_t i;
/* Contador. */

/* Copia el contenido de la memoria. */


if (sdest > ssrc) sdest = ssrc;
#if defined SDCC_MODEL_SMALL
for(i = 0; i < sdest; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
*((__data unsigned char *) (dest + i)) =
*((__data unsigned char *) (src + i));
}
reset_watchdog();

FernandoArielBeunza79156

715

Tesis de Grado en Ingeniera Informtica


#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
for(i = 0; i < sdest; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
*((__xdata unsigned char *) (dest + i)) =
*((__xdata unsigned char *) (src + i));
}
reset_watchdog();
#else
#error "memcpy3(): unknow memory model"
#endif
}
/*
Funcin memccpy3:
Copia el contenido de la memoria de cdigo a la memoria de datos.
*/
static void memccpy3(unsigned char *dest, length_t sdest,
const unsigned char *src, length_t ssrc)
{
/* Variables. */
length_t i;
/* Contador. */

/* Copia el contenido de la memoria. */


if (sdest > ssrc) sdest = ssrc;
#if defined SDCC_MODEL_SMALL
for(i = 0; i < sdest; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
*((__data unsigned char *) (dest + i)) =
*((__code unsigned char *) (src + i));
}
reset_watchdog();
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
for(i = 0; i < sdest; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
*((__xdata unsigned char *) (dest + i)) =
*((__code unsigned char *) (src + i));
}
reset_watchdog();
#else
#error "memccpy3(): unknow memory model"
#endif
}
/*
Funcin memcmp2:
Compara el contenido de la memoria de datos.
*/
static int memcmp2(const unsigned char *mem1, const unsigned char *mem2,
length_t size)
{
/* Variables. */
length_t i;
/* Contador. */

/* Copia el contenido de la memoria. */


#if defined SDCC_MODEL_SMALL
for(i = 0; i < size; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
if (*((__data unsigned char *) (mem1 + i)) !=
*((__data unsigned char *) (mem2 + i)))
return 0;
}
reset_watchdog();
return 1;
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
for(i = 0; i < size; i++)

716

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
if (*((__xdata unsigned char *) (mem1 + i)) !=
*((__xdata unsigned char *) (mem2 + i)))
return 0;
}
reset_watchdog();
return 1;
#else
#error "memcmp2(): unknow memory model"
#endif
}
/*
Funcin memccmp2:
Compara el contenido de la memoria de cdigo a la memoria de datos.
*/
static int memccmp2(const unsigned char *mem1, const unsigned char *mem2,
length_t size)
{
/* Variables. */
length_t i;
/* Contador. */

/* Copia el contenido de la memoria. */


#if defined SDCC_MODEL_SMALL
for(i = 0; i < size; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
if (*((__data unsigned char *) (mem1 + i)) !=
*((__code unsigned char *) (mem2 + i)))
return 0;
}
reset_watchdog();
return 1;
#elif (defined SDCC_MODEL_LARGE) || (defined SDCC_MODEL_MEDIUM)
for(i = 0; i < size; i++)
{
if (!(i & WATCHDOG_PERIOD)) reset_watchdog();
if (*((__xdata unsigned char *) (mem1 + i)) !=
*((__code unsigned char *) (mem2 + i)))
return 0;
}
reset_watchdog();
return 1;
#else
#error "memccmp2(): unknow memory model"
#endif
}

C.8.3. Archivo serial.h


/*
serial.h:
Declaracin de funciones referentes a la UART.
*/

#if !defined(__SERIAL_H__)
#define __SERIAL_H__

/* Definicin de funciones pblicas. */


/*
Funcin inituart:
Inicializa la UART del microcontrolador.
*/

FernandoArielBeunza79156

717

Tesis de Grado en Ingeniera Informtica


void inituart(unsigned char);
/*
Funcin putchar:
Enva un caracter a travs de la UART.
*/
void putchar(char);
/*
Funcin poll:
Devuelve si hay un caracter almacenado en la UART.
*/
int poll(void);
/*
Funcin getchar:
Devuelve un caracter recibido por medio de la UART.
*/
char getchar(void);

#endif

C.8.4. Archivo serial.c


/*
serial.c:
Implementacin de funciones referentes a la UART.
*/

/* Archivos includos necesarios. */


#include "common.h"

/* Definicin de SFR necesarias. */


__sfr __at (0x87) SIO_PCON;
__sfr __at (0x89) SIO_TMOD;
__sfr __at (0x8D) SIO_TH1;
__sfr __at (0x8B) SIO_TL1;
__sfr __at (0x98) SIO_SCON;
__sfr __at (0x99) SIO_SBUF;
__sbit __at (0x8E) SIO_TR1;
__sbit __at (0x98) SIO_RI;
__sbit __at (0x99) SIO_TI;
__sbit __at (0x9A) SIO_RB8;
__sbit __at (0x9B) SIO_TB8;
__sbit __at (0x9C) SIO_REN;
__sbit __at (0x9D) SIO_SM2;
__sbit __at (0x9E) SIO_SM1;
__sbit __at (0x9F) SIO_SM0;

/* Variables globales. */
/* Contador de reinicio del watchdog. */
static unsigned char __watchdog_counter__;

/*
Funcin inituart:
Inicializa la UART del microcontrolador.
*/
void inituart(unsigned char t1_reload)
{
/* Inicializa la UART. */
SIO_SCON = 0x50;
SIO_TR1 = 0;

718

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


SIO_TMOD = (SIO_TMOD & 0x0f) | 0x20;
SIO_PCON |= 0x80;
SIO_TH1 = t1_reload;
SIO_TR1 = 1;
SIO_TI = 1;
/* Inicializa el contador de reinicio del watchdog. */
__watchdog_counter__ = 0;
}
/*
Funcin putchar:
Enva un caracter a travs de la UART.
*/
void putchar(char c)
{
if ((status_watchdog()) && (!__watchdog_counter__))
{
reset_watchdog();
while(!SIO_TI);
}
else
while(!SIO_TI);
SIO_TI = 0;
SIO_SBUF = c;
__watchdog_counter__ ++;
}
/*
Funcin poll:
Devuelve si hay un caracter almacenado en la UART.
*/
int poll(void)
{
return SIO_RI;
}
/*
Funcin getchar:
Devuelve un caracter recibido por medio de la UART.
*/
char getchar(void)
{
/* Varaibles. */
char c;

/* Caracter recibido. */

/* Recibe un caracter por medio de la UART. */


if (status_watchdog())
{
while(!poll()) reset_watchdog();
}
else
while(!poll());
SIO_RI = 0;
c = SIO_SBUF;
/* Devuelve el caracter recibido. */
return c;
}

FernandoArielBeunza79156

719

Tesis de Grado en Ingeniera Informtica

720

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice D: Interfaz C++


En el presente apndice se detalla la interfaz C++ constituida por una biblioteca de clases.
Junto con la declaracin de las clases se especifica el cdigo fuente que implementa cada uno de los
mtodos pertenecientes a las clases mencionadas.

D.1. Descripcin
La interfaz C++ es una extensin de la capa de aplicacin que permite proveer a las
aplicaciones orientadas a objetos desarrolladas en lenguaje C++, los mismos servicios brindados a
aplicaciones escritas en lenguaje C. El sistema se encuentra desarrollado en lenguaje C, ya que
permite implementar los distintos componentes del sistema de comunicaciones en diversas
plataformas de forma eficiente. De todas formas, el sistema se encuentra diseado para aceptar el
agregado de interfaces que permitan adaptar la interfaz de la capa de aplicacin a otros entornos y
lenguajes de programacin. En ste caso se hace referencia al lenguaje C++, porque es el
implementado en el presente trabajo, y utilizado para mostrar la caracterstica anterior de diseo,
pero nada impide que en un futuro se desarrollen extensiones a otros lenguajes.
La interfaz se encuentra desarrollada tanto para Windows como para Linux, del mismo modo
que las capas de aplicacin y presentacin. No se encuentra desarrollada una plataforma para
AT89X5X ya que resulta poco prctica para el microcontrolador propuesto para el dispositivo
cliente, pero nada impide que en el futuro tambin se desarrolle una interfaz C++ para determinados
tipos de microcontroladores cuyo poder de computo absorban el costo adicional de C++.

D.2. Cdigo fuente


La interfaz C++ se compone de dos clases asociadas a los tipos de datos estructurados
ofrecidos por la interfaz de la capa de aplicacin. Una de las clases se encarga del manejo de la
conexin, mientras que la otra maneja los mensajes que se enva y reciben. La interfaz permite
adaptar, la interfaz de la capa de aplicacin provista por el sistema de comunicaciones, al modelo de
objetos del lenguaje C++, para que aplicaciones desarrolladas en el lenguaje anterior puedan
tambin utilizar los servicios provistos por el sistema desarrollado en ste trabajo. A continuacin se
presenta el cdigo fuente asociado a la interfaz C++ para plataforma Windows y Linux.

D.2.1. Archivo modplcapcpp.h (plataforma Windows)


/*
modplcapcpp.h:
Declaracin de funciones referentes a la interfaz de la capa de aplicacin
del modem PLC.
*/

#if !defined(__MODPLCAPCPP_H__)
#define __MODPLCAPCPP_H__

/* Archivos includos necesarios. */

FernandoArielBeunza79156

721

Tesis de Grado en Ingeniera Informtica


#include "..\modplcap\modplcap.h"

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcapcpp_grpid;
/* Identificador de mensaje. */
typedef unsigned short int modplcapcpp_msgid;
/* Tipo de campo. */
typedef unsigned char modplcapcpp_ftype;

/* Definicin de constantes. */
/* Tipos de datos. */
#define MODPLCAPCPP_NULLTYPE
#define MODPLCAPCPP_CHARTYPE
#define MODPLCAPCPP_SINT8TYPE
#define MODPLCAPCPP_UINT8TYPE
#define MODPLCAPCPP_SINT16TYPE
#define MODPLCAPCPP_UINT16TYPE
#define MODPLCAPCPP_SINT32TYPE
#define MODPLCAPCPP_UINT32TYPE
#define MODPLCAPCPP_FLOATTYPE

MODPLCAP_NULLTYPE
MODPLCAP_CHARTYPE
MODPLCAP_SINT8TYPE
MODPLCAP_UINT8TYPE
MODPLCAP_SINT16TYPE
MODPLCAP_UINT16TYPE
MODPLCAP_SINT32TYPE
MODPLCAP_UINT32TYPE
MODPLCAP_FLOATTYPE

/* Variables globales. */
/* Indicador de carga de biblioteca dinmica. */
int __modplcapcpp_loadlib__ = 0;

/* Declaracin de clases. */
/* Clases declaradas. */
class modplcapcpp;
class modplcapcpp_msg;
/*
Clase modplcapcpp
*/
class modplcapcpp
{
/* Atributos y mtodos privados. */
private:
modplcap_hd *handle;

/* Manejador de capa de
aplicacin. */

/* Mtodos pblicos. */
public:
/*
Constructor:
Inicializa los recursos utilizados por la capa de aplicacin del
modem PLC.
*/
modplcapcpp(int);
/*
Destructor:
Libera los recursos utilizados por la capa de aplicacin del modem
PLC.
*/
~modplcapcpp();
/*
Mtodo publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.

722

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/
int publish(modplcapcpp_grpid);
/*
Mtodo subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
int subscribe(modplcapcpp_grpid);
/*
Mtodo leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
int leave(modplcapcpp_grpid);
/*
Mtodo poll:
Verifica la llegada de un nuevo mensaje.
*/
int poll(void);
/*
Mtodo status:
Devuelve el estado del modem PLC.
*/
int status(void);
/* Clases amigas. */
friend class modplcapcpp_msg;
};
/*
Clase modplcapcpp_msg
*/
class modplcapcpp_msg
{
/* Atributos y mtodos privados. */
private:
modplcap_msg *msghd;

/* Manejador de mensaje. */

/* Mtodos pblicos. */
public:
/*
Constructor:
Crea un nuevo mensaje.
*/
modplcapcpp_msg(modplcapcpp *, modplcapcpp_grpid, modplcapcpp_msgid);
/*
Constructor:
Crea un copia de un mensaje.
*/
modplcapcpp_msg(modplcapcpp_msg *msg);
/*
Constructor:
Recibe un mensaje por medio de la capa de aplicacin.
*/
modplcapcpp_msg(modplcapcpp *hd);
/*
Destructor:
Destruye un mensaje.
*/
~modplcapcpp_msg();
/*
Mtodo putfield:
Agrega un nuevo campo al mensaje.
*/

FernandoArielBeunza79156

723

Tesis de Grado en Ingeniera Informtica


int putfield(modplcapcpp_ftype, unsigned char, const void *);
/*
Mtodo sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
int sendmsg(void);
/*
Mtodo getfield:
Extrae un campo del mensaje.
*/
int getfield(modplcapcpp_ftype *, unsigned char *, void *);
/*
Mtodo getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcapcpp_grpid getgrpid(void);
/*
Mtodo getmsgid:
Devuelve el identificador de mensaje.
*/
modplcapcpp_msgid getmsgid(void);
};

/* Implementacin de mtodos de la clase modplcapcpp. */


/*
Constructor:
Inicializa los recursos utilizados por la capa de aplicacin del modem PLC.
*/
inline modplcapcpp::modplcapcpp(int sid)
{
if (!__modplcapcpp_loadlib__)
{
modplcap_loadlib();
__modplcapcpp_loadlib__ = 1;
}
this->handle = modplcap_init(sid);
}
/*
Destructor:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
inline modplcapcpp::~modplcapcpp()
{
modplcap_release(this->handle);
}
/*
Mtodo publish:
Registra el dispositivo como publicador del grupo de difusin especificado.
*/
inline int modplcapcpp::publish(modplcapcpp_grpid grpid)
{
return modplcap_publish(this->handle, (modplcap_grpid)grpid);
}
/*
Mtodo subscribe:
Registra el dispositivo como suscriptor del grupo de difusin especificado.
*/
inline int modplcapcpp::subscribe(modplcapcpp_grpid grpid)
{
return modplcap_subscribe(this->handle, (modplcap_grpid) grpid);
}

724

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/*
Mtodo leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
inline int modplcapcpp::leave(modplcapcpp_grpid grpid)
{
return modplcap_leave(this->handle, (modplcap_grpid) grpid);
}
/*
Mtodo poll:
Verifica la llegada de un nuevo mensaje.
*/
inline int modplcapcpp::poll(void)
{
return modplcap_poll(this->handle);
}
/*
Mtodo status:
Devuelve el estado del modem PLC.
*/
inline int modplcapcpp::status(void)
{
return modplcap_status(this->handle);
}

/* Implementacin de mtodos de la clase modplcapcpp_msg. */


/*
Constructor:
Crea un nuevo mensaje.
*/
inline modplcapcpp_msg::modplcapcpp_msg(modplcapcpp *hd,
modplcapcpp_grpid grpid,
modplcapcpp_msgid msgid)
{
if (!__modplcapcpp_loadlib__)
{
modplcap_loadlib();
__modplcapcpp_loadlib__ = 1;
}
this->msghd = new modplcap_msg;
if (!this->msghd) return;
modplcap_newmsg(hd->handle, (modplcap_msg *) (this->msghd),
(modplcap_grpid) grpid, (modplcap_msgid) msgid);
}
/*
Constructor:
Crea un copia de un mensaje.
*/
inline modplcapcpp_msg::modplcapcpp_msg(modplcapcpp_msg *msg)
{
if (!__modplcapcpp_loadlib__)
{
modplcap_loadlib();
__modplcapcpp_loadlib__ = 1;
}
this->msghd = new modplcap_msg;
if (!this->msghd) return;
if (!modplcap_copymsg(this->msghd, msg->msghd))
delete this->msghd;
}
/*
Constructor:
Recibe un mensaje por medio de la capa de aplicacin.
*/
inline modplcapcpp_msg::modplcapcpp_msg(modplcapcpp *hd)

FernandoArielBeunza79156

725

Tesis de Grado en Ingeniera Informtica


{
if (!__modplcapcpp_loadlib__)
{
modplcap_loadlib();
__modplcapcpp_loadlib__ = 1;
}
this->msghd = new modplcap_msg;
if (!this->msghd) return;
if (!modplcap_receivemsg(hd->handle, this->msghd))
delete this->msghd;
}
/*
Destructor:
Destruye un mensaje.
*/
inline modplcapcpp_msg::~modplcapcpp_msg()
{
if (!this->msghd) return;
modplcap_destroymsg(this->msghd);
delete this->msghd;
}
/*
Mtodo putfield:
Agrega un nuevo campo al mensaje.
*/
inline int modplcapcpp_msg::putfield(modplcapcpp_ftype type,
unsigned char count, const void *dat)
{
return modplcap_putfield(this->msghd, (modplcap_ftype) type, count, dat);
}
/*
Mtodo sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
inline int modplcapcpp_msg::sendmsg(void)
{
return modplcap_sendmsg(this->msghd);
}
/*
Mtodo getfield:
Extrae un campo del mensaje.
*/
inline int modplcapcpp_msg::getfield(modplcapcpp_ftype *type,
unsigned char *count, void *dat)
{
return modplcap_getfield(this->msghd, (modplcap_ftype *) type, count, dat);
}
/*
Mtodo getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
inline modplcapcpp_grpid modplcapcpp_msg::getgrpid(void)
{
return (modplcap_grpid) modplcap_getgrpid(this->msghd);
}
/*
Mtodo getmsgid:
Devuelve el identificador de mensaje.
*/
inline modplcapcpp_msgid modplcapcpp_msg::getmsgid(void)
{
return (modplcap_msgid) modplcap_getmsgid(this->msghd);
}

726

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


#endif

D.2.2. Archivo modplcapcpp.h (plataforma Linux)


/*
modplcapcpp.h:
Declaracin de funciones referentes a la interfaz de la capa de
aplicacin del modem PLC.
*/

#if !defined(__MODPLCAPCPP_H__)
#define __MODPLCAPCPP_H__

/* Archivos includos necesarios. */


#ifdef __cplusplus
extern "C" {
#include "../modplcap/modplcap.h"
}
#else
#include "../modplcap/modplcap.h"
#endif

/* Definicin de tipos. */
/* Identificador de grupo. */
typedef unsigned char modplcapcpp_grpid;
/* Identificador de mensaje. */
typedef unsigned short int modplcapcpp_msgid;
/* Tipo de campo. */
typedef unsigned char modplcapcpp_ftype;

/* Definicin de constantes. */
/* Tipos de datos. */
#define MODPLCAPCPP_NULLTYPE
#define MODPLCAPCPP_CHARTYPE
#define MODPLCAPCPP_SINT8TYPE
#define MODPLCAPCPP_UINT8TYPE
#define MODPLCAPCPP_SINT16TYPE
#define MODPLCAPCPP_UINT16TYPE
#define MODPLCAPCPP_SINT32TYPE
#define MODPLCAPCPP_UINT32TYPE
#define MODPLCAPCPP_FLOATTYPE

MODPLCAP_NULLTYPE
MODPLCAP_CHARTYPE
MODPLCAP_SINT8TYPE
MODPLCAP_UINT8TYPE
MODPLCAP_SINT16TYPE
MODPLCAP_UINT16TYPE
MODPLCAP_SINT32TYPE
MODPLCAP_UINT32TYPE
MODPLCAP_FLOATTYPE

/* Declaracin de clases. */
/* Clases declaradas. */
class modplcapcpp;
class modplcapcpp_msg;
/*
Clase modplcapcpp
*/
class modplcapcpp
{
/* Atributos y mtodos privados. */
private:
modplcap_hd *handle;

/* Manejador de capa de
aplicacin. */

/* Mtodos pblicos. */

FernandoArielBeunza79156

727

Tesis de Grado en Ingeniera Informtica


public:
/*
Constructor:
Inicializa los recursos utilizados por la capa de
aplicacin del modem PLC.
*/
modplcapcpp(int);
/*
Destructor:
Libera los recursos utilizados por la capa de
aplicacin del modem PLC.
*/
~modplcapcpp();
/*
Mtodo publish:
Registra el dispositivo como publicador del grupo de
difusin especificado.
*/
int publish(modplcapcpp_grpid);
/*
Mtodo subscribe:
Registra el dispositivo como suscriptor del grupo de
difusin especificado.
*/
int subscribe(modplcapcpp_grpid);
/*
Mtodo leave:
Desvincula el dispositivo del grupo de difusin
especificado.
*/
int leave(modplcapcpp_grpid);
/*
Mtodo poll:
Verifica la llegada de un nuevo mensaje.
*/
int poll(void);
/*
Mtodo status:
Devuelve el estado del modem PLC.
*/
int status(void);
/* Clases amigas. */
friend class modplcapcpp_msg;
};
/*
Clase modplcapcpp_msg
*/
class modplcapcpp_msg
{
/* Atributos y mtodos privados. */
private:
modplcap_msg *msghd;

/* Manejador de mensaje. */

/* Mtodos pblicos. */
public:
/*
Constructor:
Crea un nuevo mensaje.
*/
modplcapcpp_msg(modplcapcpp *, modplcapcpp_grpid,
modplcapcpp_msgid);
/*

728

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Constructor:
Crea un copia de un mensaje.
*/
modplcapcpp_msg(modplcapcpp_msg *msg);
/*
Constructor:
Recibe un mensaje por medio de la capa de aplicacin.
*/
modplcapcpp_msg(modplcapcpp *hd);
/*
Destructor:
Destruye un mensaje.
*/
~modplcapcpp_msg();
/*
Mtodo putfield:
Agrega un nuevo campo al mensaje.
*/
int putfield(modplcapcpp_ftype, unsigned char, const void *);
/*
Mtodo sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
int sendmsg(void);
/*
Mtodo getfield:
Extrae un campo del mensaje.
*/
int getfield(modplcapcpp_ftype *, unsigned char *, void *);
/*
Mtodo getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
modplcapcpp_grpid getgrpid(void);
/*
Mtodo getmsgid:
Devuelve el identificador de mensaje.
*/
modplcapcpp_msgid getmsgid(void);
};

/* Implementacin de mtodos de la clase modplcapcpp. */


/*
Constructor:
Inicializa los recursos utilizados por la capa de aplicacin del modem
PLC.
*/
inline modplcapcpp::modplcapcpp(int sid)
{
this->handle = modplcap_init(sid);
}
/*
Destructor:
Libera los recursos utilizados por la capa de aplicacin del modem PLC.
*/
inline modplcapcpp::~modplcapcpp()
{
modplcap_release(this->handle);
}
/*

FernandoArielBeunza79156

729

Tesis de Grado en Ingeniera Informtica


Mtodo publish:
Registra el dispositivo como publicador del grupo de difusin
especificado.
*/
inline int modplcapcpp::publish(modplcapcpp_grpid grpid)
{
return modplcap_publish(this->handle, (modplcap_grpid)grpid);
}
/*
Mtodo subscribe:
Registra el dispositivo como suscriptor del grupo de difusin
especificado.
*/
inline int modplcapcpp::subscribe(modplcapcpp_grpid grpid)
{
return modplcap_subscribe(this->handle, (modplcap_grpid) grpid);
}
/*
Mtodo leave:
Desvincula el dispositivo del grupo de difusin especificado.
*/
inline int modplcapcpp::leave(modplcapcpp_grpid grpid)
{
return modplcap_leave(this->handle, (modplcap_grpid) grpid);
}
/*
Mtodo poll:
Verifica la llegada de un nuevo mensaje.
*/
inline int modplcapcpp::poll(void)
{
return modplcap_poll(this->handle);
}
/*
Mtodo status:
Devuelve el estado del modem PLC.
*/
inline int modplcapcpp::status(void)
{
return modplcap_status(this->handle);
}

/* Implementacin de mtodos de la clase modplcapcpp_msg. */


/*
Constructor:
Crea un nuevo mensaje.
*/
inline modplcapcpp_msg::modplcapcpp_msg(modplcapcpp *hd,
modplcapcpp_grpid grpid,
modplcapcpp_msgid msgid)
{
this->msghd = new modplcap_msg;
if (!this->msghd) return;
modplcap_newmsg(hd->handle, (modplcap_msg *) (this->msghd),
(modplcap_grpid) grpid, (modplcap_msgid) msgid);
}
/*
Constructor:
Crea un copia de un mensaje.
*/
inline modplcapcpp_msg::modplcapcpp_msg(modplcapcpp_msg *msg)
{
this->msghd = new modplcap_msg;
if (!this->msghd) return;

730

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


if (!modplcap_copymsg(this->msghd, msg->msghd))
delete this->msghd;
}
/*
Constructor:
Recibe un mensaje por medio de la capa de aplicacin.
*/
inline modplcapcpp_msg::modplcapcpp_msg(modplcapcpp *hd)
{
this->msghd = new modplcap_msg;
if (!this->msghd) return;
if (!modplcap_receivemsg(hd->handle, this->msghd))
delete this->msghd;
}
/*
Destructor:
Destruye un mensaje.
*/
inline modplcapcpp_msg::~modplcapcpp_msg()
{
if (!this->msghd) return;
modplcap_destroymsg(this->msghd);
delete this->msghd;
}
/*
Mtodo putfield:
Agrega un nuevo campo al mensaje.
*/
inline int modplcapcpp_msg::putfield(modplcapcpp_ftype type,
unsigned char count, const void *dat)
{
return modplcap_putfield(this->msghd, (modplcap_ftype) type, count,
dat);
}
/*
Mtodo sendmsg:
Enva un mensaje por medio de la capa de aplicacin.
*/
inline int modplcapcpp_msg::sendmsg(void)
{
return modplcap_sendmsg(this->msghd);
}
/*
Mtodo getfield:
Extrae un campo del mensaje.
*/
inline int modplcapcpp_msg::getfield(modplcapcpp_ftype *type,
unsigned char *count, void *dat)
{
return modplcap_getfield(this->msghd, (modplcap_ftype *) type, count,
dat);
}
/*
Mtodo getgrpid:
Devuelve el identificador de grupo del mensaje.
*/
inline modplcapcpp_grpid modplcapcpp_msg::getgrpid(void)
{
return (modplcap_grpid) modplcap_getgrpid(this->msghd);
}
/*
Mtodo getmsgid:
Devuelve el identificador de mensaje.
*/

FernandoArielBeunza79156

731

Tesis de Grado en Ingeniera Informtica


inline modplcapcpp_msgid modplcapcpp_msg::getmsgid(void)
{
return (modplcap_msgid) modplcap_getmsgid(this->msghd);
}

#endif

732

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice E: Interfaz Simulink


En el ste apndice se describe y detalla la interfaz Simulink conformada por una biblioteca
de bloques. Tambin se detalla el cdigo fuente asociado a la implementacin de la mencionada
biblioteca de bloques.

E.1. Descripcin
La interfaz para el entorno Simulink es una extensin de la capa de aplicacin que permite un
uso ms interactivo de las comunicaciones a travs de la red PLC. La capa de aplicacin provee una
interfaz apropiada para entornos de programacin en donde se implementan algoritmos que hacen
uso de la red PLC, lo que resulta cmodo para usuarios con conocimientos de programacin. Para
usuario sin ste tipo de conocimiento resulta ms adecuado la utilizacin de un entorno grfico que
permita representar algoritmos en forma de modelos grficos. Simulink es una herramienta incluida
dentro de MATLAB que permite la modelizacin grfica de sistemas de control mediante la
interconexin de bloques funcionales. La interfaz Simulink diseada en el presente trabajo provee
una biblioteca de bloques Simulink que permiten agregar las funcionalidades de comunicacin por
medio de redes PLC a cualquier modelo de control realizado en Simulink.

E.2. Biblioteca de bloques Simulink


La biblioteca de bloques funcionales es un conjunto de bloques que proveen bsicamente las
funciones de conexin al modem PLC, envo y recepcin de mensajes. Los bloques que proveen
dichas funciones bsicas, independientemente de la funcionalidad que cumplen, cuentan con dos
salidas: una asociada al manejador de la conexin y otra un indicador de resultado de la operacin
llevada a cabo por el bloque. Salvo uno de los bloques encargado de la conexin al modem PLC, el
resto cuenta tambin con dos entradas tambin asociadas al manejador de la conexin y al resultado
de la operacin realizada por el bloque predecesor. El motivo de sto se debe a que cualquier
operacin de comunicacin necesita del manejador de conexin y tambin es necesario conocer
como se llev a cabo la operacin de modo tal que se puedan encadenar cada una de las operaciones
como si se tratara de la ejecucin de un algoritmo y en caso de que alguna falle se pueda
implementar una alternativa de ejecucin.
Adems de las funciones bsicas anteriores existen otras adicionales utilizadas para el
armado y desarmado de mensajes, que permiten la especificacin del grupo de difusin por el cual
se enva o recibe el mensaje, el identificador de mensaje y los campos de datos que componen al
mensaje.
A continuacin se muestra el contenido de la biblioteca de bloques correspondientes al
manejo del modem PLC.

FernandoArielBeunza79156

733

Tesis de Grado en Ingeniera Informtica

Figura E1. Biblioteca de bloques funcionales.

Algunos de los bloques funcionales mostrados en la figura E1 presentan una serie de


parmetros configurables como el caso de los bloques Modem PLC Interface, Modem PLC Create
Message, Modem PLC Receive Message, Modem PLC Put Field y Modem PLC Get Field.
El primer bloque al cual se hace referencia es el relacionado a la conexin con el modem
PLC denominado Modem PLC Interface. Dicho bloque se encarga de establecer las comunicaciones
con el mencionado modem y presenta como nico parmetro configurable el nmero de puerto serie
(correspondiendo 1 a COM1, 2 a COM2, etc.) al cual se encuentra conectado el modem PLC como
se puede observar en la figura E2.

Figura E2. Parmetros configurables correspondientes al bloque Modem PLC Interface.

El segundo bloque al cual se hace referencia se denomina Modem PLC Create Message,
utilizado para crear un nuevo mensaje. Con este bloque funcional se inicializa un mensaje en donde
se especifica el identificador de grupo de difusin que se utiliza para el envo del mensaje, y un
734

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


identificador de mensaje utilizado para que el destinatario del mensaje pueda identificar y procesar
el mensaje recibido. En la figura E3 se pueden observar los parmetros configurables a los cuales se
hacia referencia anteriormente.

Figura E3. Parmetros configurables correspondientes al bloque Modem PLC Create Message.

El bloque denominado Modem PLC Put Field, es utilizado para agregar un campo de datos a
un mensaje previamente creado con el bloque descripto anteriormente. El nico parmetro
configurable que presenta hace referencia al tipo de datos que contiene el campo como se puede
observar en la figura E4. La multiplicidad de los datos de campo est dada por la entrada de datos
del bloque, si la entrada se compone de una seal, la multiplicidad del campo sera uno; y si se tratan
de varias seales concentradas por ejemplo por el bloque Multiplexor provisto por Simulink, la
multiplicidad del campo la determinar la cantidad de seales que ingresan al multiplexor.

Figura E4. Parmetros configurables correspondientes al bloque Modem PLC Put Field.

El bloque denominado Modem PLC Send Message, es utilizado para enviar un mensaje
armado por medio de los dos bloques anteriormente descriptos. No presenta ningn parmetro
configurable ya que todo lo referente al mensaje se especifica por medio de los dos bloques
anteriores.
El bloque denominado Modem PLC Receive Message, es utilizado recibir un mensaje por
medio del grupo de difusin especificado como parmetro, y asociado a un determinado
identificador de mensaje opcionalmente tambin especificado como parmetro, como se muestra en
la figura E5. El identificador de grupo es obligatorio especificarlo, mientras que el identificador de
mensaje, con slo especificar el valor -1 se indica que se acepta cualquier mensaje
independientemente del identificador de mensaje que posean.

FernandoArielBeunza79156

735

Tesis de Grado en Ingeniera Informtica

Figura E5. Parmetros configurables correspondientes al bloque Modem PLC Receive Message.

El bloque denominado Modem PLC Get Field, es utilizado para extraer un campo de datos
de un mensaje recibido. Como parmetro configurable (figura E6) posee la cantidad de datos del
campo que se desea recibir que no es necesario que conocida con la cantidad de datos recibidos. Si
la cantidad especificada es mayor a la recibida, el bloque devuelve en su salida la cantidad de datos
recibida; y si es menor, devuelve la cantidad especificada.

Figura E6. Parmetros configurables correspondientes al bloque Modem PLC Get Field.

El bloque denominado Modem PLC Real Time, brinda la posibilidad aproximar el tiempo de
simulacin al tiempo real transcurrido, para poder simular modelos en un tiempo similar al real.
Este bloque no presenta parmetros configurables pero posee una salida que devuelve el tiempo real
que se debe agregar en cada paso de simulacin para aproximar el tiempo de simulacin al tiempo
real. Cuando devuelve un valor negativo, indica que el tiempo real transcurrido supera al tiempo de
simulacin.

E.3. Cdigo fuente


La interfaz Simulink se compone de seis bloques que permiten utilizar de forma interactiva
las funcionalidades que ofrece la capa de aplicacin. Cada bloque lleva asociado un cdigo fuente
en lenguaje C que se compila generando una biblioteca dinmica. Dichas bibliotecas dinmicas
interactan con la capa de aplicacin por medio de otra biblioteca dinmica encargada de
compatibilizar la interfaz Simulink con la interfaz de la capa anteriormente mencionada.
736

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Bloques Simulink

modem_plc_interface.dllmodem_plc_create_message.dllmodem_plc_put_field.dll
modem_plc_send_message.dllmodem_plc_receive_message.dll
modem_plc_get_field.dll
modplc_simulink.dll

Capa de aplicacin

modplcap.dll

Figura E7. Diagrama de organizacin de cdigo.

En la figura E7 se puede observar la organizacin de los elementos descriptos dentro del


esquema de capas propuesto en el presente trabajo.

E.3.1. Archivo modplc_simulink.c


/*
modplc_simulink.c:
Implementacin de funciones referentes a la interfaz Simulink del modem
PLC.
*/

/* Archivos includos necesarios. */


#include <stdio.h>
#include <math.h>
#include "..\modplcap\modplcap.h"

/* Definicin de tipos. */
/* Estructura de nodo de lista de mensajes recibidos. */
typedef struct
{
modplcap_msg *msg;
void *next;
} listmsg_node;

/* Mensaje. */
/* Puntero al prximo nodo. */

/* Estructura de manejador de comunicacin entre bloques Simulink del Modem


PLC. */
typedef struct
{
modplcap_hd *hd;
/* Manejador de capa de
aplicacin del Modem PLC. */
modplcap_msg *msg;
/* Mensaje a enviar o recibido. */
int groups[256];
/* Grupos suscriptos. */
listmsg_node *frecvmsg;
/* Puntero al nodo del primer
mensaje recibido. */
listmsg_node *lrecvmsg;
/* Puntero al nodo del ltimo
mensaje recibido. */
} modplcsimulink_hd;

/* Definicin de constantes. */
/* Tipos de datos. */
#define MODPLCSIMULINK_CHARTYPE
#define MODPLCSIMULINK_SINT8TYPE
#define MODPLCSIMULINK_UINT8TYPE
#define MODPLCSIMULINK_SINT16TYPE
#define MODPLCSIMULINK_UINT16TYPE
#define MODPLCSIMULINK_SINT32TYPE

FernandoArielBeunza79156

1
2
3
4
5
6

737

Tesis de Grado en Ingeniera Informtica


#define MODPLCSIMULINK_UINT32TYPE
#define MODPLCSIMULINK_FLOATTYPE

7
8

/* Implementacin de funciones pblicas referentes al bloque Modem PLC


Interface. */
/*
Funcin ModemPlcInterface_Initialize:
Inicializa el bloque Modem PLC Interface.
*/
void *ModemPlcInterface_Initialize(int port)
{
/* Variables. */
short int i;
modplcsimulink_hd *handle;

/* Contador. */
/* Manejador de comunicacin entre
bloques Simulink del Modem
PLC. */

/* Inicializa el bloque. */
handle = NULL;
while(1)
{
/* Carga la biblioteca. */
if (!modplcap_loadlib()) break;
/* Inicializa el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
handle = (modplcsimulink_hd *) malloc(sizeof(modplcsimulink_hd));
if (!handle) break;
/* Inicializa el manejador de capa fsica del modem PLC.. */
handle->hd = modplcap_init(port);
if (!handle->hd) break;
/* Inicializa el puntero al mensaje a enviar o recibido. */
handle->msg = NULL;
/* Inicializa la tabla de suscripciones a grupos. */
for(i = 0; i < 255; i++) handle->groups[i] = 0;
/* Inicializa la lista de mensajes recibidos. */
handle->frecvmsg = NULL;
handle->lrecvmsg = NULL;
/* xito. */
return handle;
}
if (handle)
{
modplcap_release(handle->hd);
free(handle);
handle = NULL;
}
return handle;
}
/*
Funcin ModemPlcInterface_Output:
Ejecuta el bloque Modem PLC Interface.
*/
int ModemPlcInterface_Output(void *handle)
{
/* Variables. */
listmsg_node *node;

/* Nodo de lista de mensajes. */

/* Verifica que manejador de comunicacin entre bloques Simulink del Modem


PLC exista. */
if (!handle) return 0;

738

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Verifica el estado del Model PLC. */
if (!modplcap_status(((modplcsimulink_hd *) handle)->hd)) return 0;
/* Recibe mensajes disponibles. */
while(modplcap_poll(((modplcsimulink_hd *) handle)->hd))
{
/* Crea un nuevo nodo. */
node = (listmsg_node *) malloc(sizeof(listmsg_node));
if (!node) break;
/* Recibe el mensaje. */
node->msg = (modplcap_msg *) malloc(sizeof(modplcap_msg));
if (!node->msg)
{
free(node);
break;
}
if (!modplcap_receivemsg(((modplcsimulink_hd *) handle)->hd,
node->msg))
{
free(node->msg);
free(node);
break;
}
node->next = NULL;
/* Agrega el nuevo nodo a la lista. */
if (!((modplcsimulink_hd *) handle)->frecvmsg)
{
((modplcsimulink_hd *) handle)->frecvmsg = node;
((modplcsimulink_hd *) handle)->lrecvmsg = node;
}
else
{
((modplcsimulink_hd *) handle)->lrecvmsg->next = node;
((modplcsimulink_hd *) handle)->lrecvmsg = node;
}
break;
}
return 1;
}
/*
Funcin ModemPlcInterface_Terminate:
Libera los recursos utilizados por el bloque Modem PLC Interface.
*/
int ModemPlcInterface_Terminate(void *handle)
{
/* Variables. */
listmsg_node *node;
listmsg_node *next;

/* Nodo de lista de mensajes. */


/* Prximo nodo en la lista de
mensajes. */

/* Verifica que manejador de comunicacin entre bloques Simulink del Modem


PLC exista. */
if (!handle) return 0;
/* Limpia la lista de mensajes recibidos. */
node = ((modplcsimulink_hd *) handle)->frecvmsg;
while(node)
{
/* Destruye el mensaje almacenado. */
modplcap_destroymsg(node->msg);
/* Almacena el puntero al siguiente nodo. */
next = (listmsg_node *) node->next;
/* Destruye el nodo. */
free(node);

FernandoArielBeunza79156

739

Tesis de Grado en Ingeniera Informtica


/* Carga el siguiente nodo. */
node = next;
}
/* Libera los recursos utilizados por la capa de aplicacin del modem
PLC. */
modplcap_release(((modplcsimulink_hd *) handle)->hd);
/* Libera el manejador de comunicacin entre bloques Simulink del Modem
PLC. */
free(handle);
/* xito. */
return 1;
}

/* Implementacin de funciones pblicas referentes al bloque Modem PLC Create


Message. */
/*
Funcin ModemPlcCreateMessage_Initialize:
Inicializa el bloque Modem PLC Create Message.
*/
void *ModemPlcCreateMessage_Initialize(void)
{
return malloc(sizeof(modplcap_msg));
}
/*
Funcin ModemPlcCreateMessage_Output:
Ejecuta el bloque Modem PLC Create Message.
*/
int ModemPlcCreateMessage_Output(void *handle, void *msg, int grpid, int msgid)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del Modem
PLC exista. */
if (!handle) return 0;
/* Verifica que exista el mensaje. */
if (!msg) return 0;
/* Destruye el mensaje anterior, */
if (((modplcsimulink_hd *) handle)->msg)
{
modplcap_destroymsg(msg);
((modplcsimulink_hd *) handle)->msg = NULL;
}
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del
Modem PLC y el manejador de mensaje exista. */
if (!handle) break;
/* Establace al modem PLC como publicador del grupo asociado al mensaje
que se quiere crear. */
if (!((modplcsimulink_hd *) handle)->groups[(modplcap_grpid) grpid])
{
modplcap_publish(((modplcsimulink_hd *) handle)->hd,
(modplcap_grpid) grpid);
((modplcsimulink_hd *) handle)->groups[(modplcap_grpid) grpid] = 1;
}
/* Crea un nuevo mensaje. */
if (!modplcap_newmsg(((modplcsimulink_hd *) handle)->hd,
(modplcap_msg *) msg, (modplcap_grpid) grpid,
(modplcap_msgid) msgid))
break;

740

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Carga el nuevo mensaje en el manejador. */
((modplcsimulink_hd *) handle)->msg = (modplcap_msg *) msg;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
return 1;
}
/* No se pudo inicializar el mensaje. */
return 0;
}
/*
Funcin ModemPlcCreateMessage_Terminate:
Libera los recursos utilizados por el bloque Modem PLC Create Message.
*/
int ModemPlcCreateMessage_Terminate(void *msg)
{
/* Destruye el mensaje anterior. */
if (!msg) return 0;
modplcap_destroymsg((modplcap_msg *) msg);
free(msg);
return 1;
}

/* Implementacin de funciones pblicas referentes al bloque Modem PLC Put


Field. */
/*
Funcin ModemPlcPutField_Initialize:
Inicializa el bloque Modem PLC Put Field.
*/
void *ModemPlcPutField_Initialize(void)
{
return NULL;
}
/*
Funcin ModemPlcPutField_Output:
Ejecuta el bloque Modem PLC Put Field.
*/
int ModemPlcPutField_Output(void *handle, int type, int count, double *dat)
{
/* Variables. */
int i;
/* Contador. */
int result;
/* Resultado de la operacin de
agregado del campo de datos. */
char *datchar;
/* Puntero a datos tipo caracter. */
char *datsint8;
/* Puntero a datos tipo entero con
signo de 8 bits. */
unsigned char *datuint8;
/* Puntero a datos tipo entero sin
signo de 8 bits. */
short int *datsint16;
/* Puntero a datos tipo entero con
signo de 16 bits. */
unsigned short int *datuint16;
/* Puntero a datos tipo entero sin
signo de 16 bits. */
long int *datsint32;
/* Puntero a datos tipo entero con
signo de 32 bits. */
unsigned long int *datuint32;
/* Puntero a datos tipo entero sin
signo de 32 bits. */
float *datfloat;
/* Puntero a datos tipo punto
flotante. */

/* Verifica que manejador de comunicacin entre bloques Simulink del Modem


PLC exista. */
if (!handle) return 0;
/* Ejecuta un ciclo Simulink. */

FernandoArielBeunza79156

741

Tesis de Grado en Ingeniera Informtica


while(1)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del
Modem PLC exista. */
if (!handle) break;
if (!((modplcsimulink_hd *) handle)->msg) break;
/* Carga el campo de datos. */
result = 0;
if (count > 255) count = 255;
switch(type)
{
/* Tipo caracter. */
case MODPLCSIMULINK_CHARTYPE:
datchar = (char *) malloc(count * sizeof(char));
if (!datchar) break;
for(i = 0; i < count; i++) datchar[i] = (char) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_CHARTYPE,
(unsigned char) count, datchar);
free(datchar);
break;
/* Tipo entero con signo de 8 bits. */
case MODPLCSIMULINK_SINT8TYPE:
datsint8 = (char *) malloc(count * sizeof(char));
if (!datsint8) break;
for(i = 0; i < count; i++) datsint8[i] = (char) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_SINT8TYPE,
(unsigned char) count, datsint8);
free(datsint8);
break;
/* Tipo entero sin signo de 8 bits. */
case MODPLCSIMULINK_UINT8TYPE:
datuint8 =
(unsigned char *) malloc(count * sizeof(unsigned char));
if (!datuint8) break;
for(i = 0; i < count; i++)
datuint8[i] = (unsigned char) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_UINT8TYPE,
(unsigned char) count, datuint8);
free(datuint8);
break;
/* Tipo entero con signo de 16 bits. */
case MODPLCSIMULINK_SINT16TYPE:
datsint16 = (short int *) malloc(count * sizeof(short int));
if (!datsint16) break;
for(i = 0; i < count; i++)
datsint16[i] = (short int) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_SINT16TYPE,
(unsigned char) count, datsint16);
free(datsint16);
break;
/* Tipo entero sin signo de 16 bits. */
case MODPLCSIMULINK_UINT16TYPE:
datuint16 = (unsigned short int *)
malloc(count * sizeof(unsigned short int));
if (!datuint16) break;
for(i = 0; i < count; i++)
datuint16[i] = (unsigned short int) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_UINT16TYPE,
(unsigned char) count, datuint16);
free(datuint16);
break;

742

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Tipo entero con signo de 32 bits. */
case MODPLCSIMULINK_SINT32TYPE:
datsint32 = (long int *) malloc(count * sizeof(long int));
if (!datsint32) break;
for(i = 0; i < count; i++)
datsint32[i] = (long int) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_SINT32TYPE,
(unsigned char) count, datsint32);
free(datsint32);
break;
/* Tipo entero sin signo de 32 bits. */
case MODPLCSIMULINK_UINT32TYPE:
datuint32 = (unsigned long int *)
malloc(count * sizeof(unsigned long int));
if (!datuint32) break;
for(i = 0; i < count; i++)
datuint32[i] = (unsigned long int) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_UINT32TYPE,
(unsigned char) count, datuint32);
free(datuint32);
break;
/* Tipo punto flotante. */
case MODPLCSIMULINK_FLOATTYPE:
datfloat = (float *) malloc(count * sizeof(float));
if (!datfloat) break;
for(i = 0; i < count; i++) datfloat[i] = (float) ceil(dat[i]);
result = modplcap_putfield(((modplcsimulink_hd *) handle)->msg,
MODPLCAP_FLOATTYPE,
(unsigned char) count, datfloat);
free(datfloat);
break;
/* Tipo desconocido. */
default:
break;
}
if (!result) break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
return 1;
}
/* No se pudo agregar el campo de datos al mensaje. */
return 0;
}
/*
Funcin ModemPlcPutField_Terminate:
Libera los recursos utilizados por el bloque Modem PLC Put Field.
*/
int ModemPlcPutField_Terminate(void)
{
return 1;
}

/* Implementacin de funciones pblicas referentes al bloque Modem PLC Send


Message. */
/*
Funcin ModemPlcSendMessage_Initialize:
Inicializa el bloque Modem PLC Send Message.
*/
void *ModemPlcSendMessage_Initialize(void)
{

FernandoArielBeunza79156

743

Tesis de Grado en Ingeniera Informtica


return NULL;
}
/*
Funcin ModemPlcSendMessage_Output:
Ejecuta el bloque Modem PLC Send Message.
*/
int ModemPlcSendMessage_Output(void *handle)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del Modem
PLC exista. */
if (!handle) return 0;
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del
Modem PLC exista. */
if (!handle) break;
/* Enva el mensaje. */
modplcap_sendmsg(((modplcsimulink_hd *) handle)->msg);
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
return 1;
}
/* No se pudo enviar el mensaje. */
return 0;
}
/*
Funcin ModemPlcSendMessage_Terminate:
Libera los recursos utilizados por el bloque Modem PLC Send Message.
*/
int ModemPlcSendMessage_Terminate(void)
{
return 1;
}

/* Implementacin de funciones pblicas referentes al bloque Modem PLC Receive


Message. */
/*
Funcin ModemPlcReceiveMessage_Initialize:
Inicializa el bloque Modem PLC Receive Message.
*/
void *ModemPlcReceiveMessage_Initialize(void)
{
return malloc(sizeof(modplcap_msg));
}
/*
Funcin ModemPlcReceiveMessage_Output:
Ejecuta el bloque Modem PLC Receive Message.
*/
int ModemPlcReceiveMessage_Output(void *handle, void *msg, int grpid,
int msgid)
{
/* Variables. */
listmsg_node *currnode;
/* Nodo corriente de lista de
mensajes. */
listmsg_node *prevnode;
/* Nodo previo al corriente de
lista de mensajes. */

/* Verifica que manejador de comunicacin entre bloques Simulink del Modem


PLC exista. */
if (!handle) return 0;

744

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Veririca que exista el mensaje. */
if (!msg) return 0;
/* Destruye el mensaje anterior, */
if (((modplcsimulink_hd *) handle)->msg)
{
modplcap_destroymsg(msg);
((modplcsimulink_hd *) handle)->msg = NULL;
}
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del Modem
PLC y el manejador de mensaje exista. */
if (!handle) break;
/* Establace al modem PLC como suscriptor del grupo asociado al mensaje
recibido. */
if (!((modplcsimulink_hd *) handle)->groups[(modplcap_grpid) grpid])
{
modplcap_subscribe(((modplcsimulink_hd *) handle)->hd,
(modplcap_grpid) grpid);
((modplcsimulink_hd *) handle)->groups[(modplcap_grpid) grpid] = 1;
}
/* Busca el siguiente mensaje en la lista. */
prevnode = NULL;
currnode = ((modplcsimulink_hd *) handle)->frecvmsg;
while(currnode)
{
/* Filtra el mensaje por identificador de grupo. */
if (modplcap_getgrpid(currnode->msg) != grpid)
{
prevnode = currnode;
currnode = currnode->next;
continue;
}
/* Filtra el mensaje por identificador de mensaje. */
if (msgid > -1)
{
if (modplcap_getmsgid(currnode->msg) != msgid)
{
prevnode = currnode;
currnode = currnode->next;
continue;
}
}
/* Obtiene el mensaje encontrado. */
msg = currnode->msg;
/* Elimina el mensaje de la lista. */
if (prevnode)
prevnode->next = currnode->next;
else
((modplcsimulink_hd *) handle)->frecvmsg = currnode->next;
if (((modplcsimulink_hd *) handle)->lrecvmsg == currnode)
((modplcsimulink_hd *) handle)->lrecvmsg = prevnode;
free(currnode);
break;
}
/* Carga el mensaje recibido en el manejador. */
if (currnode)
((modplcsimulink_hd *) handle)->msg = (modplcap_msg *) msg;
else
{
((modplcsimulink_hd *) handle)->msg = NULL;

FernandoArielBeunza79156

745

Tesis de Grado en Ingeniera Informtica


break;
}
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
return 1;
}
/* No se pudo recibir el mensaje. */
return 0;
}
/*
Funcin ModemPlcReceiveMessage_Terminate:
Libera los recursos utilizados por el bloque Modem PLC Receive Message.
*/
int ModemPlcReceiveMessage_Terminate(void *msg)
{
/* Destruye el mensaje anterior. */
if (!msg) return 0;
modplcap_destroymsg((modplcap_msg *) msg);
free(msg);
return 1;
}

/* Implementacin de funciones pblicas referentes al bloque Modem PLC Get


Field. */
/*
Funcin ModemPlcGetField_Initialize:
Inicializa el bloque Modem PLC Get Field.
*/
void *ModemPlcGetField_Initialize(void)
{
return NULL;
}
/*
Funcin ModemPlcGetField_Output:
Ejecuta el bloque Modem PLC Get Field.
*/
int ModemPlcGetField_Output(void *handle, unsigned char count, double *dat)
{
/* Variables. */
int i;
/* Contador. */
int result;
/* Resultado de la operacin de
agregado del campo de datos. */
modplcap_ftype rtype;
/* Identificador de tipo de
dato. */
unsigned char rcount;
/* Cantidad de datos recibidos. */
void *rdat;
/* Puntero a los datos
recibidos. */
char *datchar;
/* Puntero a datos tipo caracter. */
char *datsint8;
/* Puntero a datos tipo entero con
signo de 8 bits. */
unsigned char *datuint8;
/* Puntero a datos tipo entero sin
signo de 8 bits. */
short int *datsint16;
/* Puntero a datos tipo entero con
signo de 16 bits. */
unsigned short int *datuint16;
/* Puntero a datos tipo entero sin
signo de 16 bits. */
long int *datsint32;
/* Puntero a datos tipo entero con
signo de 32 bits. */
unsigned long int *datuint32;
/* Puntero a datos tipo entero sin
signo de 32 bits. */
float *datfloat;
/* Puntero a datos tipo punto
flotante. */

/* Verifica que manejador de comunicacin entre bloques Simulink del Modem

746

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


PLC exista. */
if (!handle) return 0;
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del
Modem PLC exista. */
if (!handle) break;
if (!((modplcsimulink_hd *) handle)->msg) break;
/* Carga el campo de datos. */
rdat = malloc(256 * sizeof(unsigned long int));
if (!rdat) break;
if (!modplcap_getfield(((modplcsimulink_hd *) handle)->msg, &rtype,
&rcount, rdat))
break;
result = 1;
datchar = (char *) rdat;
datsint8 = (char *) rdat;
datuint8 = (unsigned char *) rdat;
datsint16 = (short int *) rdat;
datuint16 = (unsigned short int *) rdat;
datsint32 = (long int *) rdat;
datuint32 = (unsigned long int *) rdat;
datfloat = (float *) rdat;
switch(rtype)
{
/* Tipo caracter. */
case MODPLCSIMULINK_CHARTYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datchar[i];
else
dat[i] = 0;
}
break;
/* Tipo entero con signo de 8 bits. */
case MODPLCSIMULINK_SINT8TYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datsint8[i];
else
dat[i] = 0;
}
break;
/* Tipo entero sin signo de 8 bits. */
case MODPLCSIMULINK_UINT8TYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datuint8[i];
else
dat[i] = 0;
}
break;
/* Tipo entero con signo de 16 bits. */
case MODPLCSIMULINK_SINT16TYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datsint16[i];
else
dat[i] = 0;
}
break;

FernandoArielBeunza79156

747

Tesis de Grado en Ingeniera Informtica


/* Tipo entero sin signo de 16 bits. */
case MODPLCSIMULINK_UINT16TYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datuint16[i];
else
dat[i] = 0;
}
break;
/* Tipo entero con signo de 32 bits. */
case MODPLCSIMULINK_SINT32TYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datsint32[i];
else
dat[i] = 0;
}
break;
/* Tipo entero sin signo de 32 bits. */
case MODPLCSIMULINK_UINT32TYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datuint32[i];
else
dat[i] = 0;
}
break;
/* Tipo punto flotante. */
case MODPLCSIMULINK_FLOATTYPE:
for(i = 0; i < count; i++)
{
if (i < rcount)
dat[i] = (double) datfloat[i];
else
dat[i] = 0;
}
break;
/* Tipo desconocido. */
default:
result = 0;
break;
}
free(rdat);
if (!result) break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
return 1;
}
/* No se pudo agregar el campo de datos al mensaje. */
return 0;
}
/*
Funcin ModemPlcGetField_Terminate:
Libera los recursos utilizados por el bloque Modem PLC Get Field.
*/
int ModemPlcGetField_Terminate(void)
{
return 1;
}

748

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

E.3.2. Archivo MODEM_PLC_INTERFACE.C


/*
MODEM_PLC_INTERFACE.C:
Se encarga de configurar la interfaz donde se encuentran conectado el modem
PLC.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

Modem_PLC_Interface
2

/* Archivos includos necesarios. */


#include <windows.h>
#include <math.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

/* Variables globales. */
static void *handle;

/* Manejador de comunicacin entre


bloques Simulink del Modem
PLC. */

/* Declaracin de funciones externas. */


void * (*ModemPlcInterface_Initialize)(int);
int (*ModemPlcInterface_Output)(void *);
int (*ModemPlcInterface_Terminate)(void *);

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */
DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 1);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas que requiere el bloque Simulink. */
if (!ssSetNumInputPorts(S, 0)) return;
/* Define la cantidad de salidas que requiere el bloque Simulink. */
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);
ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}

FernandoArielBeunza79156

749

Tesis de Grado en Ingeniera Informtica


/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca dinmica. */

/* Establece el tiempo de muestreo. */


ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Carga la biblioteca. */
hlib = NULL;
ModemPlcInterface_Initialize = NULL;
ModemPlcInterface_Output = NULL;
ModemPlcInterface_Terminate = NULL;
hlib = LoadLibrary("MODPLC_SIMULINK");
if (!hlib) return;
ModemPlcInterface_Initialize = (void * (*)(int))
GetProcAddress(hlib, "ModemPlcInterface_Initialize");
ModemPlcInterface_Output = (int (*)(void *))
GetProcAddress(hlib, "ModemPlcInterface_Output");
ModemPlcInterface_Terminate = (int (*)(void *))
GetProcAddress(hlib, "ModemPlcInterface_Terminate");
if ((!ModemPlcInterface_Initialize) || (!ModemPlcInterface_Output) ||
(!ModemPlcInterface_Terminate))
return;
/* Inicializa el bloque Simulink. */
handle = ModemPlcInterface_Initialize(
(int) ceil(*mxGetPr(ssGetSFcnParam(S, 0))));
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque
Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
int *flag_out;

unsigned long int *handle_out;

/* Puntero al indicador de
resultado de ejecucin de la
presente operacin. */
/* Puntero al manejador de conexin
de salida. */

/* Carga salidas del bloque Simulink. */


handle_out = (unsigned long int *) ssGetOutputPortSignal(S, 0);
flag_out = (int *) ssGetOutputPortSignal(S, 1);
/* Ejecuta un ciclo de simulacin para el bloque Simulink. */
while(1)
{
/* Verifica que manejador de comunicacin entre bloques Simulink del
Modem PLC exista. */
if (!handle) break;
/* Ejecuta un ciclo Simulink. */
if (!ModemPlcInterface_Output(handle)) break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
*handle_out = (unsigned long int) handle;
*flag_out = 1;
return;

750

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


}
/* No se pudo ejecutar el ciclo de simulacin. */
*handle_out = 0;
*flag_out = 0;
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{
ModemPlcInterface_Terminate(handle);
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

E.3.3. Archivo MODEM_PLC_CREATE_MESSAGE.C


/*
MODEM_PLC_CREATE_MESSAGE.C:
Se encarga de inicializar un nuevo mensaje.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

Modem_PLC_Create_Message
2

/* Archivos includos necesarios. */


#include <windows.h>
#include <math.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

/* Variables globales. */
static int grpid;
static int msgid;
static void *msg;

/* Identificador de grupo. */
/* Identificador de mensaje. */
/* Puntero al mensaje. */

/* Declaracin de funciones externas. */


void * (*ModemPlcCreateMessage_Initialize)(void);
int (*ModemPlcCreateMessage_Output)(void *, void *, int, int);
int (*ModemPlcCreateMessage_Terminate)(void *);

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */

FernandoArielBeunza79156

751

Tesis de Grado en Ingeniera Informtica


DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 2);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas que requiere el bloque Simulink. */
if (!ssSetNumInputPorts(S, 2)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortRequiredContiguous(S, 0, 1);
ssSetInputPortWidth(S, 1, 1);
ssSetInputPortDirectFeedThrough(S, 1, 1);
ssSetInputPortRequiredContiguous(S, 1, 1);
/* Define la cantidad de salidas que requiere el bloque Simulink. */
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);
ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca dinmica. */

/* Establece el tiempo de muestreo. */


ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Carga la biblioteca. */
msg = NULL;
hlib = NULL;
ModemPlcCreateMessage_Initialize = NULL;
ModemPlcCreateMessage_Output = NULL;
ModemPlcCreateMessage_Terminate = NULL;
hlib = LoadLibrary("MODPLC_SIMULINK");
if (!hlib) return;
ModemPlcCreateMessage_Initialize = (void * (*)(void))
GetProcAddress(hlib, "ModemPlcCreateMessage_Initialize");
ModemPlcCreateMessage_Output = (int (*)(void *, void *, int, int))
GetProcAddress(hlib, "ModemPlcCreateMessage_Output");
ModemPlcCreateMessage_Terminate = (int (*)(void *))
GetProcAddress(hlib, "ModemPlcCreateMessage_Terminate");
if ((!ModemPlcCreateMessage_Initialize) ||
(!ModemPlcCreateMessage_Output) || (!ModemPlcCreateMessage_Terminate))
return;
/* Inicializa el bloque Simulink. */
grpid = (int) ceil(*mxGetPr(ssGetSFcnParam(S, 0)));
msgid = (int) ceil(*mxGetPr(ssGetSFcnParam(S, 1)));
msg = ModemPlcCreateMessage_Initialize();
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque

752

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
int *flag_in;

int *flag_out;

unsigned long int *handle_in;


unsigned long int *handle_out;

/* Puntero al indicador de entrada


de ejecucin de la presente
operacin. */
/* Puntero al indicador de salida
de ejecucin de la presente
operacin. */
/* Puntero al manejador de conexin
de entrada. */
/* Puntero al manejador de conexin
de salida. */

/* Carga entradas del bloque Simulink. */


handle_in = (unsigned long int *) ssGetInputPortSignal(S, 0);
flag_in = (int *) ssGetInputPortSignal(S, 1);
/* Carga salidas del bloque Simulink. */
handle_out = (unsigned long int *) ssGetOutputPortSignal(S, 0);
flag_out = (int *) ssGetOutputPortSignal(S, 1);
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica si se solicita ejecutar un ciclo de la presente
operacin. */
if (!(*flag_in)) break;
/* Verifica que exista el manejador de conexin. */
if (!(*handle_in)) break;
/* Ejecuta un ciclo Simulink. */
if (!ModemPlcCreateMessage_Output((void *) *handle_in, msg, grpid,
msgid))
break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
*handle_out = *handle_in;
*flag_out = 1;
return;
}
/* No se pudo ejecutar el ciclo de simulacin. */
*handle_out = 0;
*flag_out = 0;
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{
ModemPlcCreateMessage_Terminate(msg);
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

FernandoArielBeunza79156

753

Tesis de Grado en Ingeniera Informtica

E.3.4. Archivo MODEM_PLC_PUT_FIELD.C


/*
MODEM_PLC_PUT_FIELD.C:
Se encarga de agregar un campo de datos a un mensaje.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

Modem_PLC_Put_Field
2

/* Archivos includos necesarios. */


#include <windows.h>
#include <math.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

/* Variables globales. */
static int type;

/* Identificador de tipo de
dato. */

/* Declaracin de funciones externas. */


void * (*ModemPlcPutField_Initialize)(void);
int (*ModemPlcPutField_Output)(void *, int, int, double *);
int (*ModemPlcPutField_Terminate)(void);

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */
DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 1);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas que requiere el bloque Simulink. */
if (!ssSetNumInputPorts(S, 3)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortRequiredContiguous(S, 0, 1);
ssSetInputPortWidth(S, 1, 1);
ssSetInputPortDirectFeedThrough(S, 1, 1);
ssSetInputPortRequiredContiguous(S, 1, 1);
ssSetInputPortWidth(S, 2 , DYNAMICALLY_SIZED);
ssSetInputPortDirectFeedThrough(S, 2, 1);
/* Define la cantidad de salidas que requiere el bloque Simulink. */
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);

754

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca dinmica. */

/* Establece el tiempo de muestreo. */


ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Carga la biblioteca. */
hlib = NULL;
ModemPlcPutField_Initialize = NULL;
ModemPlcPutField_Output = NULL;
ModemPlcPutField_Terminate = NULL;
hlib = LoadLibrary("MODPLC_SIMULINK");
if (!hlib) return;
ModemPlcPutField_Initialize = (void * (*)(void))
GetProcAddress(hlib, "ModemPlcPutField_Initialize");
ModemPlcPutField_Output = (int (*)(void *, int, int, double *))
GetProcAddress(hlib, "ModemPlcPutField_Output");
ModemPlcPutField_Terminate = (int (*)(void))
GetProcAddress(hlib, "ModemPlcPutField_Terminate");
if ((!ModemPlcPutField_Initialize) || (!ModemPlcPutField_Output) ||
(!ModemPlcPutField_Terminate))
return;
/* Inicializa el bloque Simulink. */
type = (int) ceil(*mxGetPr(ssGetSFcnParam(S, 0)));
ModemPlcPutField_Initialize();
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque
Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
InputRealPtrsType data_in;
int *flag_in;

int *flag_out;

unsigned long int *handle_in;


unsigned long int *handle_out;

/* Datos de entrada. */
/* Puntero al indicador de entrada
de ejecucin de la presente
operacin. */
/* Puntero al indicador de salida
de ejecucin de la presente
operacin. */
/* Puntero al manejador de conexin
de entrada. */
/* Puntero al manejador de conexin
de salida. */

/* Carga entradas del bloque Simulink. */


handle_in = (unsigned long int *) ssGetInputPortSignal(S, 0);
flag_in = (int *) ssGetInputPortSignal(S, 1);
if (ssGetInputPortRequiredContiguous(S, 2))
data_in = &ssGetInputPortRealSignal(S, 2);
else
data_in = ssGetInputPortRealSignalPtrs(S, 2);

FernandoArielBeunza79156

755

Tesis de Grado en Ingeniera Informtica


/* Carga salidas del bloque Simulink. */
handle_out = (unsigned long int *) ssGetOutputPortSignal(S, 0);
flag_out = (int *) ssGetOutputPortSignal(S, 1);
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica si se solicita ejecutar un ciclo de la presente
operacin. */
if (!(*flag_in)) break;
/* Verifica que exista el manejador de conexin. */
if (!(*handle_in)) break;
/* Ejecuta un ciclo Simulink. */
if (!ModemPlcPutField_Output((void *) *handle_in, type,
(unsigned char) ssGetInputPortWidth(S, 2), (double *) *data_in))
break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
*handle_out = *handle_in;
*flag_out = 1;
return;
}
/* No se pudo ejecutar el ciclo de simulacin. */
*handle_out = 0;
*flag_out = 0;
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{
ModemPlcPutField_Terminate();
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

E.3.5. Archivo MODEM_PLC_SEND_MESSAGE.C


/*
MODEM_PLC_SEND_MESSAGE.C:
Se encarga de enviar un mensaje.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

Modem_PLC_Send_Message
2

/* Archivos includos necesarios. */


#include <windows.h>
#include <math.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

756

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

/* Declaracin de funciones externas. */


void * (*ModemPlcSendMessage_Initialize)(void);
int (*ModemPlcSendMessage_Output)(void *);
int (*ModemPlcSendMessage_Terminate)(void);

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */
DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas que requiere el bloque Simulink. */
if (!ssSetNumInputPorts(S, 2)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortRequiredContiguous(S, 0, 1);
ssSetInputPortWidth(S, 1, 1);
ssSetInputPortDirectFeedThrough(S, 1, 1);
ssSetInputPortRequiredContiguous(S, 1, 1);
/* Define la cantidad de salidas que requiere el bloque Simulink. */
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);
ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca dinmica. */

/* Establece el tiempo de muestreo. */


ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Carga la biblioteca. */
hlib = NULL;
ModemPlcSendMessage_Initialize = NULL;
ModemPlcSendMessage_Output = NULL;
ModemPlcSendMessage_Terminate = NULL;
hlib = LoadLibrary("MODPLC_SIMULINK");
if (!hlib) return;
ModemPlcSendMessage_Initialize = (void * (*)(void))
GetProcAddress(hlib, "ModemPlcSendMessage_Initialize");

FernandoArielBeunza79156

757

Tesis de Grado en Ingeniera Informtica


ModemPlcSendMessage_Output = (int (*)(void *))
GetProcAddress(hlib, "ModemPlcSendMessage_Output");
ModemPlcSendMessage_Terminate = (int (*)(void))
GetProcAddress(hlib, "ModemPlcSendMessage_Terminate");
if ((!ModemPlcSendMessage_Initialize) || (!ModemPlcSendMessage_Output) ||
(!ModemPlcSendMessage_Terminate))
return;
/* Inicializa el bloque Simulink. */
ModemPlcSendMessage_Initialize();
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque
Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
int *flag_in;

int *flag_out;

unsigned long int *handle_in;


unsigned long int *handle_out;

/* Puntero al indicador de entrada


de ejecucin de la presente
operacin. */
/* Puntero al indicador de salida
de ejecucin de la presente
operacin. */
/* Puntero al manejador de conexin
de entrada. */
/* Puntero al manejador de conexin
de salida. */

/* Carga entradas del bloque Simulink. */


handle_in = (unsigned long int *) ssGetInputPortSignal(S, 0);
flag_in = (int *) ssGetInputPortSignal(S, 1);
/* Carga salidas del bloque Simulink. */
handle_out = (unsigned long int *) ssGetOutputPortSignal(S, 0);
flag_out = (int *) ssGetOutputPortSignal(S, 1);
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica si se solicita ejecutar un ciclo de la presente
operacin. */
if (!(*flag_in)) break;
/* Verifica que exista el manejador de conexin. */
if (!(*handle_in)) break;
/* Ejecuta un ciclo Simulink. */
if (!ModemPlcSendMessage_Output((void *) *handle_in)) break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
*handle_out = *handle_in;
*flag_out = 1;
return;
}
/* No se pudo ejecutar el ciclo de simulacin. */
*handle_out = 0;
*flag_out = 0;
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{

758

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


ModemPlcSendMessage_Terminate();
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

E.3.6. Archivo MODEM_PLC_RECEIVE.C


/*
MODEM_PLC_RECEIVE_MESSAGE.C:
Se encarga de recibir un mensaje.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

Modem_PLC_Receive_Message
2

/* Archivos includos necesarios. */


#include <windows.h>
#include <math.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

/* Variables globales. */
static int grpid;
static int msgid;
static void *msg;

/* Identificador de grupo. */
/* Identificador de mensaje. */
/* Puntero al mensaje. */

/* Declaracin de funciones externas. */


void * (*ModemPlcReceiveMessage_Initialize)(void);
int (*ModemPlcReceiveMessage_Output)(void *, void *, int, int);
int (*ModemPlcReceiveMessage_Terminate)(void *);

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */
DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 2);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas que requiere el bloque Simulink. */
if (!ssSetNumInputPorts(S, 2)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortRequiredContiguous(S, 0, 1);
ssSetInputPortWidth(S, 1, 1);

FernandoArielBeunza79156

759

Tesis de Grado en Ingeniera Informtica


ssSetInputPortDirectFeedThrough(S, 1, 1);
ssSetInputPortRequiredContiguous(S, 1, 1);
/* Define la cantidad de salidas que requiere el bloque Simulink. */
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);
ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Variables. */
struct HINSTANCE__ *hlib;

/* Manejador de biblioteca dinmica. */

/* Establece el tiempo de muestreo. */


ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Carga la biblioteca. */
msg = NULL;
hlib = NULL;
ModemPlcReceiveMessage_Initialize = NULL;
ModemPlcReceiveMessage_Output = NULL;
ModemPlcReceiveMessage_Terminate = NULL;
hlib = LoadLibrary("MODPLC_SIMULINK");
if (!hlib) return;
ModemPlcReceiveMessage_Initialize = (void * (*)(void))
GetProcAddress(hlib, "ModemPlcReceiveMessage_Initialize");
ModemPlcReceiveMessage_Output = (int (*)(void *, void *, int, int))
GetProcAddress(hlib, "ModemPlcReceiveMessage_Output");
ModemPlcReceiveMessage_Terminate = (int (*)(void *))
GetProcAddress(hlib, "ModemPlcReceiveMessage_Terminate");
if ((!ModemPlcReceiveMessage_Initialize) ||
(!ModemPlcReceiveMessage_Output) ||
(!ModemPlcReceiveMessage_Terminate))
return;
/* Inicializa el bloque Simulink. */
grpid = (int) ceil(*mxGetPr(ssGetSFcnParam(S, 0)));
msgid = (int) ceil(*mxGetPr(ssGetSFcnParam(S, 1)));
msg = ModemPlcReceiveMessage_Initialize();
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque
Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
int *flag_in;

int *flag_out;

unsigned long int *handle_in;

760

/* Puntero al indicador de entrada


de ejecucin de la presente
operacin. */
/* Puntero al indicador de salida
de ejecucin de la presente
operacin. */
/* Puntero al manejador de conexin

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


unsigned long int *handle_out;

de entrada. */
/* Puntero al manejador de conexin
de salida. */

/* Carga entradas del bloque Simulink. */


handle_in = (unsigned long int *) ssGetInputPortSignal(S, 0);
flag_in = (int *) ssGetInputPortSignal(S, 1);
/* Carga salidas del bloque Simulink. */
handle_out = (unsigned long int *) ssGetOutputPortSignal(S, 0);
flag_out = (int *) ssGetOutputPortSignal(S, 1);
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica si se solicita ejecutar un ciclo de la presente
operacin. */
if (!(*flag_in)) break;
/* Verifica que exista el manejador de conexin. */
if (!(*handle_in)) break;
/* Ejecuta un ciclo Simulink. */
if (!ModemPlcReceiveMessage_Output((void *) *handle_in, msg, grpid,
msgid))
break;
/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
*handle_out = *handle_in;
*flag_out = 1;
return;
}
/* No se pudo ejecutar el ciclo de simulacin. */
*handle_out = 0;
*flag_out = 0;
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{
ModemPlcReceiveMessage_Terminate(msg);
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

E.3.7. Archivo MODEM_PLC_GET_FIELD.C


/*
MODEM_PLC_GET_FIELD.C:
Se encarga de extraer un campo de datos a un mensaje.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

FernandoArielBeunza79156

Modem_PLC_Get_Field
2

761

Tesis de Grado en Ingeniera Informtica


/* Archivos includos necesarios. */
#include <windows.h>
#include <math.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

/* Variables globales. */
static int count;

/* Cantidad de datos del campo. */

/* Declaracin de funciones externas. */


void * (*ModemPlcGetField_Initialize)(void);
int (*ModemPlcGetField_Output)(void *, unsigned char, double *);
int (*ModemPlcGetField_Terminate)(void);

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.
*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */
DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 1);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas y salidas que requiere el bloque
Simulink. */
if (!ssSetNumInputPorts(S, 2)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortRequiredContiguous(S, 0, 1);
ssSetInputPortWidth(S, 1, 1);
ssSetInputPortDirectFeedThrough(S, 1, 1);
ssSetInputPortRequiredContiguous(S, 1, 1);
if (!ssSetNumOutputPorts(S, 3)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortWidth(S, 1, 1);
ssSetOutputPortWidth(S, 2, (int) ceil(*mxGetPr(ssGetSFcnParam(S, 0))));
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);
ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Variables. */
struct HINSTANCE__ *hlib;

762

/* Manejador de biblioteca dinmica. */

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Establece el tiempo de muestreo. */
ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Carga la biblioteca. */
hlib = NULL;
ModemPlcGetField_Initialize = NULL;
ModemPlcGetField_Output = NULL;
ModemPlcGetField_Terminate = NULL;
hlib = LoadLibrary("MODPLC_SIMULINK");
if (!hlib) return;
ModemPlcGetField_Initialize = (void * (*)(void))
GetProcAddress(hlib, "ModemPlcGetField_Initialize");
ModemPlcGetField_Output = (int (*)(void *, unsigned char, double *))
GetProcAddress(hlib, "ModemPlcGetField_Output");
ModemPlcGetField_Terminate = (int (*)(void))
GetProcAddress(hlib, "ModemPlcGetField_Terminate");
if ((!ModemPlcGetField_Initialize) || (!ModemPlcGetField_Output) ||
(!ModemPlcGetField_Terminate))
return;
/* Inicializa el bloque Simulink. */
count = (int) ceil(*mxGetPr(ssGetSFcnParam(S, 0)));
ModemPlcGetField_Initialize();
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque
Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
int *flag_in;

int *flag_out;

unsigned long int *handle_in;


unsigned long int *handle_out;
real_T *data_out;

/* Puntero al indicador de entrada


de ejecucin de la presente
operacin. */
/* Puntero al indicador de salida
de ejecucin de la presente
operacin. */
/* Puntero al manejador de conexin
de entrada. */
/* Puntero al manejador de conexin
de salida. */
/* Datos de salida. */

/* Carga entradas del bloque Simulink. */


handle_in = (unsigned long int *) ssGetInputPortSignal(S, 0);
flag_in = (int *) ssGetInputPortSignal(S, 1);
/* Carga salidas del bloque Simulink. */
handle_out = (unsigned long int *) ssGetOutputPortSignal(S, 0);
flag_out = (int *) ssGetOutputPortSignal(S, 1);
data_out = (real_T *) ssGetOutputPortRealSignal(S, 2);
/* Ejecuta un ciclo Simulink. */
while(1)
{
/* Verifica si se solicita ejecutar un ciclo de la presente
operacin. */
if (!(*flag_in)) break;
/* Verifica que exista el manejador de conexin. */
if (!(*handle_in)) break;
/* Ejecuta un ciclo Simulink. */
if (!ModemPlcGetField_Output((void *) *handle_in,
(unsigned char) count, data_out))
break;

FernandoArielBeunza79156

763

Tesis de Grado en Ingeniera Informtica


/* Devuelve el manejador de comunicacin entre bloques Simulink del
Modem PLC. */
*handle_out = *handle_in;
*flag_out = 1;
return;
}
/* No se pudo ejecutar el ciclo de simulacin. */
*handle_out = 0;
*flag_out = 0;
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{
ModemPlcGetField_Terminate();
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

E.3.8. Archivo MODEM_PLC_REAL_TIME.C


/*
MODEM_PLC_REAL_TIME.C:
Se encarga de minimizar la diferencia entre el tiempo simulacin y el
tiempo real transcurrido.
*/
/* Especifica el nombre de la S-Function. */
#define S_FUNCTION_NAME
#define S_FUNCTION_LEVEL

Modem_PLC_Real_Time
2

/* Archivos includos necesarios. */


#include <windows.h>
#include <math.h>
#include <time.h>
#include "simstruc.h"
#include "tmwtypes.h"
#if defined(MATLAB_MEX_FILE)
#include "mex.h"
#endif

/* Variables globales. */
static int priority_thread;
static DWORD priority_process;
unsigned long int start_rtime;

/* Prioridad del hilo de


ejecucin. */
/* Prioridad del proceso. */
/* Primera muestra de tiempo real
transcurrido. */

/* Implementacin de funciones. */
/*
Funcin mdlInitializeSizes:
Establece las dimensiones de las entradas y salidas del bloque Simulink y
la cantidad de parmetros que requiere.

764

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


*/
static void mdlInitializeSizes(SimStruct *S)
{
/* Inicializa dimensiones de entradas y salidas. */
DECL_AND_INIT_DIMSINFO(inputDimsInfo);
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
/* Define la cantidad de parmetros que requiere el bloque Simulink. */
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;
/* Define la cantidad de entradas que requiere el bloque Simulink. */
if (!ssSetNumInputPorts(S, 0)) return;
/* Define la cantidad de salidas que requiere el bloque Simulink. */
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, DYNAMICALLY_SIZED);
ssSetNumIWork(S, DYNAMICALLY_SIZED);
ssSetNumPWork(S, DYNAMICALLY_SIZED);
ssSetNumModes(S, DYNAMICALLY_SIZED);
/* */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
/*
Funcin mdlInitializeSampleTimes:
Establece el tiempo de muestreo utilizado durante la simulacin.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
/* Establece el tiempo de muestreo. */
ssSetSampleTime(S, 0, 0.0);
ssSetOffsetTime(S, 0, 0.0);
/* Aumenta la prioridad del proceso encargado de la simulacin. */
priority_process = GetPriorityClass(GetCurrentProcess());
priority_thread = GetThreadPriority(GetCurrentThread());
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
}
/*
Funcin mdlOutputs:
Devuelve el resultado de la ejecucin de un ciclo de simulacin del bloque
Simulink.
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
/* Variables. */
LARGE_INTEGER freq;
LARGE_INTEGER ticks;
unsigned long int rtime;
unsigned long int stime;
real_T *time_diff;

/* Frecuencia de reloj. */
/* Cantidad de ticks
transcurridos. */
/* Tiempo real transcurrido. */
/* Tiempo de simulacin
transcurrido. */
/* Puntero a la direrencia entre
tiempo de simulacin y tiempo
real. */

/* Carga salidas del bloque Simulink. */


time_diff = (real_T *) ssGetOutputPortRealSignal(S, 0);
/* Obtiene el tiempo de simulacin transcurrido. */
stime = (unsigned long int) (ssGetT(S) - ssGetTStart(S)) * 1000;
/* Obtiene el tiempo real transcurrido con mxima precisin posible. */
ticks.QuadPart = 0;

FernandoArielBeunza79156

765

Tesis de Grado en Ingeniera Informtica


if (QueryPerformanceFrequency(&freq))
{
QueryPerformanceCounter(&ticks);
rtime = (unsigned long int)
((((double) (ticks.QuadPart)) * 1000) / freq.QuadPart);
}
else
rtime = (unsigned long int)
(((double) (clock()) / CLOCKS_PER_SEC) * 1000);
if (stime)
rtime -= start_rtime;
else
{
start_rtime = rtime;
rtime = 0;
}
/* Minimiza la diferencia entre el tiempo simulacin y el tiempo real
transcurrido. */
if (stime > rtime)
{
Sleep(stime - rtime);
*time_diff = (real_T) (stime - rtime);
}
else
*time_diff = -((real_T) (rtime - stime));
}
/*
Funcin mdlTerminate:
Finaliza la ejecucin de la simulacin del bloque Simulink.
*/
static void mdlTerminate(SimStruct *S)
{
SetPriorityClass(GetCurrentProcess(), priority_process);
SetThreadPriority(GetCurrentThread(), priority_thread);
}

/* Definido por Simulink. */


#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif

766

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice F: Implementacin del


dispositivo cliente
En el ste apndice se describe y detalla la implementacin del dispositivo cliente utilizado
para evaluar el funcionamiento del modem PLC. La implementacin incluye tanto el hardware que
conforma al dispositivo cliente como el cdigo fuente asociado al firmware del mismo.

F.1. Descripcin del dispositivo


El dispositivo cliente tiene la funcin de transformar los mensajes que viajan por medio de la
red PLC en acciones concretas. Dicho dispositivo posee una interfaz de comunicacin con la que se
conecta al modem PLC, y por la cual recibe y enva mensajes; una entrada de alimentacin que se
conecta a la alimentacin provista por el modem PLC, utilizada para alimentar los circuitos del
dispositivo cliente; y una entrada de alimentacin auxiliar que se conecta directamente a la red,
destinada a proporcionar energa a los bloques de potencia del dispositivo cliente.
Para poder transformar los mensajes en acciones concretas, el dispositivo cliente posee un
microcontrolador encargado de recibir los mensajes, y segn el contenido de los mismos, ejecutar
las acciones asociadas a dichos mensajes. En el caso particular del dispositivo implementado, las
acciones se reducen al encendido y apagado de tres luces. Tambin, el dispositivo cliente cuenta con
la posibilidad de detectar fallas en los focos de iluminacin antes de ser encendidos, a modo de
generar y enviar mensajes a otros dispositivos reportando la falla. El dispositivo cliente fue diseado
para proveer las mnimas funcionalidades a modo de probar el funcionamiento de las red PLC, y de
los modems conectados a sta ltima.

F.2. Implementacin del dispositivo


A continuacin se detalla el esquema del dispositivo cliente en donde se muestran cada uno
de los componentes descriptos con anterioridad. En la primer pgina se pueden observar la fuente de
alimentacin, la interfaz de comunicacin con el mdulo de procesamiento. En la segunda pgina se
puede observar el microcontrolador junto a su reloj. Por ltimo en la tercer pgina se puede observar
los bloques de control de potencia.

FernandoArielBeunza79156

767

Tesis de Grado en Ingeniera Informtica

768

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

FernandoArielBeunza79156

769

Tesis de Grado en Ingeniera Informtica

770

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

F.3. Cdigo fuente


EL cdigo fuente del dispositivo cliente consta de un solo archivo denominado
client_device.c que se detalla a continuacin:
/*
client_device:
Firmware del dispositivo cliente.
*/

/* Archivos includos necesarios. */


#define MODPLCAP_MSGSIZE 9
#include <stdio.h>
#include <at89x52.h>
#include "modplcap.h"

/* Definicin de SFR necesarias. */


__sfr __at (0xa7) WDTPRG;
__sfr __at (0xa6) WDTRST;

/* Configuracin del watchdog. */


/* Control del watchdog. */

/* Variables globales. */
/* Estado de las luces. */
unsigned char lights;
/* Posicin de las luces. */
unsigned char side;
/* Buffer de mensajes recibidos. */
modplcap_msg buffer;

/*
Funcin func:
Procesa los mensajes recibidos por medio de la conexin.
*/
void func(__data modplcap_hd *hd, __data modplcap_msg *msg, __data void *param)
__reentrant
{
/* Variables. */
modplcap_msg rmsg;
/* Mensaje de respuesta. */
modplcap_ftype type;
/* Tipo de parmetro. */
modplcap_msgid msgid;
/* Identificador de mensaje. */
unsigned char val;
/* Parmetro. */
unsigned char port;
/* Puerto. */
unsigned char count;
/* Multiplicidad del parmetro. */

/* Apaga todas las luces. */


port = P1;
P1 = 0xf8;
/* Procesa mensaje. */
while(1)
{
/* Recibe el mensaje. */
msgid = modplcap_getmsgid(msg);
modplcap_getfield(msg, &type, &count, &val);
/* Crea un mensaje de respuesta. */
modplcap_newmsg(hd, &rmsg, 0x02, 0x8001);
/* Verificacin de estado de focos de iluminacin. */
if (msgid == 0x8000)

FernandoArielBeunza79156

771

Tesis de Grado en Ingeniera Informtica


{
val = 0x00;
if (!(P3 & 0x08)) val |=
if (!(P3 & 0x08)) val |=
if (!((P3 & 0x10) || (P3
if (!(P3 & 0x20)) val |=
modplcap_putfield(&rmsg,

0x01;
0x02;
& 0x08))) val |= 0x04;
0x08;
MODPLCAP_UINT8TYPE, 1, &val);

}
/* Encendido/apagado de luz de guio derecho. */
else if ((msgid == 0x8001) && (side))
{
lights &= 0xf7;
if (val) lights |= 0x08;
}
/* Encendido/apagado de luz de guio izquierdo. */
else if ((msgid == 0x8002) && (!side))
{
lights &= 0xf7;
if (val) lights |= 0x08;
}
/* Encendido/apagado de luces de posicin, bajas y altas. */
else if (msgid == 0x8003)
{
lights &= 0xf8;
lights |= (val & 0x07);
}
/* Identificador de mensaje desconocido. */
else
break;
/* Devuelve estado de las luces. */
if ((msgid >= 0x8001) && (msgid <= 0x8003))
modplcap_putfield(&rmsg, MODPLCAP_UINT8TYPE, 1, &lights);
/* Enva respuesta. */
modplcap_sendmsg(&rmsg);
break;
}
/* Reestrablece el estado original de las luces. */
P1 = port;
param;
}

/*
Funcin main:
Funcin principal.
*/
void main(void)
{
/* Variables. */
unsigned short i;
__data modplcap_hd *hd;

/*
P1
P0
P2
P3

/* Contador. */
/* Manejador de conexin. */

Inicializa puertos. */
= 0xf8;
= 0xff;
= 0xff;
= 0xff;

/* Inicializa el estado de las luces. */


lights = 0x00;
side = (P1 >> 3) & 0x01;
/* Ciclo de ejecucin. */

772

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


while(1)
{
/*
hd
if
if
if
if
if

Inicializa la conexin. */
= modplcap_init(1);
(!hd) break;
(!modplcap_setbuffer(hd, &buffer)) break;
(!modplcap_notify(hd, func, NULL)) break;
(!modplcap_publish(hd, 2)) break;
(!modplcap_subscribe(hd, 1)) break;

/* Actualiza estado de las luces. */


i = 0;
while(1)
{
/* Verifica el estado del dispositivo. */
if (!i)
{
if (!modplcap_status(hd)) break;
}
/* Actualiza estado de luz de guio. */
if (lights & 0x08)
{
if (!(i & 0x7fff)) P1 = (P1 & 0xfb) | ((P1 ^ 0x04) & 0x04);
}
else
P1 &= 0xfb;
/* Actualiza estado de luces de posicin, bajas y altas. */
switch(lights & 0x07)
{
/* Luces apagadas. */
case 0x00:
P1 &= 0xfc;
break;
/* Luces de posicin. */
case 0x01:
P1 &= 0xfc;
if (P3 & 0x08) break;
if (!(i & 0x0001)) P1 |= ((P1 ^ 0x01) & 0x01);
break;
/* Luces bajas. */
case 0x02:
P1 &= 0xfc;
if (P3 & 0x08) break;
P1 |= 0x01;
break;
/* Luces altas. */
case 0x03:
P1 &= 0xfc;
if ((P3 & 0x10) || (P3 & 0x08)) break;
P1 |= 0x03;
break;
/* Otra configuracin. */
default:
break;
}
/* Actualiza contador. */
i ++;
}
/* Finaliza la conexin. */
modplcap_leave(hd, 2);
modplcap_leave(hd, 1);
modplcap_release(hd);
break;

FernandoArielBeunza79156

773

Tesis de Grado en Ingeniera Informtica


}
/* Fuerza el reinicio del dispositivo. */
P1 = 0xf8;
WDTPRG = 0x07;
WDTRST = 0x1e;
WDTRST = 0xe1;
while(1);
}

774

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Apndice G: Implementacin de pruebas


En el presente apndice se realiza la descripcin y el detalle de las implementaciones de las
aplicaciones de prueba destinadas a evaluar el funcionamiento del modem PLC. Las
implementaciones se especifican por medio del cdigo fuente correspondiente tanto a la plataforma
Windows como Linux.

G.1. Descripcin
Para evaluar el funcionamiento del sistema propuesto en el presente trabajo se implementa
una red compuesta por dos modems PLC, un dispositivo cliente real y un dispositivo cliente virtual.
El dispositivo cliente real se conecta a uno de los modems, mientras que el dispositivo cliente
virtual consiste en una aplicacin que se ejecuta en una PC que se conecta al otro modem. Gracias a
que el driver de la interfaz RS232 (ver Apndice C) presenta una funcin de depuracin que permite
ver el trfico de mensajes, y a que el modem PLC por medio de una conexin especial permite
visualizar por medio de una PC el trfico de mensajes entre el dispositivo cliente real y el modem
PLC; no es necesario implementar un dispositivo especial de diagnstico (que requerira de otro
modem PLC), ni una aplicacin de diagnstico corriendo en paralelo al la aplicacin que simula al
dispositivo cliente virtual en la PC, para supervisar el funcionamiento de la red de prueba.
La evaluacin al sistema se realiza a dos niveles: nivel capa fsica y nivel capa de aplicacin.
El objetivo de la evaluacin a nivel de capa fsica es evaluar el desempeo de los aspectos fsicos de
los modems PLC implementados. En cambio, la evaluacin a nivel de capa de aplicacin se
concentra en evaluar el comportamiento del sistema desarrollado en forma conjunta.
Para realizar la evaluacin a nivel de capa fsica se desarrolla una aplicacin de prueba que
permite determinar la tasa de bits errados y la calidad del canal de comunicacin.
Las aplicaciones de prueba para evaluar el sistema a nivel de capa de aplicacin
corresponden a los dispositivos clientes virtuales. Una de las aplicaciones de prueba consiste en un
modelo Simulink, la otra consiste en una aplicacin desarrollada en lenguaje C y C++ para
plataforma Windows y Linux.

G.2. Red de prueba implementada


Como se mencion con anterioridad, para la realizacin de las distintas pruebas se utiliza
una red compuesta por dos modems PLC, un dispositivo cliente real, una PC; adems de ciertos
componentes como una fuente de alimentacin para simular una batera y un filtro de rechazo de
banda para que la fuente de alimentacin no absorba la seal de informacin. La composicin de la
red puede observarse en la figura G1.

FernandoArielBeunza79156

775

Tesis de Grado en Ingeniera Informtica

Figura G1. Red implementada.

Como se puede ver en la figura anterior, a la derecha se puede observar el dispositivo cliente real
junto con su modem PLC. A la izquierda, hacia el fondo, se puede observar el otro modem PLC que
se conecta a la PC. A la izquierda, hacia adelante se puede observar la fuente de alimentacin que
simula la batera conectada al filtro de rechazo de banda. ste filtro de rechazo de banda puede
observarse ms en detalle en la figura G2.

Figura G2. Filtro de rechazo de banda.

El filtro de rechazo de banda simplemente consiste en un inductor cuya funcin es bloquear


el paso de la seal de informacin emitida por los modems PLC hacia la fuente de alimentacin.
En la figura G3 se puede observar el dispositivo cliente real (izquierda) conectado uno de los
modems PLC (derecha). El dispositivo cliente es alimentado en parte por la energa proveniente
776

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


directamente de la lnea y tambin por el modem PLC (que tiene capacidad de suministrar una
alimentacin limitada). La transferencia de datos entre el dispositivo cliente y el modem PLC se
lleva a cabo por medio de tres conductores (TX, RX y GND). La interfaz RS232 que posee el
modem PLC se encuentra conectada para poder visualizar por medio de una PC las comunicaciones
entre el dispositivo cliente y el modem PLC.

Figura G3. Modem PLC conectado al dispositivo cliente.

En la figura G4 se puede observar el modem PLC conectado a la PC donde se ejecuta la


aplicacin que implementa al dispositivo cliente virtual. Las comunicaciones entre la PC y el
modem PLC se realizan por medio de la interfaz RS232 que se conecta al puerto serie de la PC (o a
un puerto USB por medio de un adaptador, como sucede en ste caso).

Figura G4. Modem PLC conectado a una PC.

FernandoArielBeunza79156

777

Tesis de Grado en Ingeniera Informtica

G.3. Modelo Simulink de prueba


El modelo Simulink que implementa que implementa el dispositivo cliente virtual consiste
en una seal generada por el correspondiente bloque funcional, que enciende y apaga uno de los
focos del dispositivo cliente virtual por medio del envo de mensajes. El dispositivo cliente real
tambin enva un mensaje de respuesta que es recibido y mostrado por el bloque osciloscopio, junto
con la seal de activacin original.

Figura G5. Modelo Simulink de prueba.

En la figura G5 se observan todos los bloques funcionales que intervienen en el envo y


recepcin de mensajes. En la parte superior, recorriendo de izquierda a derecha, el primer bloque es
el encargado de establecer la conexin con el modem PLC, el segundo se encarga de crear un
mensaje, el tercero agrega un campo al mensaje creado, el cuarto enva el mensaje hacia el
dispositivo cliente real, el quinto recibe un mensaje del dispositivo cliente real, y el ltimo extrae el
campo de datos con la informacin recibida del mensaje recibido.

G.4. Aplicaciones C/C++ de prueba


Aqu se detalla el cdigo fuente de cada una de las aplicaciones desarrolladas en lenguaje C
y C++ que simulan un dispositivo cliente virtual, utilizadas para evaluar del sistema de
comunicacin desarrollado. Dichas aplicaciones de prueba se encuentran implementadas tanto en
plataforma Windows como en Linux. A continuacin se mencionan cada uno de los archivos fuente
correspondientes a las aplicaciones de prueba:

778

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Archivo testphy.c: en este archivo se encuentran implementadas las pruebas realizadas


sobre la capa fsica del modem PLC.

Archivo testap.c: en este archivo se encuentra implementado (en lenguaje C) el


dispositivo cliente virtual utilizado para realizar pruebas sobre la capa de aplicacin del
modem PLC.

Archivo testapcpp.cpp: en este archivo se encuentra implementado (en lenguaje C++) el


dispositivo cliente virtual utilizado para realizar pruebas sobre la capa de aplicacin del
modem PLC.

G.4.1. Plataforma Windows


A continuacin se detalla cada uno de los archivos fuente correspondientes a las aplicaciones
de prueba para plataforma Windows.

G.4.1.1. Archivo testphy.c


/*
testphy.c:
Pruebas de funcionamiento de la capa fsica del modem PLC.
*/

/* Archivos includos necesarios. */


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "..\..\..\modem_driver\windows\modplcphy\modplcphy.h"

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port1;
int port2;
int badframe;
size_t i;
size_t size;
size_t framesize;
unsigned long int
unsigned long int
unsigned long int
unsigned long int
unsigned long int
unsigned long int
unsigned long int

c;
dist;
frames;
badbits;
lostbits;
sentbits;
badframes;

unsigned long int lostframes;


double difftime;
clock_t clock1;
clock_t clock2;
unsigned char diff;

FernandoArielBeunza79156

/* Puerto serie utilizado. */


/* Puerto serie utilizado. */
/* Indicador de trama
corrompida. */
/* Contador. */
/* Tamao de trama
enviada/recibida. */
/* Tamao de trama. */
/* Contador de ciclos de prueba. */
/* Distancia. */
/* Cantidad de tramas de prueba. */
/* Cantidad de bits errados. */
/* Cantidad de bits perdidos. */
/* Cantidad de bits enviados. */
/* Cantidad de tramas
corrompidas. */
/* Cantidad de tramas prdidas. */
/* Diferencia de tiempo. */
/* Tiempo inicial. */
/* Tiempo final. */
/* Diferencia entre bytes. */

779

Tesis de Grado en Ingeniera Informtica


modplcphy_hd *hd1;

/* Manejador de interfaz
capa fsica del modem
/* Manejador de interfaz
capa fsica del modem
/* Trama de prueba, */
/* Trama de prueba. */

modplcphy_hd *hd2;
unsigned char *frame1;
unsigned char *frame2;

con la
PLC. */
con la
PLC. */

/* Carga parmetros. */
if (argc < 4) return -1;
port1 = atoi(argv[1]);
port2 = atoi(argv[2]);
frames = atoi(argv[3]);
/* Carga biblioteca. */
if (!modplcphy_loadlib()) return 0;
/* Prueba. */
while(1)
{
/* Inicializa conexiones con capa fsica. */
hd1 = modplcphy_init(port1);
if (!hd1) break;
hd2 = modplcphy_init(port2);
if (!hd2) break;
/* Obtiene el tamao mximo de trama. */
framesize = modplcphy_getpayloadsize(hd1, 0);
if (framesize > modplcphy_getpayloadsize(hd2, 0))
framesize = modplcphy_getpayloadsize(hd2, 0);
/* Reserva memoria para almacenar las tramas de prueba. */
frame1 = (unsigned char *) malloc(sizeof(unsigned char) * framesize);
if (!frame1) break;
frame2 = (unsigned char *) malloc(sizeof(unsigned char) * framesize);
if (!frame2) break;
/* Inicializa contadores. */
badbits = 0;
lostbits = 0;
sentbits = 0;
badframes = 0;
lostframes = 0;
/* Inicia la secuencia pseudoaleatoria. */
srand((unsigned) time(NULL));
/* Prueba de envo y recepcin de tramas. */
for(c = 1; c <= frames; c++)
{
/* Genera trama de prueba. */
printf("ciclo %li - ", c);
size = (rand() % framesize) + 1;
switch(rand() % 14)
{
/* Patrn 00000000. */
case 0:
printf("patrn 00000000 - ");
for(i = 0; i < size; i++) frame1[i] = 0x00;
break;
/* Patrn 11111111. */
case 1:
printf("patrn 11111111 - ");
for(i = 0; i < size; i++) frame1[i] = 0xff;
break;
/* Patrn 01010101. */
case 2:
printf("patrn 01010101 - ");
for(i = 0; i < size; i++) frame1[i] = 0x55;

780

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


break;
/* Patrn 10101010. */
case 3:
printf("patrn 10101010 - ");
for(i = 0; i < size; i++) frame1[i] = 0xaa;
break;
/* Patrn 00110011. */
case 4:
printf("patrn 00110011 - ");
for(i = 0; i < size; i++) frame1[i] = 0x33;
break;
/* Patrn 11001100. */
case 5:
printf("patrn 11001100 - ");
for(i = 0; i < size; i++) frame1[i] = 0xcc;
break;
/* Patrn 01100110. */
case 6:
printf("patrn 01100110 - ");
for(i = 0; i < size; i++) frame1[i] = 0x66;
break;
/* Patrn 10011001. */
case 7:
printf("patrn 10011001 - ");
for(i = 0; i < size; i++) frame1[i] = 0x99;
break;
/* Patrn 00001111. */
case 8:
printf("patrn 00001111 - ");
for(i = 0; i < size; i++) frame1[i] = 0x0f;
break;
/* Patrn 11110000. */
case 9:
printf("patrn 11110000 - ");
for(i = 0; i < size; i++) frame1[i] = 0xf0;
break;
/* Patrn 00111100. */
case 10:
printf("patrn 00111100 - ");
for(i = 0; i < size; i++) frame1[i] = 0x3c;
break;
/* Patrn 11000011. */
case 11:
printf("patrn 11000011 - ");
for(i = 0; i < size; i++) frame1[i] = 0xc3;
break;
/* Patrn secuencia. */
case 12:
printf("patrn secuencia - ");
for(i = 0; i < size; i++) frame1[i] = (char) (i & 0x00ff);
break;
/* Patrn aleatorio. */
case 13:
printf("patrn aleatorio - ");
for(i = 0; i < size; i++)
frame1[i] = (char) ((rand() % 256) & 0x00ff);
break;
}
/* Limpia el buffer del receptor. */

FernandoArielBeunza79156

781

Tesis de Grado en Ingeniera Informtica


modplcphy_clrbuffer(hd2, 0);
/* Establece el modo captura para el receptor. */
modplcphy_capframe(hd2, 0, size);
/* Enva trama de prueba. */
clock1 = clock();
size = modplcphy_sndframe(hd1, 0, frame1, size);
if (!size)
{
badframes ++;
continue;
}
sentbits += (size * 8);
/* Recibe trama de prueba. */
if (!modplcphy_poll(hd2, 0))
{
printf("%li bits - trama perdida\r\n", size * 8);
lostbits += (size * 8);
lostframes ++;
continue;
}
size = modplcphy_getframe(hd2, 0, frame2, size);
clock2 = clock();
/* Calcula el tiempo entre envo y recepcin. */
difftime = ((double) (clock2 - clock1) / CLOCKS_PER_SEC) * 1000;
printf("%li bits - %.1f milisegundos\r\n", size * 8, difftime);
/* Cuenta los errores ocurridos. */
badframe = 0;
for(i = 0; i < size; i++)
{
dist = badbits;
diff = frame1[i] ^ frame2[i];
if (diff & 0x80) badbits ++;
if (diff & 0x40) badbits ++;
if (diff & 0x20) badbits ++;
if (diff & 0x10) badbits ++;
if (diff & 0x08) badbits ++;
if (diff & 0x04) badbits ++;
if (diff & 0x02) badbits ++;
if (diff & 0x01) badbits ++;
dist = badbits - dist;
if (!dist) continue;
badframe = 1;
}
if (badframe) badframes ++;
}
/* Imprime resultados de la prueba. */
printf("\r\n");
printf("Bits enviados: %li\r\n", sentbits);
printf("Bits perdidos: %li (%.3f%%)\r\n",
lostbits,
((double) lostbits / (double) sentbits) * 100);
printf("Bits errados: %li (%.3f%%)\r\n",
badbits,
((double) badbits / (double) sentbits) * 100);
printf("Tramas enviadas: %li\r\n", frames);
printf("Tramas prdidas: %li (%.3f%%)\r\n",
lostframes,
((double) lostframes / (double) frames) * 100);
printf("Tramas corrompidas: %li (%.3f%%)\r\n",
badframes,
((double) badframes / (double) frames) * 100);
printf("\r\n");
break;
}

782

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Libera memoria reservada para almacenar tramas de prueba. */
if (frame2) free(frame2);
if (frame1) free(frame1);
/* Finaliza las conexiones. */
modplcphy_release(hd2);
modplcphy_release(hd1);
/* Fin. */
return 0;
}

G.4.1.2. Archivo testap.c


/*
testap.c:
Pruebas de funcionamiento de la capa de aplicacin del modem PLC.
*/

/* Archivos includos necesarios. */


#include <stdio.h>
#include <windows.h>
#include "..\..\..\modem_driver\windows\modplcap\modplcap.h"

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port;
unsigned char count;
unsigned char status;
modplcap_ftype type;
modplcap_msg msg;
modplcap_hd *hd;

/*
/*
/*
/*
/*
/*

Puerto serie utilizado. */


Multiplicidad. */
Estado de los faros. */
Tipo de campo. */
Mensaje. */
Manejador de interfaz con la
capa de aplicacin del modem
PLC. */

/* Carga parmetros. */
if (argc < 2) return -1;
port = atoi(argv[1]);
/* Carga biblioteca. */
if (!modplcap_loadlib()) return 0;
/* Prueba. */
while(1)
{
/* Inicializa la conexin con capa de aplicacin. */
hd = modplcap_init(port);
if (!hd) break;
/* Suscripcin a grupos de difusin. */
if (!modplcap_publish(hd, 1)) break;
if (!modplcap_subscribe(hd, 2)) break;
/* Verifica el estado de los focos. */
printf("Verificacin de estado de focos\r\n\n");
modplcap_newmsg(hd, &msg, 1, 0x8000);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
if (!modplcap_receivemsg(hd, &msg)) break;
modplcap_getfield(&msg, &type, &count, &status);
modplcap_destroymsg(&msg);

FernandoArielBeunza79156

783

Tesis de Grado en Ingeniera Informtica


printf("* Estado luz de posicin
if (status & 0x01)
printf("OK\r\n");
else
printf("Falla\r\n");
printf("* Estado luz de baja
if (status & 0x02)
printf("OK\r\n");
else
printf("Falla\r\n");
printf("* Estado luz de alta
if (status & 0x04)
printf("OK\r\n");
else
printf("Falla\r\n");
printf("* Estado luz de guio
if (status & 0x08)
printf("OK\r\n");
else
printf("Falla\r\n");

: ");

: ");

: ");

: ");

/* Encendido de luz de guio derecho. */


printf("\r\nEncendido de luz de guio derecho ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8001);
status = 0x01;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Apagado de luz de guio derecho. */
printf("Apagado de luz de guio derecho ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8001);
status = 0x00;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luz de guio izquierdo. */
printf("Encendido de luz de guio izquierdo ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8002);
status = 0x01;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Apagado de luz de guio izquierdo. */
printf("Apagado de luz de guio izquierdo ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8002);
status = 0x00;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luces de posicin. */
printf("Encendido de luces de posicin ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x01;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);

784

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Encendido de luces bajas. */
printf("Encendido de luces bajas ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x02;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luces altas. */
printf("Encendido de luces altas ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x03;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Apagado de luces de iluminacin. */
printf("Apagado de luz luces de iluminacin ");
printf("(presione una tecla para continuar)\r\n\n");
getchar();
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x00;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
break;
}
/* Finaliza la conexin. */
modplcap_release(hd);
/* Fin. */
return 0;
}

G.4.1.3. Archivo testapcpp.cpp


/*
testapcpp.c:
Pruebas de funcionamiento de la capa de aplicacin del modem PLC.
*/

/* Archivos includos necesarios. */


#include <iostream>
#include <windows.h>
#include "..\..\..\modem_driver\windows\modplcapcpp\modplcapcpp.h"

using namespace std;

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port;
unsigned char count;
unsigned char status;
modplcapcpp_ftype type;
modplcapcpp_msg *msg;
modplcapcpp *hd;

FernandoArielBeunza79156

/*
/*
/*
/*
/*
/*

Puerto serie utilizado. */


Multiplicidad. */
Estado de los faros. */
Tipo de campo. */
Mensaje. */
Manejador de interfaz con la

785

Tesis de Grado en Ingeniera Informtica


capa de aplicacin del modem
PLC. */

/* Carga parmetros. */
if (argc < 2) return -1;
port = atoi(argv[1]);
/* Prueba. */
while(1)
{
/* Inicializa la conexin con capa de aplicacin. */
hd = new modplcapcpp(port);
if (!hd) break;
/* Suscripcin a grupos de difusin. */
if (!hd->publish(1)) break;
if (!hd->subscribe(2)) break;
/* Verifica el estado de los focos. */
cout << "Verificacin de estado de focos" << endl << endl;
msg = new modplcapcpp_msg(hd, 1, 0x8000);
if (!msg) break;
msg->sendmsg();
delete msg;
msg = new modplcapcpp_msg(hd);
if (!msg) break;
msg->getfield(&type, &count, &status);
delete msg;
cout << "* Estado luz de posicin : ";
if (status & 0x01)
cout << "OK" << endl;
else
cout << "Falla" << endl;
cout << "* Estado luz de baja
: ";
if (status & 0x02)
cout << "OK" << endl;
else
cout << "Falla" << endl;
cout << "* Estado luz de alta
: ";
if (status & 0x04)
cout << "OK" << endl;
else
cout << "Falla" << endl;
cout << "* Estado luz de guio
: ";
if (status & 0x08)
cout << "OK" << endl;
else
cout << "Falla" << endl;
/* Encendido de luz de guio derecho. */
cout << endl << "Encendido de luz de guio derecho ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8001);
if (!msg) break;
status = 0x01;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Apagado de luz de guio derecho. */
cout << "Apagado de luz de guio derecho ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8001);
if (!msg) break;
status = 0x00;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;

786

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


/* Encendido de luz de guio izquierdo. */
cout << "Encendido de luz de guio izquierdo ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8002);
if (!msg) break;
status = 0x01;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;;
/* Apagado de luz de guio izquierdo. */
cout << "Apagado de luz de guio izquierdo ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8002);
if (!msg) break;
status = 0x00;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luces de posicin. */
cout << "Encendido de luces de posicin ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x01;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luces bajas. */
cout << "Encendido de luces bajas ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x02;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luces altas. */
cout << "Encendido de luces altas ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x03;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Apagado de luces de iluminacin. */
cout << "Apagado de luz luces de iluminacin ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x00;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
break;
}
/* Finaliza la conexin. */
delete hd;

FernandoArielBeunza79156

787

Tesis de Grado en Ingeniera Informtica


/* Fin. */
return 0;
}

G.4.2. Plataforma Linux


A continuacin se detalla cada uno de los archivos fuente correspondientes a las aplicaciones
de prueba para plataforma Linux.

G.4.2.1. Archivo testphy.c


/*
testphy.c:
Pruebas de funcionamiento de la capa fsica del modem PLC.
*/

/* Archivos includos necesarios. */


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include "../../../modem_driver/linux/modplcphy/modplcphy.h"

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port1;
int port2;
int badframe;
size_t i;
size_t size;
size_t framesize;
unsigned long int
unsigned long int
unsigned long int
unsigned long int
unsigned long int
unsigned long int
unsigned long int

c;
dist;
frames;
badbits;
lostbits;
sentbits;
badframes;

unsigned long int lostframes;


double difftime;
struct timeval time1;
struct timeval time2;
unsigned char diff;
modplcphy_hd *hd1;
modplcphy_hd *hd2;
unsigned char *frame1;
unsigned char *frame2;

/* Puerto serie utilizado. */


/* Puerto serie utilizado. */
/* Indicador de trama
corrompida. */
/* Contador. */
/* Tamao de trama
enviada/recibida. */
/* Tamao de trama. */
/* Contador de ciclos de prueba. */
/* Distancia. */
/* Cantidad de tramas de prueba. */
/* Cantidad de bits errados. */
/* Cantidad de bits perdidos. */
/* Cantidad de bits enviados. */
/* Cantidad de tramas
corrompidas. */
/* Cantidad de tramas prdidas. */
/* Diferencia de tiempo. */
/* Tiempo inicial. */
/* Tiempo final. */
/* Diferencia entre bytes. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Manejador de interfaz con la
capa fsica del modem PLC. */
/* Trama de prueba, */
/* Trama de prueba. */

/* Carga parmetros. */
if (argc < 4) return -1;
port1 = atoi(argv[1]);

788

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


port2 = atoi(argv[2]);
frames = atoi(argv[3]);
/* Prueba. */
while(1)
{
/* Inicializa conexiones con capa fsica. */
hd1 = modplcphy_init(port1);
if (!hd1) break;
hd2 = modplcphy_init(port2);
if (!hd2) break;
/* Obtiene el tamao mximo de trama. */
framesize = modplcphy_getpayloadsize(hd1, 0);
if (framesize > modplcphy_getpayloadsize(hd2, 0))
framesize = modplcphy_getpayloadsize(hd2, 0);
/* Reserva memoria para almacenar las tramas de prueba. */
frame1 = (unsigned char *)
malloc(sizeof(unsigned char) * framesize);
if (!frame1) break;
frame2 = (unsigned char *)
malloc(sizeof(unsigned char) * framesize);
if (!frame2) break;
/* Inicializa contadores. */
badbits = 0;
lostbits = 0;
sentbits = 0;
badframes = 0;
lostframes = 0;
/* Inicia la secuencia pseudoaleatoria. */
srand((unsigned) time(NULL));
/* Prueba de envo y recepcin de tramas. */
for(c = 1; c <= frames; c++)
{
/* Genera trama de prueba. */
printf("ciclo %li - ", c);
size = (rand() % framesize) + 1;
switch(rand() % 14)
{
/* Patrn 00000000. */
case 0:
printf("patrn 00000000 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x00;
break;
/* Patrn 11111111. */
case 1:
printf("patrn 11111111 - ");
for(i = 0; i < size; i++)
frame1[i] = 0xff;
break;
/* Patrn 01010101. */
case 2:
printf("patrn 01010101 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x55;
break;
/* Patrn 10101010. */
case 3:
printf("patrn 10101010 - ");
for(i = 0; i < size; i++)
frame1[i] = 0xaa;
break;

FernandoArielBeunza79156

789

Tesis de Grado en Ingeniera Informtica


/* Patrn 00110011. */
case 4:
printf("patrn 00110011 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x33;
break;
/* Patrn 11001100. */
case 5:
printf("patrn 11001100 - ");
for(i = 0; i < size; i++)
frame1[i] = 0xcc;
break;
/* Patrn 01100110. */
case 6:
printf("patrn 01100110 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x66;
break;
/* Patrn 10011001. */
case 7:
printf("patrn 10011001 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x99;
break;
/* Patrn 00001111. */
case 8:
printf("patrn 00001111 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x0f;
break;
/* Patrn 11110000. */
case 9:
printf("patrn 11110000 - ");
for(i = 0; i < size; i++)
frame1[i] = 0xf0;
break;
/* Patrn 00111100. */
case 10:
printf("patrn 00111100 - ");
for(i = 0; i < size; i++)
frame1[i] = 0x3c;
break;
/* Patrn 11000011. */
case 11:
printf("patrn 11000011 - ");
for(i = 0; i < size; i++)
frame1[i] = 0xc3;
break;
/* Patrn secuencia. */
case 12:
printf("patrn secuencia - ");
for(i = 0; i < size; i++)
frame1[i] =
(char) (i & 0x00ff);
break;
/* Patrn aleatorio. */
case 13:
printf("patrn aleatorio - ");
for(i = 0; i < size; i++)
frame1[i] = (char)
((rand() % 256) &
0x00ff);

790

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


break;
}
/* Limpia el buffer del receptor. */
modplcphy_clrbuffer(hd2, 0);
/* Establece el modo captura para el receptor. */
modplcphy_capframe(hd2, 0, size);
/* Enva trama de prueba. */
gettimeofday(&time1, NULL);
size = modplcphy_sndframe(hd1, 0, frame1, size);
if (!size)
{
badframes ++;
continue;
}
sentbits += (size * 8);
/* Recibe trama de prueba. */
if (!modplcphy_poll(hd2, 0))
{
printf("%li bits - trama perdida\r\n",
size * 8);
lostbits += (size * 8);
lostframes ++;
continue;
}
size = modplcphy_getframe(hd2, 0, frame2, size);
gettimeofday(&time2, NULL);
/* Calcula el tiempo entre envo y recepcin. */
difftime =
((double) (time2.tv_sec - time1.tv_sec) * 1000 +
(double) (time2.tv_usec - time1.tv_usec) /
1000.0) + 0.5;
printf("%li bits - %.1f milisegundos\r\n",
size * 8, difftime);
/* Cuenta los errores ocurridos. */
badframe = 0;
for(i = 0; i < size; i++)
{
dist = badbits;
diff = frame1[i] ^ frame2[i];
if (diff & 0x80) badbits ++;
if (diff & 0x40) badbits ++;
if (diff & 0x20) badbits ++;
if (diff & 0x10) badbits ++;
if (diff & 0x08) badbits ++;
if (diff & 0x04) badbits ++;
if (diff & 0x02) badbits ++;
if (diff & 0x01) badbits ++;
dist = badbits - dist;
if (!dist) continue;
badframe = 1;
}
if (badframe) badframes ++;
}
/* Imprime resultados de la prueba. */
printf("\r\n");
printf("Bits enviados: %li\r\n", sentbits);
printf("Bits perdidos: %li (%.3f%%)\r\n",
lostbits,
((double) lostbits / (double) sentbits) * 100);
printf("Bits errados: %li (%.3f%%)\r\n",
badbits,
((double) badbits / (double) sentbits) * 100);
printf("Tramas enviadas: %li\r\n", frames);
printf("Tramas prdidas: %li (%.3f%%)\r\n",

FernandoArielBeunza79156

791

Tesis de Grado en Ingeniera Informtica


lostframes,
((double) lostframes / (double) frames) * 100);
printf("Tramas corrompidas: %li (%.3f%%)\r\n",
badframes,
((double) badframes / (double) frames) * 100);
printf("\r\n");
break;
}
/* Libera memoria reservada para almacenar tramas de prueba. */
if (frame2) free(frame2);
if (frame1) free(frame1);
/* Finaliza las conexiones. */
modplcphy_release(hd2);
modplcphy_release(hd1);
/* Fin. */
return 0;
}

G.4.2.2. Archivo testap.c


/*
testap.c:
Pruebas de funcionamiento de la capa de aplicacin del modem PLC.
*/

/* Archivos includos necesarios. */


#include <stdio.h>
#include <stdlib.h>
#include "../../../modem_driver/linux/modplcap/modplcap.h"

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */
int port;
unsigned char count;
unsigned char status;
modplcap_ftype type;
modplcap_msg msg;
modplcap_hd *hd;

/*
/*
/*
/*
/*
/*

Puerto serie utilizado. */


Multiplicidad. */
Estado de los faros. */
Tipo de campo. */
Mensaje. */
Manejador de interfaz con la
capa de aplicacin del modem
PLC. */

/* Carga parmetros. */
if (argc < 2) return -1;
port = atoi(argv[1]);
/* Prueba. */
while(1)
{
/* Inicializa la conexin con capa de aplicacin. */
hd = modplcap_init(port);
if (!hd) break;
/* Suscripcin a grupos de difusin. */
if (!modplcap_publish(hd, 1)) break;
if (!modplcap_subscribe(hd, 2)) break;
/* Verifica el estado de los focos. */
printf("Verificacin de estado de focos\r\n\n");

792

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


modplcap_newmsg(hd, &msg, 1, 0x8000);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
if (!modplcap_receivemsg(hd, &msg)) break;
modplcap_getfield(&msg, &type, &count, &status);
modplcap_destroymsg(&msg);
printf("* Estado luz de posicin : ");
if (status & 0x01)
printf("OK\r\n");
else
printf("Falla\r\n");
printf("* Estado luz de baja
: ");
if (status & 0x02)
printf("OK\r\n");
else
printf("Falla\r\n");
printf("* Estado luz de alta
: ");
if (status & 0x04)
printf("OK\r\n");
else
printf("Falla\r\n");
printf("* Estado luz de guio
: ");
if (status & 0x08)
printf("OK\r\n");
else
printf("Falla\r\n");
/* Encendido de luz de guio derecho. */
printf("\r\nEncendido de luz de guio derecho ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8001);
status = 0x01;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Apagado de luz de guio derecho. */
printf("Apagado de luz de guio derecho ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8001);
status = 0x00;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luz de guio izquierdo. */
printf("Encendido de luz de guio izquierdo ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8002);
status = 0x01;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Apagado de luz de guio izquierdo. */
printf("Apagado de luz de guio izquierdo ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8002);
status = 0x00;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luces de posicin. */
printf("Encendido de luces de posicin ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);

FernandoArielBeunza79156

793

Tesis de Grado en Ingeniera Informtica


modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x01;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luces bajas. */
printf("Encendido de luces bajas ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x02;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Encendido de luces altas. */
printf("Encendido de luces altas ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x03;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
/* Apagado de luces de iluminacin. */
printf("Apagado de luz luces de iluminacin ");
printf("(presione una tecla para continuar)\r\n\n");
getc(stdin);
modplcap_newmsg(hd, &msg, 1, 0x8003);
status = 0x00;
modplcap_putfield(&msg, MODPLCAP_UINT8TYPE, 1, &status);
modplcap_sendmsg(&msg);
modplcap_destroymsg(&msg);
break;
}
/* Finaliza la conexin. */
modplcap_release(hd);
/* Fin. */
return 0;
}

G.4.2.3. Archivo testapcpp.cpp


/*
testapcpp.c:
Pruebas de funcionamiento de la capa de aplicacin del modem PLC.
*/

/* Archivos includos necesarios. */


#include <iostream>
#include <stdlib.h>
#include "../../../modem_driver/linux/modplcapcpp/modplcapcpp.h"

using namespace std;

/*
Funcin main.
*/
int main(int argc, char *argv[])
{
/* Variables. */

794

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


int port;
unsigned char count;
unsigned char status;
modplcapcpp_ftype type;
modplcapcpp_msg *msg;
modplcapcpp *hd;

/*
/*
/*
/*
/*
/*

Puerto serie utilizado. */


Multiplicidad. */
Estado de los faros. */
Tipo de campo. */
Mensaje. */
Manejador de interfaz con la
capa de aplicacin del modem
PLC. */

/* Carga parmetros. */
if (argc < 2) return -1;
port = atoi(argv[1]);
/* Prueba. */
while(1)
{
/* Inicializa la conexin con capa de aplicacin. */
hd = new modplcapcpp(port);
if (!hd) break;
/* Suscripcin a grupos de difusin. */
if (!hd->publish(1)) break;
if (!hd->subscribe(2)) break;
/* Verifica el estado de los focos. */
cout << "Verificacin de estado de focos" << endl << endl;
msg = new modplcapcpp_msg(hd, 1, 0x8000);
if (!msg) break;
msg->sendmsg();
delete msg;
msg = new modplcapcpp_msg(hd);
if (!msg) break;
msg->getfield(&type, &count, &status);
delete msg;
cout << "* Estado luz de posicin : ";
if (status & 0x01)
cout << "OK" << endl;
else
cout << "Falla" << endl;
cout << "* Estado luz de baja
: ";
if (status & 0x02)
cout << "OK" << endl;
else
cout << "Falla" << endl;
cout << "* Estado luz de alta
: ";
if (status & 0x04)
cout << "OK" << endl;
else
cout << "Falla" << endl;
cout << "* Estado luz de guio
: ";
if (status & 0x08)
cout << "OK" << endl;
else
cout << "Falla" << endl;
/* Encendido de luz de guio derecho. */
cout << endl << "Encendido de luz de guio derecho ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8001);
if (!msg) break;
status = 0x01;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Apagado de luz de guio derecho. */
cout << "Apagado de luz de guio derecho ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();

FernandoArielBeunza79156

795

Tesis de Grado en Ingeniera Informtica


msg = new modplcapcpp_msg(hd, 1, 0x8001);
if (!msg) break;
status = 0x00;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luz de guio izquierdo. */
cout << "Encendido de luz de guio izquierdo ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8002);
if (!msg) break;
status = 0x01;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;;
/* Apagado de luz de guio izquierdo. */
cout << "Apagado de luz de guio izquierdo ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8002);
if (!msg) break;
status = 0x00;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luces de posicin. */
cout << "Encendido de luces de posicin ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x01;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luces bajas. */
cout << "Encendido de luces bajas ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x02;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Encendido de luces altas. */
cout << "Encendido de luces altas ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x03;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();
delete msg;
/* Apagado de luces de iluminacin. */
cout << "Apagado de luz luces de iluminacin ";
cout << "(presione una tecla para continuar)" << endl << endl;
cin.get();
msg = new modplcapcpp_msg(hd, 1, 0x8003);
if (!msg) break;
status = 0x00;
msg->putfield(MODPLCAPCPP_UINT8TYPE, 1, &status);
msg->sendmsg();

796

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


delete msg;
break;
}
/* Finaliza la conexin. */
delete hd;
/* Fin. */
return 0;
}

FernandoArielBeunza79156

797

Tesis de Grado en Ingeniera Informtica

798

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica

Glosario
ACKN

Acknowledgement
Conjunto de bits utilizado en las tramas CAN para indicar si la trama fue recibida
correctamente por los destinatarios de la misma.

ADC

Analogic to Digital Converter


Dispositivo electrnico que permite convertir una seal analgica en un valor
cuantificable capaz de ser representado por medio de una seal digital.

APDU

Application Protocol Data Unit


Unidad de datos definida por el protocolo de capa de aplicacin del estndar CEBus.

ARM

Advanced RISC Machines


Familia de microcontroladores RISC desarrollados originalmente por la empresa
Acorn Computers Ltd. En la actualidad empresas como Freescale, Texas Instrument,
Atmel, entre otras; implementan microcontroladores de sta familia.

ARM9

Advanced RISC Machines 9


Modelo de microcontrolador perteneciente a la familia ARM, que puede procesar
alrededor de 220 millones de instrucciones por segundo con una frecuencia de reloj
de 200 MHz.

ARP

Address Resolution Protocol.


Protocolo que permite relacionar direcciones lgicas con direcciones fsicas propias
de un dispositivo.

ARQ

Automatic Repeat Request.


Protocolo de comunicacin que permite la retransmisin de informacin en caso de
no recibir confirmacin de recepcin por parte del destinatario.

ASK

Amplitude Shift Keying


Tcnica de modulacin que utiliza la amplitud de una portadora para codificar la
informacin binaria a enviar.

AVR

Advanced Virtual RISC


Familia de microcontroladores RISC desarrollados por la empresa Atmel.

BFSK

Binary Frecuency Shift Keying


Tcnica de modulacin que utiliza la frecuencia de una portadora para codificar la
informacin binaria a enviar.

FernandoArielBeunza79156

799

Tesis de Grado en Ingeniera Informtica


BPL

Broadband over Power Lines


Servicio de banda ancha sobre lneas elctricas.

BPSK

Binary Phase Shift Keying.


Tcnica de modulacin que utiliza la fase de una portadora para codificar la
informacin binaria a enviar. En este caso se emplean 2 fases que permiten codificar
un bit de informacin por smbolo.

CAL

CEBus Application Language


Lenguaje definido por el estndar CEBus, para garantizar la interoperabilidad entre
los distintos tipos de dispositivos que cumplan con ste estndar.

CAN

Controller Area Network


Red de datos utilizada en aplicaciones de control.

CEBus

Consumer Electronics Bus


Estndar desarrollado para el mbito del control domtico.

CENELEC Comit Europen de Normalisation Electrotechnique


Es el Comit Europeo de Normalizacin Electrotcnica.
Chirp

Chirp
Seal conformada por un barrido en frecuencia dentro de un determinado rango de
una seal senoidal.

CNP

Control Network Protocol


Protocolo de control de red basado en el modelo OSI.

CRC

Cyclic Redundancy Code


Cdigo calculado a partir de una trama de datos utilizado para verificar que dicha
trama no se haya corrompido en el momento de la transmisin.

CSMA

Carrier Sense Multiple Access


Protocolo encargado de controlar el acceso a un nico medio de comunicacin
compartido por varios dispositivos, basado en el sensado del medio previo a realizar
una transmisin.

CSMA/CA Carrier Sense Multiple Access with Collision Avoidance


Protocolo encargado de controlar el acceso a un nico medio de comunicacin
compartido por varios dispositivos, basado en el sensado del medio previo a realizar
una transmisin. sta versin particular del protocolo implementa un mecanismo que
evita las colisiones de paquetes de informacin transmitidos en forma simultnea.

800

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


CSMA/CD Carrier Sense Multiple Access with Collision Detection
Protocolo encargado de controlar el acceso a un nico medio de comunicacin
compartido por varios dispositivos, basado en el sensado del medio previo a realizar
una transmisin. sta versin particular del protocolo implementa un mecanismo de
deteccin de las colisiones de paquetes de informacin que ocurren cuando varios
dispositivos inician la transmisin en forma simultnea.
CSMA/CR Carrier Sense Multiple Access with Collision Resolution
Protocolo encargado de controlar el acceso a un nico medio de comunicacin
compartido por varios dispositivos, basado en el sensado del medio previo a realizar
una transmisin. sta versin particular del protocolo implementa un mecanismo de
deteccin y resolucin de las colisiones de paquetes de informacin que ocurren
cuando varios dispositivos inician la transmisin en forma simultnea.
CTL

ConTroL Word
Campo de control de un paquete de UPB utilizado para especificar informacin de
control acerca del paquete (tamao del paquete, etc.).

D2B

Domestic Digital Bus


Red de fibra ptica con topologa anillo utilizada para interconectar distintos
dispositivos de automvil

DAC

Digital to Analogic Converter


Dispositivo electrnico que permite convertir un valor cuantificable representado por
medio de una seal digital en una seal analgica.

DBPSK

Differential Binary Phase Shift Keying


Tcnica de modulacin que utiliza la fase de una portadora para codificar la
informacin binaria a enviar. En este caso se emplean 2 fases que permiten codificar
un bit de informacin por smbolo. A diferencia de BPSK, sta tcnica no requiere de
un recuperador de portadora.

DC-BUS

DC-BUS
Red de datos desarrollada por la empresa Yamar Electronics Ltd. que emplea como
medio fsico la red elctrica del automvil

DFT

Discrete Fourier Transform


Extensin de la transformada de Fourier a aplicaciones discretas utilizada en el
demodulador OFDM para recuperar la informacin enviada.

DID

Destination ID
Campo de un paquete UPB utilizado para especificar al dispositivo destinatario.

FernandoArielBeunza79156

801

Tesis de Grado en Ingeniera Informtica


DLC

Data Length Code


Campo de una trama CAN utilizado para especificar el tamao de la misma.

DQPSK

Differential Quadrature Phase Shift Keying


Tcnica de modulacin que utiliza la fase de una portadora para codificar la
informacin binaria a enviar. En este caso se emplean cuatro fases que permiten
codificar dos bits de informacin por smbolo. A diferencia de QPSK, sta tcnica no
requiere de un recuperador de portadora.

DSSS

Direct Sequence Spread Spectrum


Tcnica de expansin del espectro basada en la utilizacin de un cdigo
pseudoaleatorio para enviar la informacin.

EEPROM

Electrically Erasable Programmable Read Only


Tipo de memoria ROM que permite el borrado y programacin de su contenido
elctricamente. Es utilizada en bancos de memoria cuando se desarrolla firmware que
debe ser modificado reiteradas veces. Tambin puede ser empleada para almacenar
datos que requieren persistir (lo que no permite una memoria tipo RAM).

EOF

End Of Frame
Conjunto de bits utilizado en las tramas CAN y J1850 para indicar el final de la
misma.

FEC

Foward Error Correction


Es un mecanismo de correccin de errores que permite corregir errores en el receptor
sin necesidad de retransmisin.

FPGA

Field Programmable Gate Array


Dispositivo compuesto por bloques de lgica programables.

FSK

Frecuency Shift Keying


Tcnica de modulacin que utiliza la frecuencia de una portadora para codificar la
informacin binaria a enviar.

HAN

Home Area Network


Es un tipo de red destinada a interconectar los distintos dispositivos que se puede
encontrar en un hogar.

HF

High Frecuency
Banda del espectro de frecuencias utilizada para las comunicaciones PLC
comprendida entre 1 y 30 MHz.

802

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


IDE

IDentifier Extension
Bit utilizado en las tramas extendidas de CAN parte B, para diferenciarlas de las
tramas estndar.

IDFT

Inverse Discrete Fourier Transform


Extensin de la inversa de la transformada de Fourier a aplicaciones discretas
utilizada en el modulador OFDM para generar el smbolo asociado a la informacin a
enviar.

IFR

In Frame Response
Bit utilizado en las tramas J1850 para indicar que el destinatario de la misma puede
emitir una trama de respuesta a continuacin de la primera.

IP

Internet Protocol
Protocolo de comunicaciones entre redes que forma parte de la capa de red del
modelo OSI, encargado de la identificacin de nodos y del encaminado de paquetes
de informacin.

ISO

International Organization for Standardization


Es un organismo que se encarga de promover el desarrollo de normas internacionales
de fabricacin, comercio y comunicacin para todas las ramas industriales, salvo la
elctrica y la electrnica.

J1850

SAE J1850 Bus


Red de datos utilizada para intercambio de informacin entre dispositivos de un
automvil.

LIN

Local Interconnect Network


Red de datos utilizada como subred de CAN en aplicaciones automotrices.

LLC

Logical Link Control


Protocolo de control de lgica de enlace que forma parte de la capa de enlace del
modelo OSI, encargado de establecer un canal de comunicaciones sin errores y con
control de flujo de la informacin entre el transmisor y el receptor.

LON

Local Operating Network


Es un tipo de red utilizada en la automatizacin de edificios que permite la
interconexin de sensores, actuadores y otros tipos de dispositivos inteligentes.

LonWorks Local Operating Network Works


Estandar utilizado en dispositivos destinados a la automatizacin de edificios basado
en el protocolo CNP.

FernandoArielBeunza79156

803

Tesis de Grado en Ingeniera Informtica


LPDU

Link Protocol Data Unit


Unidad de datos definida por el protocolo de capa de enlace del estndar CEBus.

MAC

Medium Access Control


Protocolo de control de acceso al medio que forma parte de la capa de enlace del
modelo OSI, encargado de gestionar el uso compartido de un nico medio de
comunicacin utilizado por varios dispositivos.

MDA

Message Data Arguments


Campo de un paquete UPB reservado para enviar los parmetros asociados a un
comando.

MDID

Message Data ID
Campo de un paquete UPB reservado para especificar el comando, o la respuesta a
ste.

MOST

Media Oriented System Transport


Red multimedia de alta velocidad optimizada para la industria del automvil.

Neuron ID Neuron Identifier


Identificador utilizado en los dispositivos que cumplen con el estndar LonWorks.
Dicho identificador es nico para cada dispositivo y es establecido por el fabricante
del mismo en el momento de fabricacin.
NID

Network ID
Campo de un paquete UPB utilizado para especificar la red en donde se encuentra el
dispositivo destinatario.

NPDU

Network Protocol Data Unit


Unidad de datos definida por el protocolo de capa de red del estndar CEBus.

NRZ

Non Return to Zero


Mecanismo de codificacin de tramas en donde no se retorna a valor 0 entre bits
consecutivos de valor 1.

NT

Network Idle Time


Segmento de tiempo al final del ciclo de comunicacin recurrente de FlexRay que se
deja sin utilizar como separacin entre ciclos de comunicacin.

OFDM

Orthogonal Frecuency Division Multiplex


Mecanismo de multiplexacin por divisin de frecuencias ortogonales.

804

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


OSEK

Offene Systeme und deren Schnittstellen fr die Elektronik in Kraftfahrzeugen


Es un estndar abierto sobre interfaces para la electrnica de automviles. Consiste
en un sistema operativo integrado por una pila de protocolos de comunicacin y
administracin de redes orientado a aplicaciones empotradas utilizadas en
automviles.

OSI

Open Sytem Interconnection


Es un modelo de red propuesto por ISO utilizado como marco de referencia para la
definicin de arquitecturas de interconexin de sistemas de comunicaciones.

PAR

Peak to Average Power Ratio


Parmetro utilizado para medir el margen de amplitud de una seal.

PLC

Power Line Communication


Sistema de comunicacin que utiliza las redes de alimentacin como medio fsico de
transmisin de informacin.

PPM

Pulse Position Modulation


Tcnica de modulacin que se utiliza la posicin de un pulso para codificar la
informacin a enviar.

PWM

Pulse Width Modulation


Tcnica de modulacin que utiliza el ancho de pulso para codificar la informacin a
enviar.

PSK

Phase Shift Keying


Tcnica de modulacin que utiliza la fase de una portadora para codificar la
informacin a enviar.

QAM

Quadrature Amplitude Modulation


Tcnica de modulacin de amplitud en cuadratura. Es una variante de la modulacin
en amplitud ms eficiente que ASK, ya que la informacin se codifica por medio de la
amplitud y fase de la portadora permitiendo transmitir ms bits por smbolo.

QPSK

Quadrature Phase Shift Keying


Tcnica de modulacin que utiliza la fase de una portadora para codificar la
informacin binaria a enviar. En este caso se emplean 4 fases que permiten codificar
2 bits de informacin por smbolo.

RAM

Random Access Memory


Tipo de memoria voltil de acceso aleatorio utilizada en bancos de memoria que
permite operaciones de lectura y escritura. Es empleada para el almacenamiento de
datos transitorios.

FernandoArielBeunza79156

805

Tesis de Grado en Ingeniera Informtica


RISC

Reduced Instruction Set Computer


Es un tipo de microprocesador que se caracteriza por ofrecer un conjunto de
instrucciones de tamao fijo que puede manipular un limitado conjunto de tipos de
datos, y solamente dispone de dos instrucciones para acceder a la memoria de datos.
La ventaja que brinda este tipo de microprocesador es que las instrucciones se
ejecutan empleando muy pocos ciclos de reloj, permitiendo mayores velocidades de
procesamiento.

ROBO

ROBust OFDM
Es mecanismo para enviar informacin repetida por medio de la tcnica OFDM, para
aumentar la confiabilidad a costas de una reduccin en la velocidad de transferencia.

ROM

Read Only Memory


Tipo de memoria no voltil de acceso aleatorio utilizada en bancos de memoria que
solamente permite operaciones de lectura. Es empleada para el almacenamiento de
firmware de microcontroladores.

RS232

Recommended Standard 232


Interfaz utilizada para el intercambio de datos en forma serial entre un equipo
terminal de datos (por ejemplo, una PC) y un equipo de comunicacin de datos (por
ejemplo, un modem).

RTR

Remote Transmission Request


Bit de una trama CAN utilizado para indicar que la misma es una trama de datos.

SAE

Society of Automotive Engineers


Es la Sociedad de Ingenieros de Automocin cuya funcin es definir estndares para
todo tipo de vehculos (automviles, aviones, barcos, etc.).

SID

Source ID
Campo de un paquete UPB utilizado para especificar al dispositivo que dio origen al
paquete.

SOF

Start Of Frame
Bit utilizado en las tramas CAN y J1850 para indicar el comienzo de la misma.

SRR

Substitute Remote Request


Bit utilizado en las tramas extendidas de CAN parte B, ubicado en la misma posicin
donde se encuentra el bit RTR de una trama estndar. Su existencia se debe a razones
de compatibilidad entre las tramas estndar y las tramas extendidas.

SW

Symbol Window
Segmento opcional de tiempo del ciclo de comunicacin recurrente de FlexRay
utilizado para evaluar el estado del medio.

806

FernandoArielBeunza79156

Tesis de Grado en Ingeniera Informtica


TCC

Turbo Convolutional Code


Tipo de cdigo de correccin de errores que permite comunicaciones confiables y su
eficiencia energtica est muy cerca del lmite terico de Shannon.

TDM

Time Division Multiplexing


Es una tcnica de multiplexacin en donde se asigna todo el ancho de banda de un
medio de transmisin a cada canal durante un intervalo de tiempo.

TDMA

Time Division Multiple Access


Es una tcnica de multiplexacin que distribuye la informacin en ranuras de tiempo
de forma alternada, brindando acceso mltiple sobre un nmero reducido de
frecuencias.

TCP

Transport Control Protocol


Protocolo de control de transporte de informacin entre dos nodos que forma parte de
la capa de transporte del modelo OSI, encargado de establecer un canal de
comunicaciones confiable entre dos nodos.

TTL

Transistor Transistor Logic


Tecnologa de construccin de circuitos electrnicos digitales basada en transistores
bipolares, que se caracteriza por trabajar con dos rangos de tensin especficos para
representar el cero y uno lgicos.

UART

Universal Asynchronous Receiver Transmitter


Dispositivo utilizado para el intercambio de datos en forma serial entre dispositivos.

UPB

Universal Power Bus


Es un estndar de comunicaciones para dispositivos usados en la automatizacin del
hogar.

USB

Universal Serial Bus


Interfaz utilizada para el intercambio de datos en forma serial entre una PC y diversos
perifricos (por ejemplo, teclados, impresoras, etc.).

VDX

Vehicle Distributes eXecutive


Sistema operativo integrado por una pila de protocolos de comunicacin y
administracin de redes orientado a aplicaciones empotradas en automviles, similar
a OSEK.

VPW

Variable Pulse Width


Tcnica que emplea el ancho de pulso para codificar la informacin a enviar.

FernandoArielBeunza79156

807

Tesis de Grado en Ingeniera Informtica


VSB-SC

Vestigial Sideband Suppressed Carrier


Tipo de modulacin de amplitud que utiliza para transmitir la informacin, una de las
banda laterales y un vestigio de la otra, suprimiendo la portadora para ahorrar
energa.

WAN

Wide Area Network


Es un tipo de red que permite interconectar computadoras en un rango de distancias
comprendido entre los 100 y 1000 kilmetros.

WiFi

Wireless Fidelity
Es un tipo de red que permite interconectar computadoras de forma inalmbrica.

X10

X10
Es un estndar de comunicaciones para el control remoto de dispositivos elctricos.

808

FernandoArielBeunza79156

También podría gustarte