RS232 en el PIC: UART por software

— [ edit | raw ] migrated from node/689
La comunicación entre dispositivos es vital para diseñar sistemas más complejos. En este tema, uno de los primeros pasos cuando se trabaja con el PIC es la comunicación con el PC usando el puerto serie.
A continuación veremos las posibilidades disponibles y una implementación de una UART en ensamblador para el PIC.

Escenario

Por supuesto, existen muchos microcontroladores que integran entre sus periféricos una UART. En estos casos es mucho más sencilla la comunicación con el PC o con otros periféricos, pues la UART se encarga de casi todo. El problema surge cuando el micro que usamos no tiene el hardware adecuado (por problemas de espacio, de costo, etc.). En esos casos, es posible utilizar UART's hardware externas, pero que presentan el problema de tener que usar más hardware (encarecimiento, volumen...), por lo que quizá tampoco sea una solución. Para estas situaciones (u otras que se puedan presentar) tenemos la posibilidad de diseñar nosotros mismos la UART e implementarla en software. Veamos un ejemplo de esta implementación.

Ingredientes

Lo que vamos a hacer es conectar un PIC al PC para enviar información entre ambos dispositivos. Usaremos el puerto serie del PC, que emplea la norma RS232. Para hacer esto, tenemos que convertir los niveles de señal entre los que usa el PIC (TTL) y los del puerto serie (RS232). Para ello, necesitaremos un conversor. En este caso, usaremos el DS275. Para el conexionado y las señales, te remito a: La consola de la fonera: DS275. Si no quieres leer mucho, estos son los pines a conectar (usando un DB-9 para el RS232):
 RS232      DS275      PIC
--------------------------
 RxD(2)     TXout(5)
 TxD(3)     RXin (7)

            RXout(1)   RxD
            TXin (3)   TxD
En cuanto a hardware, sólo eso. Necesitarás también una protoboard, pines... lo normal en estos casos. El software lo haremos nosotros ;-) .

Comunicación serie

Antes de seguir, nos sería útil saber cómo funciona una comunicación serie, en este caso la que se usa en el puerto serie de nuestro PC (o Fonera...). Serie nos indica uno detrás de otro, y en efecto, cuando transmitimos algo en serie, lo hacemos bit a bit. En el caso del PIC, si queremos transmitir algo, hemos de usar uno de los pines configurado como salida. Para transmitir un '1' lógico, ponemos el pin en nivel alto (+5V por ejemplo) y si queremos enviar un '0', ponemos el pin en nivel bajo (cerca del nivel GND). Así, variando en el tiempo el estado del pin, podemos enviar todos los datos que queramos. La pregunta que surge es: ¿cuánto tiempo mantenemos el nivel? La respuesta es obvia: dependiendo de la velocidad con que estemos transmitiendo. En el RS232 mediremos la velocidad en bps (bits por segundo). Así pues, tenemos diferentes velocidades 'estándar': 600, 1200, 2400... En nuestro ejemplo usaremos 9600 bps, pero si es necesario podríamos llegar a velocidades de casi 1 Mbps. Luego veremos cuanto ha de durar cada bit para enviar a esa velocidad. Vemos que si cada bit tiene una duración fija, constante, no es necesario un reloj que marque los cambios de bit. Cierto, no es necesario, es implícito. Pero esto implica que si se comete un error en la transmisión de un bit, el resto de la comunicación sería basura. Existen por tanto ciertos métodos y bits bandera para que esto no ocurra. En primer lugar, el estado del pin de envio mientras no se está enviando es fijo (deber ser '1'). Así, cuando se empieza la transmisión, enviamos un bit de inicio (que es un '0'). Después, se acuerda entre emisor y receptor cuantos bits van a conformar los datos: 5, 6, 7 u 8. Lo normal es 8 (un byte). Se envían respetando los tiempos de cada bit. Una vez enviados los datos, el siguiente bit es opcional y se usa como mecanismo para evitar errores: la paridad. Consiste en un bit que indicar si el número de unos o ceros en los datos es par o impar. Aquí no lo usaremos. Para terminar, enviamos uno o dos bits de parada, de forma que el pin de transmisión se quede en el nivel lógico '1'. Así, se termina la transmisión de nuestro dato. Nos quedamos con la velocidad (9600 bps), los bits de datos (8bits), la paridad (N) y el bit de stop (1): 9600 8N1 Podemos verlo todo un poco más claro en el siguiente cronograma:
Cronograma rs232

UART software

Ahora lo que haremos será implementar unas rutinas que nos simplifiquen el envio de datos por el puerto serie. Antes de nada, convenir que pines usaremos. El PORTA,0 será el pin TxD mientras que el PORTA,1 será el RxD. Usaremos el PIC16F84, así lo configuramos:
	list	p=16f84		; Procesador a usar.
	include	<p16f84.inc>

;;; Configuración
;;;  Oscilador:	cristal de cuarzo
;;;  WatchDogTimer: apagado
;;;  CodeProtection: desactivado
;;;  PoWeR up Timer activado
	__CONFIG _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_ON
También podemos definir las constantes que usarán las rutinas:
;;; Constantes
tx_port equ	PORTA 		; Puerto de tranmisión
tx_pin	equ	0x0		; Pin de transmisión
rx_port equ	PORTA 		; Puerto de recepción
rx_pin	equ	0x1		; Pin de recepción

data_tx	equ	0xd		; Datos a enviar
data_rx	equ	0xf		; Datos recibidos

count_d equ	0xc		; Contador para el retardo
count_p	equ	0x10		; Contador para el número de bits
Ahora podemos definir la rutina de retardo, que será la que marque el tiempo que consideraremos de un bit. Como hemos dicho, la velocidad de transmisión será 9600bps. También hay un comentario que indica que el reloj que usaremos será de 4 MHz, lo que indica que tendremos un ciclo de reloj de 1 us. Si dividimos 9600/1s = 104 us. Luego la duración de cada bit ha de ser de 104 us. Nuestro bucle será así:
rs232_d:
	movlw	D'32'		; 1 us (algo menos de 33)
	movwf	count_d		; 1 us
	decfsz	count_d, F	; 1 us (+ 1 en caso de skip)
	goto	$-1		; 2 us

	return			; 2 us
Y como vemos, se ejecuta una media de 3 veces más 5 ciclos de inicialización y retorno. Luego haciendo un cálculo rápido vemos que con justo 33 veces conseguimos que rs232_d dure 104 us. En la práctica, no nos es útil acercarnos tanto al límite, por lo que si usamos 32, funciona mejor. Ahora, cada vez que enviamos un bit, hemos de esperar el tiempo marcado por rs232_d. Veamos la rutina de envio:
send_b:
        movwf   data_tx        	; Guargamos el dato a enviar
        movlw   d'8'          	; Enviaremos 8 bits
        movwf   count_p

        bcf     tx_port,tx_pin	; enviamos el bit de inicio
        call    rs232_d

s_loop:
	btfss	data_tx,0	; comprobamos el primer bit
        bcf     tx_port,tx_pin  ; si es un 0 enviamos un 0
        btfsc   data_tx,0
        bsf     tx_port,tx_pin  ; si es un 1 enviamos un 1

        call    rs232_d         ; mantenemos el bit el tiempo necesario

        rrf     data_tx,F	; movemos los bits a la derecha

        decfsz  count_p,F       ; si no se han enviado 8 bits...
        goto    s_loop       	; seguimos

        bsf     tx_port,tx_pin 	; si se han enviado, enviamos el bit de stop
        call    rs232_d
	return
NOTA: enviamos el LSB (least significative bit) primero, el bit 0. Antes de llamar a esta rutina, debes poner en W el byte que quieras enviar. Este byte se guarda en un registro, así como el número de bits de datos. Se envia el bit de inicio y después el resto de bits. Una vez terminado, nos queda poner el bit de stop y retornar. Sencillo, ¿verdad? Pues la de recepción no es mucho más complicada:
recv_b:
	movlw	d'8'
	movwf	count_p
	clrf	data_rx		; daremos por hecho que son todo 0's
	btfsc	rx_port, rx_pin ; comprobamos bit de inicio
	return			; datos erróneos

r_loop:
	rrf	data_rx,F	; rotamos a la derecha (primero LSB)
	call	rs232_d		; esperamos el tiempo adecuado

	btfsc	rx_port, rx_pin	; solo cambiamos si es un 1
	bsf	data_rx,7
	decfsz	count_p, F
	goto	r_loop

	movf	data_rx, W	; retornamos el dato leido, en W
	return
Antes de llamar a esta rutina, es necesario que compruebes el pin RxD en espera del bit de inicio. Inmediatamente después de cambiar de estado el pin RxD, se ha de llamar a esta rutina. Es posible retardarse un lapso de tiempo máximo de rs232_d/2, pero no mucho mayor, si se quiere leer algo. Lo más aconsejable es usar como pin RxD uno que sea sensible a cambios de estado mediante interrupciones, y llamar a la rutina de lectura desde el vector de interrupción. Así se evita el hacer un polling al pin RxD.

Ejemplo de uso

Como ejemplo de uso, veremos un simple servicio de echo en el puerto serie: cada byte que se envía desde el PC al PIC es retornado de nuevo al PC. Es algo muy sencillo:
;;; -*- coding:	utf-8 -*-
;;; Prueba de comunicación con el puerto RS232 de
;;; un pc. Se establece la comunicación a
;;; 9600bps, 8N1, con un cristal de 4MHz

;;; Author: Oscar Acena, (c) 2006, 2007
;;; License: GPL

	list	p=16f84		; Procesador a usar.
	include	<p16f84.inc>

;;; Configuración
;;;  Oscilador:	cristal de cuarzo
;;;  WatchDogTimer: apagado
;;;  CodeProtection: desactivado
;;;  PoWeR up Timer activado
	__CONFIG _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_ON

;;; Constantes
tx_port equ	PORTA 		; Puerto de tranmisión
tx_pin	equ	0x0		; Pin de transmisión
rx_port equ	PORTA 		; Puerto de recepción
rx_pin	equ	0x1		; Pin de recepción

data_tx	equ	0xd		; Datos a enviar
data_rx	equ	0xf		; Datos recibidos

count_d equ	0xc		; Contador para el retardo
count_p	equ	0x10		; Contador para el numero de bits

	org	0		; Punto de inicio
	goto	main

	org	4		; Rutina de interrupcion
	retfie

;;; -------------------------------------------------------------
;;; Tenemos que transmitir a 9600bps, lo que implica 1 bit
;;;  cada 1/9600 s -> 104 us. Con un reloj de 4MHz, tenemos
;;;  un ciclo de 1us. El siguiente codigo es un bucle que usa una
;;;  media de 3 ciclos, por lo que si lo ejecutamos unas 33 veces,
;;;  tendremos el ratio deseado: (2+1)*33 + 1+1+1+2 = 104 us
rs232_d:
	movlw	D'32'		; 1 us (algo menos de 33)
	movwf	count_d		; 1 us
	decfsz	count_d, F	; 1 us (+ 1 en caso de skip)
	goto	$-1		; 2 us

	return			; 2 us

;;; -------------------------------------------------------------
;;; Recibimos un byte, que dejamos en w cuando retornamos. Usamos la
;;; configuración 8N1. El bit de start será el primero que leeremos.
recv_b:
	movlw	d'8'
	movwf	count_p
	clrf	data_rx		; daremos por hecho que son todo 0's
	btfsc	rx_port, rx_pin ; comprobamos bit de inicio
	return			; datos erróneos

r_loop:
	rrf	data_rx,F	; rotamos a la derecha (primero LSB)
	call	rs232_d		; esperamos el tiempo adecuado

	btfsc	rx_port, rx_pin	; solo cambiamos si es un 1
	bsf	data_rx,7
	decfsz	count_p, F
	goto	r_loop

	movf	data_rx, W	; retornamos el dato leido, en W
	return

;;; -------------------------------------------------------------
;;; Enviamos un byte, que debe estar en W antes de llamar a esta rutina
;;; con la cofiguración 8N1, a la velocidad estipulada por rs232_d.
send_b:
        movwf   data_tx        	; Guargamos el dato a enviar
        movlw   d'8'          	; Enviaremos 8 bits
        movwf   count_p

        bcf     tx_port,tx_pin	; enviamos el bit de inicio
        call    rs232_d

s_loop:
	btfss	data_tx,0	; comprobamos el primer bit
        bcf     tx_port,tx_pin  ; si es un 0 enviamos un 0
        btfsc   data_tx,0
        bsf     tx_port,tx_pin  ; si es un 1 enviamos un 1

        call    rs232_d         ; mantenemos el bit el tiempo necesario

        rrf     data_tx,F	; movemos los bits a la derecha

        decfsz  count_p,F       ; si no se han enviado 8 bits...
        goto    s_loop       	; seguimos

        bsf     tx_port,tx_pin 	; si se han enviado, enviamos el bit de stop
        call    rs232_d
	return


;;; Rutina principal. Configura el pic.
main:
	bsf	STATUS, RP0
	bcf	tx_port, tx_pin ; Pin TxD como salida
	bcf	TRISB, 0x3      ; y pin PORTB,3 como salida también
	bcf	STATUS, RP0

loop:
 	btfsc	rx_port, rx_pin ; Esperamos al bit de inicio
 	goto	$-1

	bsf	PORTB, 0x3
	call	recv_b		; recibimos
	call	send_b		; enviamos
	bcf	PORTB, 0x3

	goto	loop
	end
En este caso, tengo puesto un LED en el PORTB,3, que se enciende cuando hay comunicación. Lo puedes probar con el minicom, o mejor con algo hexadecimal, como el cutecom.

Disclaimer

Esta seguro no es la mejor UART que existe, desde luego. Acepto comentarios que ayuden a mejorarla. Este es mi pequeño aporte, quizá entre todos salga algo decente que podamos usar. Es lo genial del software libre. Por otro lado, todo esto es software prototipo. No esta completamente depurado y NO ASEGURO QUE FUNCIONE EN NINGÚN CASO. NO ME HAGO RESPONSABLE DE LOS DAÑOS CAUSADOS AL HARDWARE, A LA COMPUTADORA O A SU PERSONA. Puedes modificarlo o usarlo a tu antojo. Queda bajo la licencia GPL v2.0 o posterior.

Referencias

  1. X-Robotics
  2. Mucha info útil (alemán)

La consola de la fonera: DS275

— [ edit | raw ] migrated from node/690
El router La Fonera, distribuido por Fon, cuenta con un puerto serie interno (por lo menos hasta la versión 2.1, aunque es muy posible que la 2.2 también traiga uno). Veamos como usarlo para acceder a la consola del GNU/Linux que lleva dentro.

Introducción

La fonera trae un GNU/Linux de fábrica. Es una versión modificada de OpenWRT por la gente de FON, pero al fin y al cabo es un GNU/Linux. Además, cuenta con un puerto serie, lo cual es una buena noticia porque nos permite interactuar con el mundo externo de una forma muy sencilla. De momento lo vamos a usar para acceder a la consola del sistema. Al contrario de lo que muchos piensan, usar un emulador de terminal con ese puerto serie no es ni mucho menos tener acceso SSH. El SSH (Secure SHell) es un protocolo de comunicaciones que permite el control remoto de forma segura (entre otras muchas cosas). Lo que usamos nosotros es simplemente una consola del sistema (como cuando accedemos en un terminal real). El kernel de la fonera está configurado de forma que los mensajes se envíen al puerto serie. Además, se arranca una shell para ese mismo puerto que permite la interacción con el sistema. Es una consola como las de toda la vida. Nosotros, simplemente tenemos que conectar un puerto serie de nuestro PC con el de la fonera. Bueno, realmente es un poco menos sencillo, por el hecho de que nuestro puerto serie sigue la norma RS232 con respecto a los niveles de tensión, mientras que el de la fonera no (usa niveles convencionales TTL). Luego, necesitamos algo que "adapte" entre los niveles RS232 y TTL. Este algo es un circuto, más o menos complejo. Existen múltiples versiones. Una de ellas es la conexión directa. Actualmente, las UART de los PC's soportan los niveles TTL sin mucho problema. Otra opción es diseñar un circuito basado en transistores y diodos que haga el trabajo. Sin duda, puede ser una buena opción... a menos que quieras/puedas usar los integrados que existen a tal fin. La "mejor" (depende de las circunstancias) versión de este adaptador es usar un conversor de niveles integrado. El más conocido es el MAX232. Es un integrado de 16 pines que necesita varios condensadores para trabajar. Otro modelo menos conocido pero quizá más sencillo de usar es el DS275. Es un integrado más pequeño, solo tiene 8 pines, que se conecta directamente, por lo que usarlo es sencillisimo. Es el que vamos a emplear aquí.

El adaptador

Como siempre, antes de usar ningún integrado, recomiendo leerse el datasheet correspondiente. Si ya lo has hecho, podemos continuar... :-) El puerto serie del PC tiene un montón de señales que no nos interesan ahora. Son 9 pines (en un DB9 claro) de los cuales solo vamos a emplear 3, a saber:
PIN: 2 -> RxD
     3 -> TxD
     5 -> GND
El RxD es el encargado de la recepción de los datos, el TxD de la transmisión y el GND sólo es la referencia de las señales (GrouND). Sucede lo mismo con el serie de la fonera, solo que en este caso, vamos a usar un pin más: el de 3.5 V de referencia para el integrado. No te preocupes si parece mucho lio, al final lo verás muy claro. Resumiendo: tenemos en el puerto serie del PC 3 pines a usar y en el de la fonera 4 pines. Los de la fonera son como sigue:
| GND  #  RxD  TxD  #
| Vcc  #   #    #   #
visto de tal forma que a la izquierda tengamos inmediatamente el borde de la placa. Mmm... quizá una imagen valga más que mil palabras... Zocalo serie de la fonera Bien, veamos ahora el integrado que usaremos: esquema ds275 Y ahora las conexiones que vamos a hacer... mejor una explicación gráfica: conexiones fonera-PC con un ds275 Y por último todo el invento montado: Fonera con puerto serie

Probando

Y ya está. Podemos conectar el puerto serie a la fonera y arrancar un programa de emulación de terminal en ese mismo puerto. Existe uno muy interesante llamado minicom ($ man minicom) que funciona muy bien. Configúralo para que escuche en el puerto serie de tu PC, y como parámetros: 9600 8N1 (es decir 9600 Bps, 8 bits de datos, sin paridad y 1 bit de stop). NOTA: No te fíes del estado del minicom, que muestra siempre desconectado. Esto te sería util si usaras un dispositivo de red orientado a conexión, pero usas un puerto serie, de tipo caracter que se comporta como un flujo de datos. Bien, ahora que lo tienes todo listo, arranca la fonera. Espera unos segundos y empezarás a ver el arranque del kernel. ¡Enhorabuena! Ya tienes acceso a la consola de tu fonera. Si no ves nada en un rato, es probable que hayas metido la pata. Lo siento. Repasa las conexiones con cuidado. Si sigues teniendo problemas, busca ayuda. En internet hay mucha información al respecto.

Referencias

  1. OpenWRT y la Fonera
  2. RS232C Level Converter

Cairo: tutorial en castellano

— [ edit | raw ] migrated from node/688
Estaba pensando hacer una recetilla sobre Cairo y Gtk, algo sencillo, transparencias (adiós) y demás, pero me he encontrado a alguien... ¡que ya lo ha hecho! Increíble en estos tiempos... :-p Así que me limito a poner el enlace de su artículo, por si a alguien le interesa:

"Conferencia sobre Software Libre"

— [ edit | raw ] migrated from node/686

Los responsables de la oficina electoral “nuevos tiempos” nos han invitado a dar una charla sobre software libre. Ellos lo han llamado “conferencia” aunque mi idea es que sea mucho menos formal y mucho más participativo que una “conferencia”, pero vale, intentaremos que lo parezca.

Ajustes al tinyOS 2

— [ edit | raw ] migrated from node/687
Algunos parámetros que hay que configurar (modificando las librerías) para que las aplicaciones escritas en tinyOS 2 funcionen bien y/o se adapten a tus necesidades específicas.

Frecuencia de transmisión/Recepción de la radio

Los dispositivos que utilizan el chip de radio cc1000 de Chipcon pueden no funcionar bien en tinyOS 2 debido a que en las motas, estos chips deben estar configurados para funcionar en el rango de 915 a 998 MHz y por defecto no es así. La forma de solucionar ésto es editando el archivo CC1000Const.h. Suponiendo que tienes el árbol de tinyOS instalado en /opt/tinyos-2.x/, deberás modificar el archivo /opt/tinyos-2.x/tos/chips/cc1000/CC1000Const.h y hacer que la macro que define la constante CC1K_DEF_PRESET quede de la siguiente forma:
#ifndef CC1K_DEF_PRESET
#define CC1K_DEF_PRESET	(CC1K_915_998_MHZ)
#endif
De éste modo, en los futuros programas, la radio se configurará para funcionar a la frecuencia correcta.

Longitud del campo de datos en la estructura message_t

La estructura message_t proporciona una abstracción para enviar y recibir mensajes a través de la radio o del puerto serie. El campo de datos de ésta estructura, tiene una longitud máxima prefijada de 28 Bytes, que en muchos casos puede ser mas que suficiente, pero en otras ocasiones podemos quedarnos cortos. Para solucionar ésto, debemos pasar a nesC el flag DTOSH_DATA_LENGTH para indicar la longitud máxima que queremos que tenga dicho campo de datos. La forma de hacer ésto es editando el fichero Makefile de tu proyecto añadiendo lo siguiente:
NESC_FLAGS ?= -DTOSH_DATA_LENGTH=250

COMPONENT=sampleApp
include $(MAKERULES)
No suele ser recomendable definir una longitud mayor que esa, ya que puede haber problemas de compilación.

Instalación de librerías propias

Si tenemos pensado escribir nuestros propios módulos e interfaces, como se explica en una receta publicada también en éste portal, podemos guardarlos todos bajo un mismo directorio (por ejemplo ~/tinyOS_libs/) y a continuación hacer lo siguiente para que el compilador sepa encontrar dicha librería: Editamos el archivo Makefile de tu proyecto para hacer que incluya el directorio de tu librería:
NESC_FLAGS ?= -I ~/tinyOS/libs/

COMPONENT=sampleApp
include $(MAKERULES)
Con esto, cuando compiles, se buscarán las librerías también en ese directorio.

Webcams USB y Linux

Hola majetes! Supongo que todos vosotros tendréis webcams y quizá hayáis probado a enchufarlas en vuestras distros y... ohhh... desilusión... el linux no la pilla! (Si tenemos Debian es peor todavía porque de serie apenas tenemos módulos adecuados). No hay que preocuparse... vamos a hablar de unos cuantos módulos que hay por ahí con los que, en total, tendremos soporte para varios cientos de cámaras. No quiero decir que estén todos los que hay, pero al menos sí algunos de los más importantes.

Un millón de gracias

— [ edit | raw ] migrated from node/682
Ayer, domingo 13 de mayo, cerca de las 12 de la noche, superamos el millón de visitas (según nuestro contador).

GNU Emacs: Mejorando Tabbar

— [ edit | raw ] migrated from node/683
Ya vimos cómo Añadir pestañas a Emacs. Ahora veremos cómo cambiar las agrupaciones.

Ingredientes

Nuevamente, Emacs y emacs-goodies-el.

Agrupaciones

A menudo me ha ocurrido que he tenido que abrir ficheros Makefile. Realmente es un fastidio que tabbar agrupe por extensiones: a mí me gustaría tener disponibles mi Makefile, los .C y los .CPP que utilizo constantemente. Hoy editaremos a mano, una vez más, nuestro queridísimo .emacs (_emacs para los Windozes). Ahí va un ejemplo de hacer lo que he descrito:
(defun tabbar-buffer-groups (buffer)
  (with-current-buffer (get-buffer buffer)
    (cond
     ((eq major-mode 'dired-mode) '("Main") )
     ((memq major-mode '(c-mode c++-mode makefile-mode)) '("Coding") )
     )
    )
  )
Claro, que suele ser un fastidio tener todas las pestañitas ésas: scratch, Messages, ... Ahí va mi configuración:
(defun tabbar-buffer-groups (buffer)
  "Return the list of group names BUFFER belongs to.
Return only one group for each buffer."
  (with-current-buffer (get-buffer buffer)
    (cond
     ((member (buffer-name) '("*scratch*")) '("Misc") )
     ((member (buffer-name) '("*Messages*")) '("Misc") )
     ((member (buffer-name) '("*Completions*")) '("Misc") )
     ((member (buffer-name) '("*Ediff Registry*")) '("Misc") )
     ((eq major-mode 'dired-mode) '("Main") )
     ((memq major-mode '(c-mode c++-mode makefile-mode)) '("Coding") )
     (t '("Main") )
     )
    )
  )
Como podéis ver, tengo 3 grupos principales: Misc, Coding y Main. Por defecto lo mete todo en "Main", salvo los ficheros de c, c++ y Makefiles que son "Coding", y los buffers habituales van a "Misc". Con esta base y un poco de imaginación, se pueden hacer muchas cosas muy apañadas...

Referencias

Mike's Emacs Help Page (y ese Mike no soy yo :D).

Próxima semana:

Bueno... Podéis observar que he roto lo habitual de escribir cada semana. A parte de que estoy muy liado, ¡se me están acabando las ideas!. David ha proporcionado unos cuantos TES y Brue también ha puesto su granito de arena. Si alguien más participa, ¡estupendo! pero, por mi parte, se acaban los TES. De todas maneras, podéis poner vuestros trucos y marcarlos como "emacs" en la pestaña "Tema". Siempre son bienvenidos ;)

Otra de Linus

— [ edit | raw ] migrated from node/679
Leyendo y buscando información sobre Qt me encuentro con este interesante enlace en la página de TrollTech (los que hacen Qt):

Soy famoso!

— [ edit | raw ] migrated from node/673
Hola amigos... aquí estoy, desde un lugar de la Mancha que la gente por lo visto SI recuerda }:-).