// a function to draw smile void draw_smile (void){ int row; for(unsigned char row = 16; row < 17; row++) { for( unsigned char col = 64; col < 67; col++ ) { LCD_set_pixel(row, col, 1); } } for(unsigned char row = 9; row < 10; row++) { for( unsigned char col = 62; col < 69; col++ ) { LCD_set_pixel(row, col, 1); } } //draw the eyes row = 20; for( unsigned char col = 58; col < 61; col++ ) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row, col+10, 1); LCD_set_pixel(row, 120-col, 1); LCD_set_pixel(row, 130-col, 1); row++; } //draw the mouth row = 9; for( unsigned char col = 68; col < 72; col++ ) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row, 130-col, 1); row++; } //draw the nose row = 15; for( unsigned char col = 63; col < 65; col++ ) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row, 130-col, 1); row++; } }
// a function to draw a smiley face void draw_smiley (void){ int num = 0; while(checkNoBtns()) { TMRSRVC_delay(100); LCD_clear(); if (num % 2==0) { draw_face(); draw_smile(); TMRSRVC_delay(2000); } else { draw_face(); draw_frown(); TMRSRVC_delay(2000); } num++; for(unsigned char row = 0; row < LCD_PIX_HEIGHT; row++) { for( unsigned char col = 0; col < LCD_PIX_WIDTH; col++ ) { LCD_set_pixel(row, col, 0); } } } }
void LCD_set_pixel_tr(uintCoord p, uint8_t transpose) { uintCoord pix; if (transpose > 0) { pix.x = p.y; pix.y = p.x; } else { pix = p; } LCD_set_pixel(pix); }
/* * a function that can test that sensor data can be output * to the LCD display in a meaningful manner and the normal * printf still works correctly */ void pixel_sensor_test(void) { while(checkNoBtns()) { TMRSRVC_delay(100); LCD_clear(); float leftIR = getLeftIR(); float rightIR = getRightIR(); float trimLeftIR = trim(2*leftIR, 0, LCD_PIX_WIDTH/2); float trimRightIR = trim(2*rightIR, 0, LCD_PIX_WIDTH/2); for(unsigned char i = 0; i < LCD_PIX_HEIGHT; i++) { LCD_set_pixel(i, LCD_PIX_WIDTH/2, i & 1); LCD_set_pixel(i, LCD_PIX_WIDTH/2 - trimLeftIR, 1); LCD_set_pixel(i, LCD_PIX_WIDTH/2-1 + trimRightIR, 1); } LCD_set_RC( 0, 0 ); LCD_printf("%.1f", (double)leftIR); LCD_set_RC( 0, 16 ); LCD_printf("%.1f", (double)rightIR); } }
/* * a function that tests that all the pixels in the LCD * can be turned on an off with the LCD_set_pixel function */ void all_pixel_test(void) { while(checkNoBtns()) { for(unsigned char row = 0; row < LCD_PIX_HEIGHT; row++) { for( unsigned char col = 0; col < LCD_PIX_WIDTH; col++ ) { LCD_set_pixel(row, col, 1); } } TMRSRVC_delay(2000); for(unsigned char row = 0; row < LCD_PIX_HEIGHT; row++) { for( unsigned char col = 0; col < LCD_PIX_WIDTH; col++ ) { LCD_set_pixel(row, col, 0); } } TMRSRVC_delay(2000); } }
// a function to draw face void draw_face (void){ int row; int col; for(unsigned char row = 29; row < 30; row++) { for( unsigned char col = 55; col < 76; col++ ) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row-26, col, 1); } } for(unsigned char col = 81; col < 82; col++) { for(unsigned char row = 9; row < 24; row++) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row, col-32, 1); } } col=54; for(unsigned char row = 4; row<9; row++) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row+20, col+26, 1); col--; } row=4; for(unsigned char col = 76; col < 81; col++) { LCD_set_pixel(row, col, 1); LCD_set_pixel(row+20, col-26, 1); row++; } }
/******************************************************************* * Function: void printCell(unsigned char, unsigned char, unsigned char, BOOL isrobot, unsigned char orent) * Input Variables: void * Output Return: unsigned char, unsigned char, unsigned char, BOOL, unsigned char * Overview: Prints the cell ********************************************************************/ void printCell(unsigned char cell, unsigned char r, unsigned char c, BOOL isrobot, unsigned char orent){ r = r*LCD_CELL_OFFSET; c = c*LCD_CELL_OFFSET; LCD_set_pixel(LCD_OFFSET - r, c, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c, 1); LCD_set_pixel(LCD_OFFSET - r, c+7, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c+7, 1); if(cell&0b1000){ LCD_set_pixel(LCD_OFFSET - r, c+1, 1); LCD_set_pixel(LCD_OFFSET - r, c+2, 1); LCD_set_pixel(LCD_OFFSET - r, c+3, 1); LCD_set_pixel(LCD_OFFSET - r, c+4, 1); LCD_set_pixel(LCD_OFFSET - r, c+5, 1); LCD_set_pixel(LCD_OFFSET - r, c+6, 1); } if(cell&0b0100){ LCD_set_pixel(LCD_OFFSET - (r+1), c+7, 1); LCD_set_pixel(LCD_OFFSET - (r+2), c+7, 1); LCD_set_pixel(LCD_OFFSET - (r+3), c+7, 1); LCD_set_pixel(LCD_OFFSET - (r+4), c+7, 1); LCD_set_pixel(LCD_OFFSET - (r+5), c+7, 1); LCD_set_pixel(LCD_OFFSET - (r+6), c+7, 1); } if(cell&0b0010){ LCD_set_pixel(LCD_OFFSET - (r+7), c+1, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c+2, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c+3, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c+4, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c+5, 1); LCD_set_pixel(LCD_OFFSET - (r+7), c+6, 1); } if(cell&0b0001){ LCD_set_pixel(LCD_OFFSET - (r+1), c, 1); LCD_set_pixel(LCD_OFFSET - (r+2), c, 1); LCD_set_pixel(LCD_OFFSET - (r+3), c, 1); LCD_set_pixel(LCD_OFFSET - (r+4), c, 1); LCD_set_pixel(LCD_OFFSET - (r+5), c, 1); LCD_set_pixel(LCD_OFFSET - (r+6), c, 1); } if(isrobot){ LCD_set_pixel(LCD_OFFSET - (r+3), c+3, isrobot); LCD_set_pixel(LCD_OFFSET - (r+4), c+3, isrobot); LCD_set_pixel(LCD_OFFSET - (r+3), c+4, isrobot); LCD_set_pixel(LCD_OFFSET - (r+4), c+4, isrobot); switch(orent){ case NORTH: LCD_set_pixel(LCD_OFFSET - (r+2), c+3, isrobot); break; case EAST: LCD_set_pixel(LCD_OFFSET - (r+3), c+5, isrobot); break; case SOUTH: LCD_set_pixel(LCD_OFFSET - (r+5), c+4, isrobot); break; case WEST: LCD_set_pixel(LCD_OFFSET - (r+4), c+2, isrobot); break; default: break; } } }
void draw_polygon(fixedPointEdgeTable* global_edge_table) { //initialise parity uint8_t parity = 0; //0 represents 'not inside polygon' uint8_t last_type = 2; //initialise the scan-line - set to lowest y value int8_t scan_line = roundfip(global_edge_table->edges[0].ymin); //initialise active edge table (size should be number of edges in the global edge table) /*fixedPointEdgeTable active_edge_table; fixedPointEdge* fpedges = calloc(global_edge_table->num_edges, sizeof(fixedPointEdge)); if (NULL == fpedges) { return false; //error, not enough space to make this } active_edge_table.edges = fpedges; //we have now successfully assigned enough memory to do this */ uint8_t active_edges = 0; //loop the global edge table and update the edges for this scan line uint8_t current_edge; fixedPointEdge start_edge; uintCoord current; while(1) { for (current_edge = 0; current_edge < global_edge_table->num_edges; current_edge++) { if (global_edge_table->edges[current_edge].status == ACTIVE) { //evaluate if this edge should be deactivated if (global_edge_table->edges[current_edge].ymax < (fip(scan_line) - fip(0.5))) { //we subtract 0.5 because we want the scan line to be beyond the end of the edge before disabling it //deactivate it global_edge_table->edges[current_edge].status = COMPLETE; active_edges--; } else { //increment the pixel's x value global_edge_table->edges[current_edge].x += global_edge_table->edges[current_edge].slope; //put a cap on x values - this fixes issues with very high gradients creating lines off the polygon if (((global_edge_table->edges[current_edge].slope > 0) && (roundfip(global_edge_table->edges[current_edge].x) > global_edge_table->edges[current_edge].xlim)) || ((global_edge_table->edges[current_edge].slope < 0) && (roundfip(global_edge_table->edges[current_edge].x) < global_edge_table->edges[current_edge].xlim))) { global_edge_table->edges[current_edge].x = fip(global_edge_table->edges[current_edge].xlim); } } } else if (global_edge_table->edges[current_edge].status == INACTIVE) { //evaluate if this edge should be activated if (global_edge_table->edges[current_edge].ymin < (fip(scan_line) + fip(0.5))) { //we add 0.5 because if the scan line were at 0, we would want to pick up ymins from -0.5 to 0.5 global_edge_table->edges[current_edge].status = ACTIVE; active_edges++; //we need to make sure this edge is in the right place int8_t past_edge; for (past_edge = (current_edge-1); past_edge >= 0; past_edge--) { //iterate back down through the older (active/complete) edges and find any active ones with greater x if (global_edge_table->edges[current_edge].status == ACTIVE) { if ((global_edge_table->edges[current_edge].x < global_edge_table->edges[past_edge].x) && (global_edge_table->edges[past_edge].ymax != global_edge_table->edges[current_edge].ymin)) { //the above if statement stops a new edge that is continuing upward from an older edge from swapping with it while they are both active //this is relevant as they are allowed to both be active simultaneously (as the +-0.5 has to account for inflection points) current.y = scan_line; current.x = past_edge; LCD_set_pixel(current); fixedPointEdge tmp_edge = global_edge_table->edges[current_edge]; //this assignment copies the data across (there are no pointers in a fixepoint edge) global_edge_table->edges[current_edge] = global_edge_table->edges[past_edge]; global_edge_table->edges[past_edge] = tmp_edge; } } } } } } if (active_edges == 0) break; parity = 1; last_type = 2; //2 is a special value meaning uninitialised current.y = 0; current.x = 0; LCD_set_pixel(current); current.y = scan_line; for (current_edge = 0; current_edge < global_edge_table->num_edges; current_edge++) { if (global_edge_table->edges[current_edge].status == ACTIVE) { if(last_type == 2) last_type = 1 - global_edge_table->edges[current_edge].type; //initialise last_type if (global_edge_table->edges[current_edge].type != last_type) { parity = 1 - parity; if (parity == 0) { start_edge = global_edge_table->edges[current_edge]; }/* else if (start_edge.ymax != global_edge_table->edges[current_edge].ymin) { //this accounts for the case when 2 connected edges which continue upward are active at the same time for (current.x = roundfip(start_edge.x); fip(current.x) <= (global_edge_table->edges[current_edge].x + fip(0.5)); current.x++) { LCD_set_pixel(current); } }*/ else { for (current.x = roundfip(start_edge.x); fip(current.x) <= (global_edge_table->edges[current_edge].x + fip(0.5)); current.x++) { LCD_set_pixel(current); } } } last_type = global_edge_table->edges[current_edge].type; } } scan_line++; } }
//this function initialises all the edges and orders them into the edge table sorted by increasing ymin and xmin bool initialise_global_edge_table(fixedPointPolygon* poly, fixedPointEdgeTable* edge_table) { //malloc fixedPointEdge* fpedges = calloc(poly->num_vertices, sizeof(fixedPointEdge)); //we must assign enough memory for every edge to be in the edge table, even though some may be discarded if (NULL == fpedges) { return false; //error, not enough space to make this } edge_table->edges = fpedges; //we have now successfully assigned enough memory to do this edge_table->num_edges = 0; //we will increment this as we add each edge to the edge table fixedPointCoord start_vertex; fixedPointCoord end_vertex; fixedPointLine last_line; uint8_t vertex; uint8_t curr_edge_type = 0; for (vertex = 0; vertex < poly->num_vertices; vertex++) { //for every vertex, make an edge using it and the previous vertex start_vertex = poly->vertices[vertex]; if (vertex == 0) { end_vertex = poly->vertices[poly->num_vertices - 1]; //pull out the last vertex } else { end_vertex = poly->vertices[vertex - 1]; } //make sure 'start' has the lowest y if (start_vertex.y > end_vertex.y) { fixedPointCoord tmp = start_vertex; start_vertex = end_vertex; end_vertex = tmp; } fixedPoint dy = end_vertex.y - start_vertex.y; if (roundfip(dy) == 0) { if (last_line.end.x != NULL) { //this section moves the end of the previous line onto the end of this horizontal line if (start_vertex.x == last_line.end.x) { //if the start vertex matches the top of the previous line last_line.end.x = end_vertex.x; last_line.end.y = end_vertex.y; } else if (start_vertex.x == last_line.start.x) { //if the start vertex happens to match the bottom of the previous line last_line.start.x = end_vertex.x; last_line.start.y = end_vertex.y; } else if (end_vertex.x == last_line.end.x) { //if the start vertex happens to match the top of the previous line last_line.end.x = start_vertex.x; last_line.end.y = start_vertex.y; } else if (end_vertex.x == last_line.start.x) { //if the start vertex happens to match the bottom of the previous line last_line.start.x = start_vertex.x; last_line.start.y = start_vertex.y; } } continue; //we dont need to draw horizontal lines (or close-to horizontal lines!), other edges will take care of this } fixedPoint dx = end_vertex.x - start_vertex.x; fixedPointEdge new_edge; new_edge.slope = fip(dx)/dy; //be careful of divides and multiplies new_edge.ymin = start_vertex.y; new_edge.x = start_vertex.x; //start vertex new_edge.ymax = end_vertex.y; new_edge.xlim = roundfip(end_vertex.x); new_edge.status = INACTIVE; if (((start_vertex.x == last_line.start.x) && (start_vertex.y == last_line.start.y)) || ((end_vertex.x == last_line.end.x) && (end_vertex.y == last_line.end.y))) { //changing direction curr_edge_type = 1 - curr_edge_type; //invert } last_line.start.x = start_vertex.x; last_line.start.y = start_vertex.y; last_line.end.x = end_vertex.x; last_line.end.y = end_vertex.y; new_edge.type = curr_edge_type; //now find out where the new edge goes in the edge table (order by ymin then xmin, then slope) uint8_t current_edge; uint8_t new_position = edge_table->num_edges; //default position is to put it on the end uintCoord current; current.y = roundfip(start_vertex.y); current.x = roundfip(start_vertex.x) + (vertex*10) + 3; LCD_set_pixel(current); current.y = roundfip(end_vertex.y); current.x = roundfip(end_vertex.x) + (vertex*10) + 3; LCD_set_pixel(current); for (current_edge = 0; current_edge < edge_table->num_edges; current_edge++) { if (edge_table->edges[current_edge].ymin > new_edge.ymin) { //if the current edge starts above the new edge new_position = current_edge; break; } else if (edge_table->edges[current_edge].ymin == new_edge.ymin) { if (edge_table->edges[current_edge].x > new_edge.x) { // if the current edge starts to the right of the new edge //add the edge where current_edge is new_position = current_edge; break; } else if (edge_table->edges[current_edge].x == new_edge.x) { //if these two edges start at the same point (and diverge) //sort by slope if (edge_table->edges[current_edge].slope > new_edge.slope) { //if the current edge slopes rightward of the new edge new_position = current_edge; break; } } } } //insert the new edge in the new_position in the edge matrix (involves bumping the others up) for (current_edge = edge_table->num_edges; current_edge > new_position; current_edge--) { edge_table->edges[current_edge] = edge_table->edges[current_edge-1]; } edge_table->edges[new_position] = new_edge; edge_table->num_edges++; } return true; }