Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // COMS20001 - Cellular Automaton Farm - Initial Code Skeleton
- // (using the XMOS i2c accelerometer demo)
- #include <platform.h>
- #include <xs1.h>
- #include <stdio.h>
- #include "pgmIO.h"
- #include "i2c.h"
- #define IMHT 16 //image height
- #define IMWD 16 //image width
- #define WORKERS 8 //the number of worker threads running
- #define HT 2 //the number of lines each worker will modified
- typedef unsigned char uchar; //using uchar as shorthand
- //placed on tile[0]
- port p_scl = on tile[0] : XS1_PORT_1E; //interface ports to accelerometer
- port p_sda = on tile[0] : XS1_PORT_1F;
- in port buttons = on tile[0] : XS1_PORT_4E; //port to access xCore-200 buttons
- out port leds = on tile[0] : XS1_PORT_4F; //port to access xCore-200 leds
- #define FXOS8700EQ_I2C_ADDR 0x1E //register addresses for accelerometer
- #define FXOS8700EQ_XYZ_DATA_CFG_REG 0x0E
- #define FXOS8700EQ_CTRL_REG_1 0x2A
- #define FXOS8700EQ_DR_STATUS 0x0
- #define FXOS8700EQ_OUT_X_MSB 0x1
- #define FXOS8700EQ_OUT_X_LSB 0x2
- #define FXOS8700EQ_OUT_Y_MSB 0x3
- #define FXOS8700EQ_OUT_Y_LSB 0x4
- #define FXOS8700EQ_OUT_Z_MSB 0x5
- #define FXOS8700EQ_OUT_Z_LSB 0x6
- //function converts a decimal number into binary
- int decimal_binary(int n) {
- int rem, i=1, binary=0;
- while (n != 0) {
- rem =n%2;
- n/=2;
- binary+=rem*i;
- i*=10;
- }
- return binary;
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- //
- // Read Image from PGM file from path infname[] to channel c_out
- //
- /////////////////////////////////////////////////////////////////////////////////////////
- void DataInStream(char infname[], chanend c_out)
- {
- int res;
- uchar line[ IMWD ];
- printf( "DataInStream: Start...\n" );
- //Open PGM file
- res = _openinpgm( infname, IMWD, IMHT );
- if( res ) {
- printf( "DataInStream: Error openening %s\n.", infname );
- return;
- }
- //Read image line-by-line and send byte by byte to channel c_out
- for( int y = 0; y < IMHT; y++ ) {
- _readinline( line, IMWD );
- for( int x = 0; x < IMWD; x++ ) {
- c_out <: line[ x ];
- //printf( "-%4.1d ", line[ x ] ); //show image values
- }
- //printf( "\n" );
- }
- //Close PGM image file
- _closeinpgm();
- printf( "DataInStream:Done...\n" );
- return;
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- //
- // Start your implementation by changing this function to implement the game of life
- // by farming out parts of the image to worker threads who implement it...
- // Currently the function just inverts the image
- //
- /////////////////////////////////////////////////////////////////////////////////////////
- void distributor(chanend c_in, chanend c_out, chanend fromAcc, chanend c[n], unsigned n, in port b, out port a)
- {
- //Starting up and wait for SW1 button press of the xCore-200 Explorer
- printf( "ProcessImage:Start, size = %dx%d\n", IMHT, IMWD );
- //waiting for SW1 to be pressed before reading and processing the image
- printf("\nWaiting for SW1 button press...\n");
- int r;
- while(1) {
- b when pinsneq(15) :> r; //check if some buttons are pressed
- if(r == 14) {
- break;
- }
- }
- //lighting the green LED to indicate the image being read
- a <: 4;
- //image array stores the processed image
- uchar image[IMHT][IMWD];
- //Read in and do something with your image values..
- //This just inverts every pixel, but you should
- //change the image according to the "Game of Life"
- printf( "Processing...\n" );
- for( int y = 0; y < IMHT; y++ ) { //go through all lines
- for( int x = 0; x < IMWD; x++ ) { //go through each pixel per line
- c_in :> image[y][x];
- }
- }
- //turning off the green LED to indicate finished reading
- a <: 0;
- //bin array stores the binary representation of the image
- uchar bin[IMHT][IMWD / 8];
- //convert the image to a binary representation
- int total = 0;
- int bitValue = 128;
- int indexY = 0;
- int indexX = 0;
- for(int y = 0; y < IMHT; y++) {
- indexX = 0;
- for(int x = 0; x < IMWD; x++) {
- if(image[y][x] == 255) {
- total += bitValue;
- }
- bitValue /= 2;
- if(x % 8 == 7) {
- bin[indexY][indexX] = total;
- indexX++;
- total = 0;
- bitValue = 128;
- }
- }
- indexY++;
- }
- //int used to represent the led states
- int ledState = 1;
- a <: ledState;
- //currently processes the image a set amount of times
- for(int p = 0; p < 30; p++) {
- //sending the lines to the workers
- for(int i = 0; i < WORKERS; i++) {
- int h = i * HT;
- //send the line above
- if(i == 0) {
- for(int x = 0; x < IMWD / 8; x++) {
- c[i] <: bin[IMHT -1][x];
- }
- } else {
- for(int x = 0; x < IMWD / 8; x++) {
- c[i] <: bin[h - 1][x];
- }
- }
- //send the two lines too be modified
- for(int y = h ; y < h + HT; y++) {
- for(int x = 0; x < IMWD / 8; x++) {
- c[i] <: bin[y][x];
- }
- }
- //send the line below
- if(i == WORKERS - 1) {
- for(int x = 0; x < IMWD / 8; x++) {
- c[i] <: bin[0][x];
- }
- } else {
- for(int x = 0; x < IMWD / 8; x++) {
- c[i] <: bin[h + HT][x];
- }
- }
- }
- //recieve the modified lines from the worker threads
- int finishedThreads = 0;
- //the count array contains the number of data values recieved from each thread so far
- int count[WORKERS];
- for(int i = 0; i < WORKERS; i++) {
- count[i] = 0;
- }
- while(1) {
- if(finishedThreads == WORKERS) break;
- select {
- case c[int j] :> uchar data:
- int y = count[j] / (IMWD / 8) + j * HT;
- int x = count[j] % (IMWD / 8);
- bin[y][x] = data;
- count[j] += 1;
- if(count[j] == (IMWD / 8) * HT) {
- finishedThreads++;
- }
- break;
- }
- }
- //alternating seperate green LED state once per processing round
- if(ledState == 1) {
- ledState = 0;
- a <: ledState;
- } else {
- ledState = 1;
- a <: ledState;
- }
- printf( "\nProcessing round %d completed...\n", p + 1);
- }
- //turn off all LEDs
- a <: 0;
- printf("\nWating for SW2 button press...\n");
- //wait for button SW2 to be pressed fore making the output pgm
- while(1) {
- b when pinsneq(15) :> r; //check if some buttons are pressed
- if(r == 13) {
- break;
- }
- }
- //convert the binary data back to the image
- for(int y = 0; y < IMHT; y++) {
- for(int x = 0; x < IMWD / 8; x++) {
- unsigned int a = decimal_binary(bin[y][x]);
- for(int i = 7; i >= 0; i--) {
- if(a % 10 == 0) {
- image[y][x * 8 + i] = 0;
- } else {
- image[y][x * 8 + i] = 255;
- }
- a = a / 10;
- }
- }
- }
- printf("\nMaking output pgm...\n");
- //turn on blue LED to indicate ongoing export
- a <: 2;
- //make a pgm of the new state
- for(int y = 0; y < IMHT; y++) {
- for(int x = 0; x < IMWD; x++) {
- c_out <: (uchar) image[y][x];
- }
- }
- //turn off all LEDs
- a <: 0;
- printf("\nOutput pgm made\n");
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- //
- // Worker thread to solve part of the task
- //
- /////////////////////////////////////////////////////////////////////////////////////////
- void workerThread(chanend c, int n) {
- uchar image[HT + 2][IMWD];
- uchar newImage[HT][IMWD];
- uchar bin[HT + 2][IMWD / 8];
- while(1) {
- for(int y = 0; y < HT; y++) {
- for(int x = 0; x < IMWD; x++) {
- newImage[y][x] = 0;
- }
- }
- //recieve the binary image array from the distributor thread
- for(int y = 0; y < HT + 2; y++) {
- for(int x = 0; x < IMWD / 8; x++) {
- c :> bin[y][x];
- }
- }
- //convert the binary data back to the image
- for(int y = 0; y < HT + 2; y++) {
- for(int x = 0; x < IMWD / 8; x++) {
- unsigned int a = decimal_binary(bin[y][x]);
- for(int i = 7; i >= 0; i--) {
- if(a % 10 == 0) {
- image[y][x * 8 + i] = 0;
- } else {
- image[y][x * 8 + i] = 255;
- }
- a = a / 10;
- }
- }
- }
- //run 1 iteration of the algorithm
- for(int y = 1; y < HT +1; y++) {
- for(int x = 0; x < IMWD; x++) {
- int num = 0;
- //check the pixel to the right
- if(x == IMWD - 1) {
- if(image[y][0] == 255) {
- num++;
- }
- } else {
- if(image[y][x + 1] == 255) {
- num++;
- }
- }
- //check the pixel to the left
- if(x == 0) {
- if(image[y][IMWD - 1] == 255) {
- num++;
- }
- } else {
- if(image[y][x - 1] == 255) {
- num++;
- }
- }
- //check the pixel above
- if(image[y - 1][x] == 255) {
- num++;
- }
- //check the pixel below
- if(image[y + 1][x] == 255) {
- num++;
- }
- //check the above right pixel
- if(x == IMWD - 1) {
- if(image[y-1][0] == 255) {
- num++;
- }
- }
- else {
- if(image[y-1][x+1] == 255) {
- num++;
- }
- }
- //check the above left pixel
- if(x == 0) {
- if(image[y-1][IMWD - 1] == 255) {
- num++;
- }
- }
- else {
- if(image[y-1][x-1] == 255) {
- num++;
- }
- }
- //check the below right pixel
- if(x == IMWD - 1) {
- if(image[y+1][0] == 255) {
- num++;
- }
- } else {
- if(image[y+1][x+1] == 255) {
- num++;
- }
- }
- //check the below left pixel
- if(x == 0) {
- if(image[y+1][IMWD - 1] == 255) {
- num++;
- }
- } else {
- if(image[y+1][x-1] == 255) {
- num++;
- }
- }
- //change the cells
- if(image[y][x] == 255) {
- if(num != 3) {
- newImage[y-1][x] = 0;
- } else {
- newImage[y-1][x]= 255;
- }
- } else if(image[y][x] == 0) {
- if(num == 3) {
- newImage[y-1][x] = 255;
- }
- }
- }
- }
- //convert the new image to binary data
- int total = 0;
- int bitValue = 128;
- int indexY = 0;
- int indexX = 0;
- for(int y = 0; y < HT; y++) {
- indexX = 0;
- for(int x = 0; x < IMWD; x++) {
- if(newImage[y][x] == 255) {
- total += bitValue;
- }
- bitValue /= 2;
- if(x % 8 == 7) {
- bin[indexY][indexX] = total;
- indexX++;
- total = 0;
- bitValue = 128;
- }
- }
- indexY++;
- }
- //send the modified state back to the distributor thread
- for(int y = 0; y < HT; y++) {
- for(int x = 0; x < IMWD / 8; x++) {
- c <: bin[y][x];
- }
- }
- }
- printf("Thread finished\n");
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- //
- // Write pixel stream from channel c_in to PGM image file
- //
- /////////////////////////////////////////////////////////////////////////////////////////
- void DataOutStream(char outfname[], chanend c_in)
- {
- int res;
- uchar line[ IMWD ];
- //Open PGM file
- printf( "DataOutStream:Start...\n" );
- res = _openoutpgm( outfname, IMWD, IMHT );
- if( res ) {
- printf( "DataOutStream:Error opening %s\n.", outfname );
- return;
- }
- //Compile each line of the image and write the image line-by-line
- for( int y = 0; y < IMHT; y++ ) {
- for( int x = 0; x < IMWD; x++ ) {
- c_in :> line[ x ];
- }
- _writeoutline( line, IMWD );
- }
- //Close the PGM image
- _closeoutpgm();
- printf( "DataOutStream:Done...\n" );
- return;
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- //
- // Initialise and read accelerometer, send first tilt event to channel
- //
- /////////////////////////////////////////////////////////////////////////////////////////
- void accelerometer(client interface i2c_master_if i2c, chanend toDist) {
- i2c_regop_res_t result;
- char status_data = 0;
- int tilted = 0;
- // Configure FXOS8700EQ
- result = i2c.write_reg(FXOS8700EQ_I2C_ADDR, FXOS8700EQ_XYZ_DATA_CFG_REG, 0x01);
- if (result != I2C_REGOP_SUCCESS) {
- printf("I2C write reg failed\n");
- }
- // Enable FXOS8700EQ
- result = i2c.write_reg(FXOS8700EQ_I2C_ADDR, FXOS8700EQ_CTRL_REG_1, 0x01);
- if (result != I2C_REGOP_SUCCESS) {
- printf("I2C write reg failed\n");
- }
- //Probe the accelerometer x-axis forever
- while (1) {
- //check until new accelerometer data is available
- do {
- status_data = i2c.read_reg(FXOS8700EQ_I2C_ADDR, FXOS8700EQ_DR_STATUS, result);
- } while (!status_data & 0x08);
- //get new x-axis tilt value
- int x = read_acceleration(i2c, FXOS8700EQ_OUT_X_MSB);
- //send signal to distributor after first tilt
- if (!tilted) {
- if (x>30) {
- tilted = 1 - tilted;
- toDist <: 1;
- }
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- //
- // Orchestrate concurrent system and start up all threads
- //
- /////////////////////////////////////////////////////////////////////////////////////////
- int main(void) {
- i2c_master_if i2c[1]; //interface to accelerometer
- //char infname[] = "test.pgm"; //put your input image path here
- //char outfname[] = "testout.pgm"; //put your output image path here
- chan c_inIO, c_outIO, c_control; //extend your channel definitions here
- //currently only one worker thread
- chan c[WORKERS];
- par {
- on tile[0] : i2c_master(i2c, 1, p_scl, p_sda, 10); //server thread providing accelerometer data
- on tile[0] : accelerometer(i2c[0],c_control); //client thread reading accelerometer data
- on tile[0] : DataInStream("test.pgm", c_inIO); //thread to read in a PGM image
- on tile[0] : DataOutStream("testout.pgm", c_outIO); //thread to write out a PGM image
- on tile[0] : distributor(c_inIO, c_outIO, c_control, c, WORKERS, buttons, leds);//thread to coordinate work on image
- par (int i = 0; i < WORKERS; i++) {
- on tile[1] : workerThread(c[i], i); //worker threads to run game of life
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement