Advertisement
Guest User

Untitled

a guest
Nov 26th, 2015
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.56 KB | None | 0 0
  1. // COMS20001 - Cellular Automaton Farm - Initial Code Skeleton
  2. // (using the XMOS i2c accelerometer demo)
  3.  
  4. #include <platform.h>
  5. #include <xs1.h>
  6. #include <stdio.h>
  7. #include "pgmIO.h"
  8. #include "i2c.h"
  9.  
  10. #define IMHT 16 //image height
  11. #define IMWD 16 //image width
  12.  
  13. #define WORKERS 8 //the number of worker threads running
  14. #define HT 2 //the number of lines each worker will modified
  15.  
  16. typedef unsigned char uchar; //using uchar as shorthand
  17.  
  18. //placed on tile[0]
  19. port p_scl = on tile[0] : XS1_PORT_1E; //interface ports to accelerometer
  20. port p_sda = on tile[0] : XS1_PORT_1F;
  21.  
  22. in port buttons = on tile[0] : XS1_PORT_4E; //port to access xCore-200 buttons
  23. out port leds = on tile[0] : XS1_PORT_4F; //port to access xCore-200 leds
  24.  
  25. #define FXOS8700EQ_I2C_ADDR 0x1E //register addresses for accelerometer
  26. #define FXOS8700EQ_XYZ_DATA_CFG_REG 0x0E
  27. #define FXOS8700EQ_CTRL_REG_1 0x2A
  28. #define FXOS8700EQ_DR_STATUS 0x0
  29. #define FXOS8700EQ_OUT_X_MSB 0x1
  30. #define FXOS8700EQ_OUT_X_LSB 0x2
  31. #define FXOS8700EQ_OUT_Y_MSB 0x3
  32. #define FXOS8700EQ_OUT_Y_LSB 0x4
  33.  
  34. #define FXOS8700EQ_OUT_Z_MSB 0x5
  35. #define FXOS8700EQ_OUT_Z_LSB 0x6
  36.  
  37. //function converts a decimal number into binary
  38. int decimal_binary(int n) {
  39. int rem, i=1, binary=0;
  40. while (n != 0) {
  41. rem =n%2;
  42. n/=2;
  43. binary+=rem*i;
  44. i*=10;
  45. }
  46. return binary;
  47. }
  48.  
  49. /////////////////////////////////////////////////////////////////////////////////////////
  50. //
  51. // Read Image from PGM file from path infname[] to channel c_out
  52. //
  53. /////////////////////////////////////////////////////////////////////////////////////////
  54. void DataInStream(char infname[], chanend c_out)
  55. {
  56. int res;
  57. uchar line[ IMWD ];
  58. printf( "DataInStream: Start...\n" );
  59.  
  60. //Open PGM file
  61. res = _openinpgm( infname, IMWD, IMHT );
  62. if( res ) {
  63. printf( "DataInStream: Error openening %s\n.", infname );
  64. return;
  65. }
  66.  
  67. //Read image line-by-line and send byte by byte to channel c_out
  68. for( int y = 0; y < IMHT; y++ ) {
  69. _readinline( line, IMWD );
  70. for( int x = 0; x < IMWD; x++ ) {
  71. c_out <: line[ x ];
  72. //printf( "-%4.1d ", line[ x ] ); //show image values
  73. }
  74. //printf( "\n" );
  75. }
  76.  
  77. //Close PGM image file
  78. _closeinpgm();
  79. printf( "DataInStream:Done...\n" );
  80. return;
  81. }
  82.  
  83. /////////////////////////////////////////////////////////////////////////////////////////
  84. //
  85. // Start your implementation by changing this function to implement the game of life
  86. // by farming out parts of the image to worker threads who implement it...
  87. // Currently the function just inverts the image
  88. //
  89. /////////////////////////////////////////////////////////////////////////////////////////
  90. void distributor(chanend c_in, chanend c_out, chanend fromAcc, chanend c[n], unsigned n, in port b, out port a)
  91. {
  92.  
  93. //Starting up and wait for SW1 button press of the xCore-200 Explorer
  94. printf( "ProcessImage:Start, size = %dx%d\n", IMHT, IMWD );
  95.  
  96. //waiting for SW1 to be pressed before reading and processing the image
  97. printf("\nWaiting for SW1 button press...\n");
  98. int r;
  99. while(1) {
  100. b when pinsneq(15) :> r; //check if some buttons are pressed
  101. if(r == 14) {
  102. break;
  103. }
  104. }
  105.  
  106. //lighting the green LED to indicate the image being read
  107. a <: 4;
  108.  
  109. //image array stores the processed image
  110. uchar image[IMHT][IMWD];
  111.  
  112. //Read in and do something with your image values..
  113. //This just inverts every pixel, but you should
  114. //change the image according to the "Game of Life"
  115. printf( "Processing...\n" );
  116. for( int y = 0; y < IMHT; y++ ) { //go through all lines
  117. for( int x = 0; x < IMWD; x++ ) { //go through each pixel per line
  118. c_in :> image[y][x];
  119. }
  120. }
  121.  
  122. //turning off the green LED to indicate finished reading
  123. a <: 0;
  124.  
  125. //bin array stores the binary representation of the image
  126. uchar bin[IMHT][IMWD / 8];
  127.  
  128. //convert the image to a binary representation
  129. int total = 0;
  130. int bitValue = 128;
  131. int indexY = 0;
  132. int indexX = 0;
  133.  
  134. for(int y = 0; y < IMHT; y++) {
  135. indexX = 0;
  136. for(int x = 0; x < IMWD; x++) {
  137. if(image[y][x] == 255) {
  138. total += bitValue;
  139. }
  140. bitValue /= 2;
  141. if(x % 8 == 7) {
  142. bin[indexY][indexX] = total;
  143. indexX++;
  144. total = 0;
  145. bitValue = 128;
  146. }
  147. }
  148. indexY++;
  149. }
  150.  
  151. //int used to represent the led states
  152. int ledState = 1;
  153. a <: ledState;
  154.  
  155. //currently processes the image a set amount of times
  156. for(int p = 0; p < 30; p++) {
  157.  
  158. //sending the lines to the workers
  159. for(int i = 0; i < WORKERS; i++) {
  160. int h = i * HT;
  161.  
  162. //send the line above
  163. if(i == 0) {
  164. for(int x = 0; x < IMWD / 8; x++) {
  165. c[i] <: bin[IMHT -1][x];
  166. }
  167. } else {
  168. for(int x = 0; x < IMWD / 8; x++) {
  169. c[i] <: bin[h - 1][x];
  170. }
  171. }
  172.  
  173. //send the two lines too be modified
  174. for(int y = h ; y < h + HT; y++) {
  175. for(int x = 0; x < IMWD / 8; x++) {
  176. c[i] <: bin[y][x];
  177. }
  178. }
  179.  
  180. //send the line below
  181. if(i == WORKERS - 1) {
  182. for(int x = 0; x < IMWD / 8; x++) {
  183. c[i] <: bin[0][x];
  184. }
  185. } else {
  186. for(int x = 0; x < IMWD / 8; x++) {
  187. c[i] <: bin[h + HT][x];
  188. }
  189. }
  190.  
  191. }
  192.  
  193. //recieve the modified lines from the worker threads
  194. int finishedThreads = 0;
  195. //the count array contains the number of data values recieved from each thread so far
  196. int count[WORKERS];
  197. for(int i = 0; i < WORKERS; i++) {
  198. count[i] = 0;
  199. }
  200.  
  201. while(1) {
  202. if(finishedThreads == WORKERS) break;
  203. select {
  204. case c[int j] :> uchar data:
  205. int y = count[j] / (IMWD / 8) + j * HT;
  206. int x = count[j] % (IMWD / 8);
  207. bin[y][x] = data;
  208. count[j] += 1;
  209. if(count[j] == (IMWD / 8) * HT) {
  210. finishedThreads++;
  211. }
  212. break;
  213. }
  214. }
  215.  
  216. //alternating seperate green LED state once per processing round
  217. if(ledState == 1) {
  218. ledState = 0;
  219. a <: ledState;
  220. } else {
  221. ledState = 1;
  222. a <: ledState;
  223. }
  224.  
  225. printf( "\nProcessing round %d completed...\n", p + 1);
  226. }
  227.  
  228. //turn off all LEDs
  229. a <: 0;
  230.  
  231. printf("\nWating for SW2 button press...\n");
  232.  
  233. //wait for button SW2 to be pressed fore making the output pgm
  234. while(1) {
  235. b when pinsneq(15) :> r; //check if some buttons are pressed
  236. if(r == 13) {
  237. break;
  238. }
  239. }
  240.  
  241. //convert the binary data back to the image
  242. for(int y = 0; y < IMHT; y++) {
  243. for(int x = 0; x < IMWD / 8; x++) {
  244. unsigned int a = decimal_binary(bin[y][x]);
  245. for(int i = 7; i >= 0; i--) {
  246. if(a % 10 == 0) {
  247. image[y][x * 8 + i] = 0;
  248. } else {
  249. image[y][x * 8 + i] = 255;
  250. }
  251. a = a / 10;
  252. }
  253. }
  254. }
  255.  
  256. printf("\nMaking output pgm...\n");
  257.  
  258. //turn on blue LED to indicate ongoing export
  259. a <: 2;
  260.  
  261. //make a pgm of the new state
  262. for(int y = 0; y < IMHT; y++) {
  263. for(int x = 0; x < IMWD; x++) {
  264. c_out <: (uchar) image[y][x];
  265. }
  266. }
  267.  
  268. //turn off all LEDs
  269. a <: 0;
  270.  
  271. printf("\nOutput pgm made\n");
  272.  
  273. }
  274.  
  275. /////////////////////////////////////////////////////////////////////////////////////////
  276. //
  277. // Worker thread to solve part of the task
  278. //
  279. /////////////////////////////////////////////////////////////////////////////////////////
  280. void workerThread(chanend c, int n) {
  281. uchar image[HT + 2][IMWD];
  282. uchar newImage[HT][IMWD];
  283. uchar bin[HT + 2][IMWD / 8];
  284.  
  285. while(1) {
  286.  
  287. for(int y = 0; y < HT; y++) {
  288. for(int x = 0; x < IMWD; x++) {
  289. newImage[y][x] = 0;
  290. }
  291. }
  292.  
  293. //recieve the binary image array from the distributor thread
  294. for(int y = 0; y < HT + 2; y++) {
  295. for(int x = 0; x < IMWD / 8; x++) {
  296. c :> bin[y][x];
  297. }
  298. }
  299.  
  300. //convert the binary data back to the image
  301. for(int y = 0; y < HT + 2; y++) {
  302. for(int x = 0; x < IMWD / 8; x++) {
  303. unsigned int a = decimal_binary(bin[y][x]);
  304. for(int i = 7; i >= 0; i--) {
  305. if(a % 10 == 0) {
  306. image[y][x * 8 + i] = 0;
  307. } else {
  308. image[y][x * 8 + i] = 255;
  309. }
  310. a = a / 10;
  311. }
  312. }
  313. }
  314.  
  315. //run 1 iteration of the algorithm
  316. for(int y = 1; y < HT +1; y++) {
  317. for(int x = 0; x < IMWD; x++) {
  318. int num = 0;
  319. //check the pixel to the right
  320. if(x == IMWD - 1) {
  321. if(image[y][0] == 255) {
  322. num++;
  323. }
  324. } else {
  325. if(image[y][x + 1] == 255) {
  326. num++;
  327. }
  328. }
  329. //check the pixel to the left
  330. if(x == 0) {
  331. if(image[y][IMWD - 1] == 255) {
  332. num++;
  333. }
  334. } else {
  335. if(image[y][x - 1] == 255) {
  336. num++;
  337. }
  338. }
  339. //check the pixel above
  340.  
  341. if(image[y - 1][x] == 255) {
  342. num++;
  343. }
  344. //check the pixel below
  345.  
  346. if(image[y + 1][x] == 255) {
  347. num++;
  348. }
  349.  
  350. //check the above right pixel
  351. if(x == IMWD - 1) {
  352. if(image[y-1][0] == 255) {
  353. num++;
  354. }
  355. }
  356. else {
  357. if(image[y-1][x+1] == 255) {
  358. num++;
  359. }
  360. }
  361. //check the above left pixel
  362. if(x == 0) {
  363. if(image[y-1][IMWD - 1] == 255) {
  364. num++;
  365. }
  366. }
  367. else {
  368. if(image[y-1][x-1] == 255) {
  369. num++;
  370. }
  371. }
  372. //check the below right pixel
  373. if(x == IMWD - 1) {
  374. if(image[y+1][0] == 255) {
  375. num++;
  376. }
  377. } else {
  378. if(image[y+1][x+1] == 255) {
  379. num++;
  380. }
  381. }
  382. //check the below left pixel
  383. if(x == 0) {
  384. if(image[y+1][IMWD - 1] == 255) {
  385. num++;
  386. }
  387. } else {
  388. if(image[y+1][x-1] == 255) {
  389. num++;
  390. }
  391. }
  392. //change the cells
  393. if(image[y][x] == 255) {
  394. if(num != 3) {
  395. newImage[y-1][x] = 0;
  396. } else {
  397. newImage[y-1][x]= 255;
  398. }
  399. } else if(image[y][x] == 0) {
  400. if(num == 3) {
  401. newImage[y-1][x] = 255;
  402. }
  403. }
  404. }
  405. }
  406.  
  407. //convert the new image to binary data
  408. int total = 0;
  409. int bitValue = 128;
  410. int indexY = 0;
  411. int indexX = 0;
  412.  
  413. for(int y = 0; y < HT; y++) {
  414. indexX = 0;
  415. for(int x = 0; x < IMWD; x++) {
  416. if(newImage[y][x] == 255) {
  417. total += bitValue;
  418. }
  419. bitValue /= 2;
  420. if(x % 8 == 7) {
  421. bin[indexY][indexX] = total;
  422. indexX++;
  423. total = 0;
  424. bitValue = 128;
  425. }
  426. }
  427. indexY++;
  428. }
  429.  
  430. //send the modified state back to the distributor thread
  431. for(int y = 0; y < HT; y++) {
  432. for(int x = 0; x < IMWD / 8; x++) {
  433. c <: bin[y][x];
  434. }
  435. }
  436. }
  437. printf("Thread finished\n");
  438. }
  439.  
  440. /////////////////////////////////////////////////////////////////////////////////////////
  441. //
  442. // Write pixel stream from channel c_in to PGM image file
  443. //
  444. /////////////////////////////////////////////////////////////////////////////////////////
  445. void DataOutStream(char outfname[], chanend c_in)
  446. {
  447. int res;
  448. uchar line[ IMWD ];
  449.  
  450. //Open PGM file
  451. printf( "DataOutStream:Start...\n" );
  452. res = _openoutpgm( outfname, IMWD, IMHT );
  453. if( res ) {
  454. printf( "DataOutStream:Error opening %s\n.", outfname );
  455. return;
  456. }
  457.  
  458. //Compile each line of the image and write the image line-by-line
  459. for( int y = 0; y < IMHT; y++ ) {
  460. for( int x = 0; x < IMWD; x++ ) {
  461. c_in :> line[ x ];
  462. }
  463. _writeoutline( line, IMWD );
  464. }
  465.  
  466. //Close the PGM image
  467. _closeoutpgm();
  468. printf( "DataOutStream:Done...\n" );
  469. return;
  470. }
  471.  
  472. /////////////////////////////////////////////////////////////////////////////////////////
  473. //
  474. // Initialise and read accelerometer, send first tilt event to channel
  475. //
  476. /////////////////////////////////////////////////////////////////////////////////////////
  477. void accelerometer(client interface i2c_master_if i2c, chanend toDist) {
  478. i2c_regop_res_t result;
  479. char status_data = 0;
  480. int tilted = 0;
  481.  
  482. // Configure FXOS8700EQ
  483. result = i2c.write_reg(FXOS8700EQ_I2C_ADDR, FXOS8700EQ_XYZ_DATA_CFG_REG, 0x01);
  484. if (result != I2C_REGOP_SUCCESS) {
  485. printf("I2C write reg failed\n");
  486. }
  487.  
  488. // Enable FXOS8700EQ
  489. result = i2c.write_reg(FXOS8700EQ_I2C_ADDR, FXOS8700EQ_CTRL_REG_1, 0x01);
  490. if (result != I2C_REGOP_SUCCESS) {
  491. printf("I2C write reg failed\n");
  492. }
  493.  
  494. //Probe the accelerometer x-axis forever
  495. while (1) {
  496.  
  497. //check until new accelerometer data is available
  498. do {
  499. status_data = i2c.read_reg(FXOS8700EQ_I2C_ADDR, FXOS8700EQ_DR_STATUS, result);
  500. } while (!status_data & 0x08);
  501.  
  502. //get new x-axis tilt value
  503. int x = read_acceleration(i2c, FXOS8700EQ_OUT_X_MSB);
  504.  
  505. //send signal to distributor after first tilt
  506. if (!tilted) {
  507. if (x>30) {
  508. tilted = 1 - tilted;
  509. toDist <: 1;
  510. }
  511. }
  512.  
  513. }
  514. }
  515.  
  516. /////////////////////////////////////////////////////////////////////////////////////////
  517. //
  518. // Orchestrate concurrent system and start up all threads
  519. //
  520. /////////////////////////////////////////////////////////////////////////////////////////
  521. int main(void) {
  522.  
  523. i2c_master_if i2c[1]; //interface to accelerometer
  524.  
  525. //char infname[] = "test.pgm"; //put your input image path here
  526. //char outfname[] = "testout.pgm"; //put your output image path here
  527. chan c_inIO, c_outIO, c_control; //extend your channel definitions here
  528.  
  529. //currently only one worker thread
  530. chan c[WORKERS];
  531.  
  532. par {
  533. on tile[0] : i2c_master(i2c, 1, p_scl, p_sda, 10); //server thread providing accelerometer data
  534. on tile[0] : accelerometer(i2c[0],c_control); //client thread reading accelerometer data
  535. on tile[0] : DataInStream("test.pgm", c_inIO); //thread to read in a PGM image
  536. on tile[0] : DataOutStream("testout.pgm", c_outIO); //thread to write out a PGM image
  537. on tile[0] : distributor(c_inIO, c_outIO, c_control, c, WORKERS, buttons, leds);//thread to coordinate work on image
  538. par (int i = 0; i < WORKERS; i++) {
  539. on tile[1] : workerThread(c[i], i); //worker threads to run game of life
  540. }
  541. }
  542.  
  543. return 0;
  544. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement