Memoria compartida en C++ 
El uso de la memoria compartida en sistemas operativos compatibles SystemV y BSD (como Linux, FreeBSD, OSX, etc.) siempre ha estado tradicionalmente asociado al uso del lenguaje C. Sin embargo, si estamos en C++, podemos utilizar la memoria compartida sin renunciar al paradigma de la orientación a objetos: Creando objetos en dicha memoria compartida. Estos “objetos compartidos” serán accesibles, al estar alojados en memoria compartida, desde todos los procesos que tengan acceso a ella.

El truco consiste simplemente en redefinir el operador “new” para la clase de los objetos que queremos compartir:
extern "C++" {
    using namespace std;
    namespace avelino {
        class TShared {
            private:
                int a;
            public:
                TShared();
                void setA(int v);
                int getA();
                static void *memArea;
                void *operator new (unsigned int size);
        };
    }
}
...
void *TShared::operator new (unsigned int size) {
    return TShared::memArea;
}

Como se puede observar, hacemos que new TShared() devuelva un puntero a un área de memoria controlada por nosotros (no estoy implementando el delete ni estoy realizando una gestión de memoria como tal: obsérvese que dos new TShared() seguidos devolverían la misma posición de memoria, estoy haciéndolo así para facilitar la comprensión).

Bueno, ya tenemos una clase que, al hacerle new nos va a devolver un puntero a una dirección de memoria controlada por nosotros. Ahora sólo nos queda inicializar dicho puntero adecuadamente.

Debe haber un proceso que cree el objeto en memoria compartida:
int shmid = shmget(SHM_KEY, sizeof(TShared), IPC_CREAT | IPC_EXCL | 0700);
TShared::memArea = shmat(shmid, NULL, 0);
TShared *p = new TShared();
p->setA(12345);

Como se puede ver, antes de hacer el new TShared() inicializo TShared::memArea con la zona de memoria compartida que acabo de crear (he omitido, por claridad, los if que controlan los posibles errores que puedan devolver la funciones shmget, shmat, etc.). Ahora nuestro objeto de tipo TShared está en la memoria compartida identificada por SHM_KEY (una constante cualquiera definida por nosotros y mayor que cero).

Si otro proceso quiere acceder a dicho “objeto compartido” sólo tendrá que acceder a dicha memoria compartida y hacer el cast correspondiente:
int shmid = shmget(SHM_KEY, sizeof(TShared), 0700);
TShared::memArea = shmat(shmid, NULL, 0);
TShared *p = (TShared *) TShared::memArea;
cout << "a = " << p->getA() << endl;

El código fuente completo lo he puesto en la sección soft de la web.


[ 2 comentarios ] ( 7262 visualizaciones )   |  [ 0 trackbacks ]   |  enlace permanente  |   ( 3 / 1738 )
Minisintetizador basado en Arduino 
Versión iniciar y muy básica de un minisintetizador mononfónico de onda cuadrada con entrada MIDI y basado en Arduino. Por ahora sólo reconoce mensajes MIDI "NOTE ON" y "NOTE OFF".

El procesador del Arduino se encarga simplemente de parsear los mensajes MIDI: Genera los tonos y los silencios ante las tramas NOTE ON y NOTE OFF que detecta por la entrada MIDI.

#define  MIDI_NOTE_LOW   16
#define MIDI_NOTE_HIGH 107

// midi frequencies from C0 to B7
int freq[] = {
21, 22, 23, 24, 26, 28, 29, 31,
33, 35, 37, 39, 41, 44, 46, 48, 52, 55, 58, 62,
65, 69, 73, 78, 82, 87, 92, 98, 104, 110, 117, 123,
131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
262, 277, 294, 311, 329, 349, 370, 392, 415, 440, 466, 494,
523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1864, 1976,
2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951
};

#define MIDI_STATUS_WAIT_STATUS 0
#define MIDI_STATUS_WAIT_NOTE 1
#define MIDI_STATUS_WAIT_VELOCITY 2
#define MIDI_STATUS_WAIT_NOTE_OR_STATUS 3

#define SPEAKER_PIN 13

int midiStatus = MIDI_STATUS_WAIT_STATUS;
int midiNote = 0;
int midiVelocity = 0;

void setup() {
Serial1.begin(31250);
}

void parseMidi(int b) {
if (midiStatus == MIDI_STATUS_WAIT_STATUS) {
if ((b & 0xF0) == 0x90)
midiStatus = MIDI_STATUS_WAIT_NOTE;
}
else if (midiStatus == MIDI_STATUS_WAIT_NOTE) {
midiNote = b;
midiStatus = MIDI_STATUS_WAIT_VELOCITY;
}
else if (midiStatus == MIDI_STATUS_WAIT_VELOCITY) {
midiVelocity = b;
midiStatus = MIDI_STATUS_WAIT_STATUS;
if (midiVelocity == 0)
noTone(SPEAKER_PIN);
else {
if ((midiNote >= MIDI_NOTE_LOW) && (midiNote <= MIDI_NOTE_HIGH))
tone(SPEAKER_PIN, freq[midiNote - MIDI_NOTE_LOW]);
}
midiStatus = MIDI_STATUS_WAIT_NOTE_OR_STATUS;
}
else if (midiStatus == MIDI_STATUS_WAIT_NOTE_OR_STATUS) {
if (b < 0x80) {
midiNote = b;
midiStatus = MIDI_STATUS_WAIT_VELOCITY;
}
else if ((b & 0xF0) == 0x90)
midiStatus = MIDI_STATUS_WAIT_NOTE;
else
midiStatus = MIDI_STATUS_WAIT_STATUS;
}
}

void loop() {
while (Serial1.available() > 0) {
int b = Serial1.read();
parseMidi(b);
}
}

Como se puede ver, el parseado de las tramas MIDI se realiza mediante un sencillo autómata finito (DFA) de 4 estados.



[ añadir comentario ] ( 1331 visualizaciones )   |  [ 0 trackbacks ]   |  enlace permanente  |   ( 3 / 3485 )
Programación orientada a aspectos en Java 
La programación orientada a aspectos (AOP) se plantea como paradigma que "extiende" el concepto de programación orientada a objetos (OOP). Se basa en el concepto de las tareas "transversales". El ejemplo más sencillo sería el de los logs: La funcionalidad de log es transversal a todas las clases de un proyecto.

En la wikipedia hay una buena explicación sobre lo que es la AOP (http://es.wikipedia.org/wiki/Programaci ... a_aspectos) y no entraré en detalles. No es mi intención dar una extensa explicación sobre este paradigma pero sí arrojar algo de luz sobre cómo utilizarlo en Java.

El proyecto AspectJ permite el uso de este paradigma en el lenguaje Java. AspectJ puede ser utilizado de dos formas diferentes.

- Mediante la extensión del lenguaje Java (utilizando una sintaxis estendida de Java sólo posible utilizando un compilador aparte).
- Mediante la funcionalidad de las anotaciones (disponible a partir Java 5), denominada "@AspectJ".

Esta última modalidad es, a mi entender, la más cómoda ya que no necesita de un compilador específico y es más fácil de integrar en proyectos existentes de Java. Por otro lado, la primera modalidad está pensada para su uso desde el entorno de desarrollo Eclipse y es más complicado integrarla con otros entornos como Netbeans.

El mejor punto de arranque para empezar a curiosear con AspectJ es este post que encontré en un blog sobre programación:
- http://www.andrewewhite.net/wordpress/2 ... -tutorial/.

Para aquellas personas que quieran profundizar en este mundo recomiendo echarle un vistazo a esta hoja de referencia:
- http://blog.espenberntsen.net/2010/03/2 ... eat-sheet/.

[ añadir comentario ] ( 1319 visualizaciones )   |  [ 0 trackbacks ]   |  enlace permanente  |   ( 3 / 1788 )
Luces del belén controladas por una placa Arduino en función de la luz ambiente 
He construido un sencillo circuito utilizando una placa Arduino para controlar las luces de un belén. El procesador genera destellos aleatorios en función de la luz ambiente que mide a través de una de las entradas analógicas.

A continuación el código fuente para Arduino:
#define  NUM_ESTRELLAS  5
#define MS_BUCLE 500

int pines[NUM_ESTRELLAS] = {
2, 3, 4, 5, 6
};


void setup() {
int n;
randomSeed(analogRead(0));
for (n = 0; n < NUM_ESTRELLAS; n++)
pinMode(pines[n], OUTPUT);
}


void loop() {
int n;
int v = analogRead(0);
for (n = 0; n < NUM_ESTRELLAS; n++) {
int r = random(0, 1023);
if (r < v)
digitalWrite(pines[n], HIGH);
else
digitalWrite(pines[n], LOW);
}
delay(MS_BUCLE);
}



[ añadir comentario ] ( 5960 visualizaciones )   |  [ 0 trackbacks ]   |  enlace permanente  |   ( 3 / 1810 )
Usar fuentes personalizadas en un componente TextView desde XML 
Inauguro la sección de desarrollo Android de mi blog con un problema que se puede dar a la hora de desarrollar una app en Android y que, casi siempre, se soluciona de forma puramente programática: El uso de fuentes propias de tipo TrueType u OpenType en los textos de nuestra app.

Lo habitual es poner el componente TextView en el layout y luego, desde código, hacer lo siguiente:
TextView text = (TextView) findViewById(R.id.miTextView);
Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/fuente.otf");
text.setTypeface(tf);

Esta aproximación puramente programática a la solución del problema tiene un inconveniente clarísimo: Hay que hacer esto para cada componente TextView al que le queramos cambiar la fuente.

La solución que he encontrado es híbrida (mitad XML, mitad programática), pero requiere de mucho menos esfuerzo y es mucho más modular y elegante:

1. Lo primero que hay que hacer es colocar los ficheros TrueType y/o OpenType en la carpeta assets/fonts de nuestro proyecto.

2. Creamos una clase que herede de TextView, parecida a esta :-)
package org.atlantes.avelino.android;

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import java.util.HashMap;

public class MyTextView extends TextView {
protected static HashMap<String,Typeface> typefaceCache
= new HashMap<String,Typeface>();

public MyTextView(Context context) {
super(context);
}

public MyTextView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
this.init(attributeSet.getAttributeValue(
"http://avelino.atlantes.org/android",
"fontFile"));
}

public MyTextView(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
this.init(attributeSet.getAttributeValue(
"http://avelino.atlantes.org/android",
"fontFile"));
}

protected final void init(String fileName) {
if (fileName != null) {
Typeface tf = typefaceCache.get(fileName);
if (tf == null) {
tf = Typeface.createFromAsset(
this.getContext().getAssets(),
"fonts/" + fileName);
typefaceCache.put(fileName, tf);
}
this.setTypeface(tf);
}
}
}

3. En el fichero de layout podemos utilizar el nuevo componente MyTextView. Ojo con el nuevo namespace que debemos usar en el XML para el nuevo atributo fontFile:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:avelino="http://avelino.atlantes.org/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
...
<org.atlantes.avelino.android.MyTextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="abcd" android:textSize="50sp"
avelino:fontFile="fuente.ttf"/>
...
</LinearLayout>

Ya tenemos nuestro propio TextView que nos permite indicar la fuente que queremos usar en el propio XML :-)

[ añadir comentario ] ( 1329 visualizaciones )   |  [ 0 trackbacks ]   |  enlace permanente  |   ( 3 / 1922 )

<< <Anterior | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Siguiente> >>