Code:
#define RUNNING_ON_PC
#define NUMBEROFNEURONS 30
//********************** RUNNIN ON PC ***********************************
#ifdef RUNNING_ON_PC
#include <iostream>
#include <stdint.h>
using namespace std;
#define FOREVER while(1)
typedef uint8_t uns8; // stdint.h compatibility
typedef bool BOOL;
#define FALSE 0
#define TRUE 1
// funktioniert nicht
static unsigned char* FSR;
#define INDF (*FSR)
#define LINK_SRC 0
#define LINK_DST 1
#define LINK_USE 2
/*
#define src 0
#define dst 1
#define use 2
*/
#endif
//************************** RUNNING ON PIC ***************************************
#ifdef PIC
#include "allpic.h"
#pragma config = 0b000110000100 // hex-datei: fuses des 12F629
#pragma cdata[0x2100] = \
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,0xFF,0,0,\
0xFF,0xFF // eeprom initialisierung
#define EE_ROM // eeprom nutzen
#include "pic_mem.h"
#include "timeloop.h"
// LINK-Zugriffe
#define LINK_RD(a,m) ee_read((a) + offsetof(struct _link,m))
#define LINK_WR(a,m,v) ee_write((a) + offsetof(struct _link,m),v)
#endif
#define OUT_0 0 // GPIO
#define OUT_1 1 //
#define OUT_2 2 //
#define IN_2 3 //
#define IN_1 4 //
#define IN_0 5 //
//** alle sensoren, aktoren, triebe und neuronen nach abstraktion gestaffelt ******
uns8 zellen[30]; // zellen im RAM anlegen
#define FIRE_LIMIT 10 // fire_limit
#define RD_SUM (INDF & 0x3F) // ZELL-Zugriffe
#define WR_SUM(s) {INDF &= ~0x3F; INDF |= (s);}
#ifdef RUNNING_ON_PIC
#define RD_FIRE_REQ (INDF.7)
#define WR_FIRE_REQ(b) {INDF.7 = (b);}
#endif
#ifdef RUNNING_ON_PC
#define RD_FIRE_REQ !!(INDF>>7)
#define WR_FIRE_REQ(b) {INDF&=~0x80;INDF|=b;} //{INDF.7 = (b);}
#endif
#define SENS_0 0 // Sensoren
#define SENS_1 1
#define SENS_2 2
#define AKT_0 3 // spezialzellen definieren
#define AKT_1 4
#define AKT_2 5
#define TIMER 6 // Timer-Zelle
#define HUNGER 7 // Hunger-Zelle
#define FIRST_NEURON 8 // Beginn des Hirns
//******* verbunden werden zellen mit vielen links (dendriten) *********
#define NO_LINK -1
#define MAX_LINKS (128 / sizeof(struct _link)) // viele links im EEPROM
struct _link { // struktur eines EEPROM-links
uns8 src; // leerer link: src_zelle == NO_LINK
uns8 dst; // verbindet source- mit dest-zelle
uns8 use; // nützlichkeit dieses links
};
//********************** RUNNIN ON PC ***********************************
#ifdef RUNNING_ON_PC
_link Simulated_EEPROM[NUMBEROFNEURONS];
uns8 LINK_RD(uns8 address, uns8 component)
{
uns8 value = 0;
if (component == LINK_SRC) value = Simulated_EEPROM[address].src;
if (component == LINK_DST) value = Simulated_EEPROM[address].dst;
if (component == LINK_USE) value = Simulated_EEPROM[address].use;
return value;
}
void LINK_WR(uns8 address, uns8 component, uns8 value)
{
if (address < NUMBEROFNEURONS)
{
if (component == LINK_SRC) Simulated_EEPROM[address].src = value;
if (component == LINK_DST) Simulated_EEPROM[address].dst = value;
if (component == LINK_USE) Simulated_EEPROM[address].use = value;
} else
{
cout << "Error: link address out of range " + address << endl;
// Serial.print("Error: link address out of range "); Serial.println(address);
// delay(100);
}
}
#endif
static uns8 rand_link; // randomize link
static uns8 pattern;
static uns8 learn;
static void gi_lerne(void) // die genesis
{
uns8 zell_ind = 0, link, free, buf;
BOOL hit;
do { // Suche feuernde zellen
FSR = &zellen[zell_ind]; // pointer auf zelle
/**** sensoren, aktoren und triebe sind besondere zellen *****/
/*
switch(zell_ind) {
case SENS_0: WR_FIRE_REQ(pattern.0); break;
case SENS_1: WR_FIRE_REQ(pattern.1); break;
case SENS_2: WR_FIRE_REQ(FALSE); break;
case AKT_0: GPIO.OUT_0 = RD_FIRE_REQ; continue;
case AKT_1: GPIO.OUT_1 = RD_FIRE_REQ; continue;
case AKT_2: GPIO.OUT_2 = RD_FIRE_REQ; continue;
default: break;
}
*/
/***** diese zeilen sind der kern des systems *****************/
if(!RD_FIRE_REQ) continue; // zelle möchte nicht feuern
WR_FIRE_REQ(FALSE); // zell-feuerwunsch wird nun erfüllt
free = NO_LINK; link = 0; hit = FALSE; // verfolge die links
do { // alle links durchsuchen
buf = LINK_RD(link,LINK_SRC); // linkbyte lesen
if(buf == NO_LINK) free = link; // leeren link merken
else if(buf == zell_ind) { // einen link gefunden
uns8 hbuf = LINK_RD(link,LINK_USE); // nuetzlichkeit lesen
if(hbuf) hit = TRUE; // nutzlink gefunden
if(++hbuf > FIRE_LIMIT) hbuf = FIRE_LIMIT;// limitieren
FSR = zellen + LINK_RD(link,LINK_DST);// pointer auf dst-zelle
buf = RD_SUM + hbuf; // zellsumme berechnen
if(buf > FIRE_LIMIT) buf = FIRE_LIMIT; // limitieren
WR_SUM(buf); // zellsumme speichern
if((buf == FIRE_LIMIT)&&(!RD_FIRE_REQ)) {// will dst feuern?
WR_FIRE_REQ(TRUE); // FIRE_REQ vormerken
LINK_WR(link,LINK_USE,hbuf); // nuetzlichkeit inkrementieren
}
}
link += sizeof(struct _link); // nächsten link adressieren
} while(link < MAX_LINKS * sizeof(struct _link));
/** wenn kein nützlicher link gefunden und platz ist: erzeuge neuen link **/
if((!hit)&&(free != NO_LINK)) {
LINK_WR(free,LINK_SRC,zell_ind); // link neu erzeugen
if(learn) buf = learn; // gewollte verlinkung
else { // zufällige verlinkung
if(++rand_link >= sizeof(zellen)) rand_link = FIRST_NEURON;
buf = rand_link;
if((buf == zell_ind)&&(++buf >= sizeof(zellen))) buf = FIRST_NEURON;
}
LINK_WR(free,LINK_DST,buf);
LINK_WR(free,LINK_USE,0); // ob der link nützlich wird, weiß keiner
}
} while(++zell_ind < sizeof(zellen)); // nächste zelle
}
static void gi_verlerne(void) // links überarbeiten
{
uns8 link = 0, buf;
do { // alle links durchsuchen
if(LINK_RD(link,LINK_SRC) != NO_LINK) { // leere links skippen
buf = LINK_RD(link,LINK_USE); // nuetzlichkeit lesen
if(buf) LINK_WR(link,LINK_USE,--buf); // langsam verlernen
if(!buf) LINK_WR(link,LINK_SRC,NO_LINK);// link ganz löschen
}
link += sizeof(struct _link); // nächster link
} while(link < MAX_LINKS * sizeof(struct _link));
}
#define DELETE 0
#define REDUCE 1
#define SLEEP 2
static void gi_zellen(uns8 steuer) // zell-erregungen überarbeiten
{ // DELETE, REDUCE oder SLEEP
uns8 zell_ind = 0;
do { // Suche zellen
FSR = zellen + zell_ind;
if(steuer == DELETE) INDF = 0; // flags und summe auf einen schlag
else if(steuer == REDUCE) {if(RD_SUM) WR_SUM(RD_SUM - 1);}
else if(RD_SUM > FIRE_LIMIT) WR_SUM(FIRE_LIMIT);
} while(++zell_ind < sizeof(zellen)); // nächste zelle
}
#define NUMBER_OF_SIMULATION_STEPS 100
int main()
{
cout << "Gucki running" << endl;
#ifdef PIC
RP0 = 1; // erstmal alle Spezialregister...
#asm
DW /*CALL*/ 0x2000 + /*ADRESSE*/ 0x03FF // oscal abholen
#endasm
OSCCAL = W; // und Oszillatorkalibrierung speichern
OPTION = 0; // global weak-pullup ein (je 20kOhm)
WPU = _BV(IN_0) | _BV(IN_1) | _BV(IN_2);
TRISIO = _BV(IN_0) | _BV(IN_1) | _BV(IN_2); // eingänge
RP0 = 0; // normale register und ram
CMCON = 0x07; // komparator aus
timeloop_init(); // timer initialisieren
#endif
rand_link = FIRST_NEURON;
gi_zellen(DELETE); // zellerregungen löschen
uns8 loop = 0;
int steps=0;
for(steps=0;steps<NUMBER_OF_SIMULATION_STEPS;steps++)
{
switch(loop)
{
case 0: pattern = 0x01; learn = AKT_0; break;
case 1: pattern = 0x02; learn = AKT_1; break;
case 2: pattern = 0x03; learn = AKT_2; break;
default:
{
cout << "error, no pattern" << endl;
}//FOREVER;
}
gi_lerne();
loop++;
#ifdef WEG
gi_verlerne(); // links langsam verlernen
if(!++loop) {
gi_verlerne(); // links langsam verlernen
gi_zellen(SLEEP); // schlafen
}
else if(!(loop & 0x1F)) // alle 32 durchläufe
gi_zellen(REDUCE); // zellerregungen vermindern
#endif
}
cout << steps + " simulations steps done" << endl;
cout << " Gucki stopped" << endl;
//return 0;
}
/* ENDE */
Lesezeichen