CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Repetitive pattern on GLCD
Goto page Previous  1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 03, 2017 12:06 pm     Reply with quote

Bug.
Quote:
void glcd_refresh() {
int8 y, x;

.
.
.
for (x = 0; x < 128; x++) {
glcd_data(glcd_buffer[y * 128 + x]);

Change the y, x declaration to int16.

Basically, Hemnath found a driver for Hi-Tech C on the net and posted it.
Then you assumed it was compatible with CCS, but it's not. Hi-Tech C
uses 'int' to mean "signed 16-bit integer", but in CCS it means unsigned
8-bit integer. So your math result was getting truncated to 8 bits in
the array index calculation.
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Fri Feb 03, 2017 12:50 pm     Reply with quote

He might be better to change them to signed int16.
Though none of the code shown would need signed, if there is code to draw lines, and these can run either way across the screen, the sign would then become necessary to handle these parts.
jamalavedra



Joined: 25 Oct 2016
Posts: 62

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 10:42 am     Reply with quote

I did change the definition of the variable and now it doesn't repeat pattern. So thanks for that, but now I can only show things at the upper zone of the display. When trying to display things at the lower zone it gets displayed at the upper zone anyway somehow. Any ideas why?
newguy



Joined: 24 Jun 2004
Posts: 1902

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 10:53 am     Reply with quote

Some LCD modules will have two controller chips, with each chip responsible for half the display. Does the display have 2 enable lines?
jamalavedra



Joined: 25 Oct 2016
Posts: 62

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 11:14 am     Reply with quote

newguy wrote:
Some LCD modules will have two controller chips, with each chip responsible for half the display. Does the display have 2 enable lines?


No, I believe it has to be something to do witht the dirty pages of the display. Furthermore, i can write only at one upper quarter of the display, not exactly the half of it

thanks
jaume
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 11:20 am     Reply with quote

1. Post your complete current driver.
2. Also post your complete current test program that calls the driver.

Don't post code fragments or a few routines. Post your complete driver
and test program.

My guess is that you still have some place where 'int' is used, and it
should be int16.
jamalavedra



Joined: 25 Oct 2016
Posts: 62

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 12:27 pm     Reply with quote

attached is my full driver. I have checked and haven't found any "int" error. So I still have the following 2 problems:
1) I can only write things on the upper part of the display. When trying to write things in the lowers part the kinda"mirror" themselfs to the upper part.
2) i havent been able to write readable letters despite the library of the graphic part of the display looks fine to me.

main.c
Code:

#use delay(internal=8M)
//#include <string.h>
//#define OLED 0x78
#INCLUDE <stdlib.h>

#include "st7565.h"
#include "st7565-config.h"

#include "st7565.c"
#include "graphics.h"
#include "graphics.c"
#include "font_tahoma.h"
#include "font_verdana.h"

void main()
{

  // setup_adc_ports(NO_ANALOGS|VSS_VDD);         // No analogs
  // setup_adc(ADC_OFF|ADC_TAD_MUL_0);
   
  // setup_comparator(NC_NC_NC_NC);      // Disable comparator
   output_high(PIN_C2);
   glcd_init();
   delay_ms(200);
   glcd_blank();
   delay_ms(200);
   glcd_contrast(6, 25);

   output_low(PIN_C2);
      delay_ms(200);
   while(1)
   {     
    output_high(PIN_C2);  //this is an LED debugger
 //  draw_line(0,0,120,60,1);
    glcd_pixel(120, 60, 1);
    glcd_pixel(20, 10, 1);
  // draw_text("Hello World", 10, 10, Tahoma10, 1); //the font Tahoma won't //be attached, I dont think the is an error there.
   draw_circle(62, 10, 5, 1);
    output_low(PIN_C2);  //this is an LED debugger
    delay_ms(100);
     // Clear a pixel in the RAM buffer
    // glcd_pixel(64, 64, 0);
     glcd_refresh();     
   }
}



st7565.h
Code:

#ifndef _ST7565_H_
#define _ST7565_H_
#define GLCD_CMD_ADCREV       0b10100001  //ADC reverse
#define GLCD_CMD_A6        0b10100110  //display normal, not mirrored
#define GLCD_CMD_2F        0b101111 //possible error. Booster, regulator and follower on
#define GLCD_CMD_27        0b100111 //contrast set
#define GLCD_CMD_16        0b10110  //contrast set
#define GLCD_CMD_AC        0b10101100  //no indicator
#define GLCD_CMD_AF        0b10101111  //no indicator
#define GLCD_CMD_DISPLAY_ON       0b10101111
#define GLCD_CMD_DISPLAY_OFF       0b10101110
#define GLCD_CMD_ALL_NORMAL         0b10100100
#define GLCD_CMD_ALL_ON            0b10100101 
#define GLCD_CMD_DISPLAY_NORMAL      0b10100110
#define GLCD_CMD_DISPLAY_REVERSE   0b10100111
#define GLCD_CMD_BIAS_9            0b10100010
#define GLCD_CMD_BIAS_7            0b10100011

#define GLCD_CMD_HORIZONTAL_NORMAL   0b10100000
#define GLCD_CMD_HORIZONTAL_REVERSE   0b10100001
#define GLCD_CMD_VERTICAL_NORMAL   0b11000000
#define GLCD_CMD_VERTICAL_REVERSE   0b11001000
#define GLCD_CMD_POWER_CONTROL      0b00101000
#define GLCD_CMD_RESISTOR         0b00100000
#define GLCD_CMD_VOLUME_MODE      0b10000001
#define GLCD_CMD_DISPLAY_START      0b01000000
#define GLCD_CMD_COLUMN_LOWER      0b00000000
#define GLCD_CMD_COLUMN_UPPER      0b00010000
#define GLCD_CMD_SET_PAGE         0b10110000
#define GLCD_CMD_RESET            0b11100010
#define   GLCD_CMD_NOP            0b11100011
#define    GLCD_CMD_RATIO          0b11111000

void glcd_init();
void glcd_command(char);
void glcd_data(char); 
void glcd_refresh();
void glcd_blank();
void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour);
void glcd_flip_screen(unsigned char flip);
void glcd_inverse_screen(unsigned char inverse);
void glcd_test_card();
void glcd_contrast(char resistor_ratio, char contrast);
unsigned char glcd_flipped = 0;

#endif // _ST7565_H_


st7565-config.h
Code:

#define GLCD_CS1 PIN_C5
#define GLCD_RESET PIN_C3
#define GLCD_A0 PIN_A0
#define GLCD_SCL PIN_A2
#define GLCD_SDA PIN_A5
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define ST7565_REVERSE


st7565.c
Code:

unsigned char glcd_buffer[SCREEN_WIDTH * SCREEN_HEIGHT / 8];

#ifdef ST7565_DIRTY_PAGES
unsigned char glcd_dirty_pages;
#endif

void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour) {
    if (x > SCREEN_WIDTH || y > SCREEN_HEIGHT) return;

    // Real screen coordinates are 0-63, not 1-64.
    x -= 1;
    y -= 1;

    unsigned int16 array_pos = x + ((y / 8) * 128);

#ifdef ST7565_DIRTY_PAGES
#warning ** ST7565_DIRTY_PAGES enabled, only changed pages will be written to the GLCD **
    glcd_dirty_pages |= 1 << (array_pos / 128);
#endif
    if (colour) {
        glcd_buffer[array_pos] |= 1 << (y % 8);
    } else {
        glcd_buffer[array_pos] &= 0xFF ^ 1 << (y % 8);
    }
}
void glcd_blank()
{
   int16 n;
   int8 x,y;
    // Reset the internal buffer
    for (n = 1; n <= (SCREEN_WIDTH * SCREEN_HEIGHT / 8) - 1; ++n) {
        glcd_buffer[n] = 0;
    }

    // Clear the actual screen
    for (y = 0; y < 8; y++) {
        glcd_command(GLCD_CMD_SET_PAGE | y);
        // Reset column to 0 (the left side)
        glcd_command(GLCD_CMD_COLUMN_LOWER);
        glcd_command(GLCD_CMD_COLUMN_UPPER);
        // We iterate to 132 as the internal buffer is 65*132, not
        // 64*124.
        for (x = 0; x < 132; x++) {
            glcd_data(0x00);
        }
    }   
}
void glcd_refresh() {
  unsigned int16 y, x;
    for (y = 0; y < 8; y++) {
#ifdef ST7565_DIRTY_PAGES
        // Only copy this page if it is marked as "dirty"
        if (!(glcd_dirty_pages & (1 << y))) continue;
#endif
        glcd_command(GLCD_CMD_SET_PAGE | y);
      // Reset column to the left side.  The internal memory of the
        // screen is 132*64, we need to account for this if the display
        // is flipped.
        // Some screens seem to map the internal memory to the screen
        // pixels differently, the ST7565_REVERSE define allows this to
        // be controlled if necessary.
#ifdef ST7565_REVERSE
        if (!glcd_flipped) {
#else
        if (glcd_flipped) {
#endif
            glcd_command(GLCD_CMD_COLUMN_LOWER | 4);
        } else {
            glcd_command(GLCD_CMD_COLUMN_LOWER);
        }
        glcd_command(GLCD_CMD_COLUMN_UPPER);

        for (x = 0; x < 128; x++) {
            glcd_data(glcd_buffer[y * 128 + x]);
        }
    }
#ifdef ST7565_DIRTY_PAGES
    // All pages have now been updated, reset the indicator.
    glcd_dirty_pages = 0;
#endif
}

void glcd_init()
{
// Select the chip
    output_low(GLCD_CS1);

    output_low(GLCD_RESET);

    // Datasheet says "wait for power to stabilise" but gives
    // no specific time!
    Delay_Ms(50);
    output_high(GLCD_RESET);
    output_low(GLCD_CS1);
    output_low(GLCD_A0);
    // Datasheet says max 1ms here
    //DelayMs(1);
    // Set LCD bias to 1/9th
    glcd_command(GLCD_CMD_BIAS_9);
    // Horizontal output direction (ADC segment driver selection)
    glcd_command(GLCD_CMD_HORIZONTAL_REVERSE);

    // Vertical output direction (common output mode selection)
    glcd_command(GLCD_CMD_VERTICAL_NORMAL);
    // The screen is the "normal" way up
    glcd_flipped = 1;
    // Set internal resistor.  A suitable middle value is used as
    // the default.
    glcd_command(GLCD_CMD_RESISTOR | 0x3);
    // Power control setting (datasheet step 7)
    // Note: Skipping straight to 0x7 works with my hardware.
      // glcd_command(GLCD_CMD_POWER_CONTROL | 0x4);
     //  Delay_Ms(50);
    //   glcd_command(GLCD_CMD_POWER_CONTROL | 0x6);
    //   Delay_Ms(50);
    glcd_command(GLCD_CMD_POWER_CONTROL | 0x7);
    //   Delay_Ms(10);
    // Volume set (brightness control).  A middle value is used here
    // also.
    glcd_command(GLCD_CMD_VOLUME_MODE);
    glcd_command(31);
    // Reset start position to the top
    glcd_command(GLCD_CMD_DISPLAY_START);
    // Turn the display on
    glcd_command(GLCD_CMD_DISPLAY_ON);
    // Unselect the chip
    output_high(GLCD_CS1);
}
void glcd_data(unsigned char data) {
   int16 n;
    // A0 is high for display data
    output_high(GLCD_A0);
    // Select the chip
    output_low(GLCD_CS1);
    for (n = 0; n < 8; n++) {
        if (data & 0x80) {
            output_high(GLCD_SDA);
        } else {
            output_low(GLCD_SDA);
        }
        // Pulse SCL
        output_high(GLCD_SCL);
       output_low(GLCD_SCL);
        data <<= 1;
    }
    // Unselect the chip
    output_high(GLCD_CS1);
}
void glcd_command(char command) {
   int16 n;
    // A0 is low for command data
    output_low(GLCD_A0);
    // Select the chip
    output_low(GLCD_CS1);
    for (n = 0; n < 8; n++) {
        if (command & 0x80) {
            output_high(GLCD_SDA);
        } else {
            output_low(GLCD_SDA);
        }
        // Pulse SCL
        output_high(GLCD_SCL);
        output_low(GLCD_SCL);
        command <<= 1;
    }
    // Unselect the chip
    output_high(GLCD_CS1);
}
void glcd_flip_screen(unsigned char flip) {
    if (flip) {
        glcd_command(GLCD_CMD_HORIZONTAL_NORMAL);
        glcd_command(GLCD_CMD_VERTICAL_REVERSE);
        glcd_flipped = 0;
    } else {
        glcd_command(GLCD_CMD_HORIZONTAL_REVERSE);
        glcd_command(GLCD_CMD_VERTICAL_NORMAL);
        glcd_flipped = 1;
    }
}
void glcd_inverse_screen(unsigned char inverse) {
    if (inverse) {
        glcd_command(GLCD_CMD_DISPLAY_REVERSE);
    } else {
        glcd_command(GLCD_CMD_DISPLAY_NORMAL);
    }
}
void glcd_test_card() {   
   int16 n;
    unsigned char p = 0xF0;
    for (n = 1; n <= (SCREEN_WIDTH * SCREEN_HEIGHT / 8); ++n) {
        glcd_buffer[n - 1] = p;
        if (n % 4 == 0) {
            unsigned char q = p;
            p = p << 4;
            p |= q >> 4;
        }
    }
    glcd_refresh();
}
void glcd_contrast(char resistor_ratio, char contrast) {
    if (resistor_ratio > 7 || contrast > 63) return;

    glcd_command(GLCD_CMD_RESISTOR | resistor_ratio);
    glcd_command(GLCD_CMD_VOLUME_MODE);
    glcd_command(contrast);
}


graphics.h
Code:

#ifndef _GRAPHICS_H_
#define _GRAPHICS_H_
#define FONT_HEADER_TYPE      0
#define FONT_HEADER_ORIENTATION   1
#define FONT_HEADER_START      2
#define FONT_HEADER_LETTERS      3
#define FONT_HEADER_HEIGHT      4
#define FONT_TYPE_FIXED         0
#define FONT_TYPE_PROPORTIONAL   1
#define FONT_ORIENTATION_VERTICAL_CEILING   2
typedef struct {
   unsigned char x1;
   unsigned char y1;
   unsigned char x2;
   unsigned char y2;
} bounding_box_t;
bounding_box_t draw_text(char *string, unsigned char x, unsigned char y, unsigned char *font, unsigned char spacing);
bounding_box_t draw_char(unsigned char c, unsigned char x, unsigned char y, unsigned char *font);
void draw_rectangle(int16 x1, int16 y1, int16 x2, int16 y2, char colour);
void draw_box(int16 x1, int16 y1, int16 x2, int16 y2, char colour);
unsigned char text_width(unsigned char *string, unsigned char *font, unsigned char spacing);
unsigned char text_height(unsigned char *string, unsigned char *font);
m colour    0 = OFF, any other value = ON
void draw_line(int16 x1, int16 y1, int16 x2, int16 y2, char colour);
void draw_circle(unsigned char centre_x, unsigned char centre_y, unsigned char radius, unsigned char colour);
void draw_filled_circle(unsigned char centre_x, unsigned char centre_y, unsigned char radius, unsigned char colour);
extern void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour);
#endif // _GRAPHICS_H_


graphics.c
Code:

//stdlib.h for abs()
#include <stdlib.h>

#include "graphics.h"
//#include "main.h"
unsigned char j;
bounding_box_t draw_text(char *string, unsigned char x, unsigned char y, unsigned char *font, unsigned char spacing) {
   bounding_box_t ret;
   bounding_box_t tmp;

   ret.x1 = x;
   ret.y1 = y;

   spacing += 1;

   // BUG: As we move right between chars we don't actually wipe the space
   while (*string != 0) {
      tmp = draw_char(*string++, x, y, font);

      // Leave a single space between characters
      x = tmp.x2 + spacing;
   }

   ret.x2 = tmp.x2;
   ret.y2 = tmp.y2;

   return ret;
}

bounding_box_t draw_char(unsigned char c, unsigned char x, unsigned char y, unsigned char *font) {
   unsigned int16 pos;
   unsigned char width;
   bounding_box_t ret;

   ret.x1 = x;
   ret.y1 = y;
   ret.x2 = x;
   ret.y2 = y;

   // Read first byte, should be 0x01 for proportional
   if (font[FONT_HEADER_TYPE] != FONT_TYPE_PROPORTIONAL) return ret;

   // Check second byte, should be 0x02 for "vertical ceiling"
   if (font[FONT_HEADER_ORIENTATION] != FONT_ORIENTATION_VERTICAL_CEILING) return ret;

   // Check that font start + number of bitmaps contains c
   if (!(c >= font[FONT_HEADER_START] && c <= font[FONT_HEADER_START] + font[FONT_HEADER_LETTERS])) return ret;

   // Adjust for start position of font vs. the char passed
   c -= font[FONT_HEADER_START];

   // Work out where in the array the character is
   pos = font[c * FONT_HEADER_START + 5];
   pos <<= 8;
   pos |= font[c * FONT_HEADER_START + 6];

   // Read first byte from this position, this gives letter width
   width = font[pos];

   // Draw left to right
   unsigned char i;
   for (i = 0; i < width; i++) {

      // Draw top to bottom
      for (j = 0; j < font[FONT_HEADER_HEIGHT]; j++) {
         // Increment one data byte every 8 bits, or
         // at the start of a new column  HiTech optimizes
         // the modulo, so no need to try and avoid it.
         if (j % 8 == 0) pos++;

         if (font[pos] & 1 << (j % 8)) {
            glcd_pixel(x + i, y + j, 1);
         } else {
            glcd_pixel(x + i, y + j, 0);
         }
      }
   }

   ret.x2 = ret.x1 + width - 1;
   // TODO: Return the actual height drawn, rather than the height of the
   //       font.
  // ret.y2 = ret.y1 + height;
   ret.y2 = ret.y1 + font[FONT_HEADER_HEIGHT];

   return ret;
}

unsigned char text_height(unsigned char *string, unsigned char *font) {
   // TODO: Possibly work out the actual pixel height.  Letters with
   //       descenders (like 'g') are taller than letters without (like 'k')

   // Height is stored in the header
   return font[FONT_HEADER_HEIGHT];
}

unsigned char text_width(unsigned char *string, unsigned char *font, unsigned char spacing) {
   unsigned char width = 0;
   unsigned int16 pos;
   unsigned char c;

   // TODO: Implement for fixed width fonts

   // Check font type, should be 0x01 for proportional
   if (font[FONT_HEADER_TYPE] != FONT_TYPE_PROPORTIONAL) return 0;

   while (*string != 0) {
      c = *string++;
   
      // Check that font start + number of bitmaps contains c
      // TODO: Should we continue here but add 0 to width?
      if (!(c >= font[FONT_HEADER_START] && c <= font[FONT_HEADER_START] + font[FONT_HEADER_LETTERS])) return 0;
   
      // Adjust for start position of font vs. the char passed
      c -= font[FONT_HEADER_START];
   
      // Work out where in the array the character is
      pos = font[c * FONT_HEADER_START + 5];
      pos <<= 8;
      pos |= font[c * FONT_HEADER_START + 6];
   
      // Read first byte from this position, this gives letter width
      width += font[pos];

      // Allow for space between letters
      width += spacing;
   }

   // The last letter wont have a space after it
   return width - spacing;
}

void draw_rectangle(int16 x1, int16 y1, int16 x2, int16 y2, char colour)
{
   // Top
   draw_line(x1, y1, x2, y1, colour);
   // Left
   draw_line(x1, y1, x1, y2, colour);
   // Bottom
   draw_line(x1, y2, x2, y2, colour);
   // Right
   draw_line(x2, y1, x2, y2, colour);
}


// A rounded box
void draw_box(int16 x1, int16 y1, int16 x2, int16 y2, char colour)
{
   // Top
   draw_line(x1 + 1, y1, x2 - 1, y1, colour);
   // Left
   draw_line(x1, y1 + 1, x1, y2 - 1, colour);
   // Bottom
   draw_line(x1 + 1, y2, x2 - 1, y2, colour);
   // Right
   draw_line(x2, y1 + 1, x2, y2 - 1, colour);
}

// Implementation of Bresenham's line algorithm
//
// This code credit Tom Ootjers, originally obtained from:
// http://tinyurl.com/czok7vx
void draw_line(int16 x1, int16 y1, int16 x2, int16 y2, char colour)
{
   int16 xinc1, yinc1, den, num, numadd, numpixels, curpixel, xinc2, yinc2;

   int16 deltax = abs(x2 - x1);       // The difference between the x's
   int16 deltay = abs(y2 - y1);       // The difference between the y's
   int16 x = x1;                      // Start x off at the first pixel
   int16 y = y1;                      // Start y off at the first pixel   
   if (x2 >= x1) {                // The x-values are increasing
     xinc1 = 1;
     xinc2 = 1;
    } else {                         // The x-values are decreasing
     xinc1 = -1;
     xinc2 = -1;
   }   
   if (y2 >= y1)                   // The y-values are increasing
   {
     yinc1 = 1;
     yinc2 = 1;
   }
   else                            // The y-values are decreasing
   {
     yinc1 = -1;
     yinc2 = -1;
   }
   if (deltax >= deltay)           // There is at least one x-value for every y-value
   {
     xinc1 = 0;                    // Don't change the x when numerator >= denominator
     yinc2 = 0;                    // Don't change the y for every iteration
     den = deltax;
     num = deltax / 2;
     numadd = deltay;
     numpixels = deltax;           // There are more x-values than y-values
   }
   else                            // There is at least one y-value for every x-value
   {
     xinc2 = 0;                    // Don't change the x for every iteration
     yinc1 = 0;                    // Don't change the y when numerator >= denominator
     den = deltay;
     num = deltay / 2;
     numadd = deltax;
     numpixels = deltay;           // There are more y-values than x-values
   }
   for (curpixel = 0; curpixel <= numpixels; curpixel++)
   {
     glcd_pixel(x, y, colour);       // Draw the current pixel
     num += numadd;                // Increase the numerator by the top of the fraction
     if (num >= den)               // Check if numerator >= denominator
     {
      num -= den;                 // Calculate the new numerator value
      x += xinc1;                 // Change the x as appropriate
      y += yinc1;                 // Change the y as appropriate
     }
     x += xinc2;                   // Change the x as appropriate
     y += yinc2;                   // Change the y as appropriate
   }
}
// Implementation of Bresenham's circle algorithm
void draw_circle(unsigned char centre_x, unsigned char centre_y, unsigned char radius, unsigned char colour)
{
   signed char x = 0;
   signed char y = radius;
   signed char p = 1 - radius;
   if (!radius) return;
   for (x = 0; x < y; x++) {
      if (p < 0) {
         p += x * 2 + 3;
      } else {
         p += x * 2 - y * 2 + 5;
         y--;
      }
      glcd_pixel(centre_x - x, centre_y - y, colour);
      glcd_pixel(centre_x - y, centre_y - x, colour);
      glcd_pixel(centre_x + y, centre_y - x, colour);
      glcd_pixel(centre_x + x, centre_y - y, colour);
      glcd_pixel(centre_x - x, centre_y + y, colour);
      glcd_pixel(centre_x - y, centre_y + x, colour);
      glcd_pixel(centre_x + y, centre_y + x, colour);
      glcd_pixel(centre_x + x, centre_y + y, colour);
   }
}
// Implementation of Bresenham's circle algorithm, filled.
void draw_filled_circle(unsigned char centre_x, unsigned char centre_y, unsigned char radius, unsigned char colour)
{
   signed char x = 0;
   signed char y = radius;
   signed char p = 1 - radius;
   if (!radius) return;
   for (x = 0; x < y; x++) {
      if (p < 0) {
         p += x * 2 + 3;
      } else {
         p += x * 2 - y * 2 + 5;
         y--;
      }
      draw_line(centre_x - x, centre_y - y, centre_x + x, centre_y - y, colour);
      draw_line(centre_x - y, centre_y - x, centre_x + y, centre_y - x, colour);
      draw_line(centre_x + x, centre_y + y, centre_x - x, centre_y + y, colour);
      draw_line(centre_x + y, centre_y + x, centre_x - y, centre_y + x, colour);
   }
}


stdlib.h
Code:


#ifndef _STDLIB
#define _STDLIB

//---------------------------------------------------------------------------
// Definitions and types
//---------------------------------------------------------------------------

#ifndef RAND_MAX
#define RAND_MAX  32767    // The value of which is the maximum value
                           // ... returned by the rand function
#endif


#IF (sizeof(int16*)>1)
#DEFINE LONG_POINTERS 1
#ELSE
#DEFINE LONG_POINTERS 0
#ENDIF

typedef struct {
   signed int quot;
   signed int rem;
} div_t;

typedef struct {
   signed long quot;
   signed long rem;
} ldiv_t;

#include <stddef.h>

//---------------------------------------------------------------------------
// String conversion functions
//---------------------------------------------------------------------------

/* Standard template: signed int  atoi(char * s)
 * converts the initial portion of the string s to a signed int
 * returns the converted value if any, 0 otherwise
 */
signed int atoi(char *s);

/* Syntax: signed int32  atoi32(char * s)
   converts the initial portion of the string s to a signed int32
   returns the converted value if any, 0 otherwise*/
#if (sizeof(long)==4)
 #define atoi32(s) atol(s)
#else
 signed int32 atoi32(char *s);
#endif

#if defined(__PCD__)
// The following functions only work on the 24 bit compiler
// for the 30F, 33F, 24F and 24H parts
/* Syntax: signed int48  atoi48(char * s)
   converts the initial portion of the string s to a signed int48
   returns the converted value if any, 0 otherwise*/
   
signed int48 atoi48(char *s);

/* Syntax: signed int64  atoi64(char * s)
   converts the initial portion of the string s to a signed int64
   returns the converted value if any, 0 otherwise*/
signed int64 atoi64(char *s);
#endif

/* Syntax: char *  itoa(signed int32 num, int8 base, char * s)
   converts the signed int32 to a string and
   returns the converted value if any, 0 otherwise*/
char * itoa(signed int32 num, unsigned int base, char * s);

/* Standard template: signed int16  atol(char * s)
 * converts the initial portion of the string s to a signed int16
 * returns the converted value if any, 0 otherwise
 */
signed long atol(char *s);

/* Standard template: int16 strtoul(char * s,char *endptr,signed int base)
 * converts the initial portion of the string s, represented as an
 * integral value of radix base  to a signed long.
 * Returns the converted value if any, 0 otherwise
 * the final string is returned in the endptr, if endptr is not null
 */
signed long strtol(char *s,char *endptr, signed int base);

/* Standard template: int16 strtoul(char * s,char *endptr,signed int base)
 * converts the initial portion of the string s, represented as an
 * integral value of radix base to a unsigned long.
 * returns the converted value if any, 0 otherwise
 * the final string is returned in the endptr, if endptr is not null
 */
unsigned long strtoul(char *s,char *endptr, signed int base);

/* Standart template: float strtof(char * s,char *endptr)
                      float48 strtof48(char *s,char *endptr);
                      float64 strtod(char *s,char *endptr);
 * converts the initial portion of the string s to a float32, float48 or float64,
 * returns the converted value if any, 0 otherwise
 * the final string is returned in the endptr, if endptr is not null                   
*/
float strtof(char *s,char *endptr);
#if defined(__PCD__)
float48 strtof48(char *s,char *endptr);
float64 strtod(char *s,char *endptr);
#else
//provided for compatibility
#define strtof48(s, e) strtof(s, e)
#define strtod(s, e) strtof(s, e)
#endif

/* Standard template: float32 atof(char * s)
 * converts the initial portion of the string s to a float.
 * returns the converted value if any, 0 otherwise
 */
#define atof(s)   strtof(s, 0)

#if defined(__PCD__)
// The following functions only work on the 24 bit compiler
// for the 30F, 33F, 24F and 24H parts

/* Standard template: float48 atof48(char * s)
 * converts the initial portion of the string s to a float.
 * returns the converted value if any, 0 otherwise
 */
#define atof48(s) strtof48(s, 0)

/* Standard template: float64 atof64(char * s)
 * converts the initial portion of the string s to a float.
 * returns the converted value if any, 0 otherwise
 */
#define atof64(s) strtod(s, 0)
#endif

/* Standard template: float32 atoe(char * s)
 * converts the initial portion of the string s to a float.
 * returns the converted value if any, 0 otherwise
 * also handles E format numbers
 */
#if !defined(__PCD__)
float atoe(char * s);
#endif

#if defined(__PCD__)
float32 atoe(char * s);
#endif

//---------------------------------------------------------------------------
// Pseudo-random sequence generation functions
//---------------------------------------------------------------------------

/* The rand function computes a sequence of pseudo-random integers in
 * the range 0 to RAND_MAX
 *
 * Parameters:
 *       (none)
 *
 * Returns:
 *       The pseudo-random integer
 */
unsigned int16 rand(void);

/* The srand function uses the argument as a seed for a new sequence of
 * pseudo-random numbers to be returned by subsequent calls to rand.
 *
 * Parameters:
 *       [in] seed: The seed value to start from. You might need to pass
 *
 * Returns:
 *       (none)
 *
 * Remarks
 *          The srand function sets the starting point for generating
 *       a series of pseudorandom integers. To reinitialize the
 *       generator, use 1 as the seed argument. Any other value for
 *       seed sets the generator to a random starting point. rand
 *       retrieves the pseudorandom numbers that are generated.
 *       Calling rand before any call to srand generates the same
 *       sequence as calling srand with seed passed as 1.
 *          Usually, you need to pass a time here from outer source
 *       so that the numbers will be different every time you run.
 */
void srand(unsigned int32 seed);

//---------------------------------------------------------------------------
// Memory management functions
//---------------------------------------------------------------------------

// Comming soon

//---------------------------------------------------------------------------
// Communication with the environment
//---------------------------------------------------------------------------

/* The function returns 0 always
 */
signed int8 system(char *string);

//---------------------------------------------------------------------------
// Searching and sorting utilities
//---------------------------------------------------------------------------

/* Performs a binary search of a sorted array..
 *
 * Parameters:
 *       [in] key: Object to search for
 *       [in] base: Pointer to base of search data
 *       [in] num: Number of elements
 *       [in] width: Width of elements
 *       [in] compare: Function that compares two elements
 *
 * Returns:
 *       bsearch returns a pointer to an occurrence of key in the array pointed
 *       to by base. If key is not found, the function returns NULL. If the
 *       array is not in order or contains duplicate records with identical keys,
 *       the result is unpredictable.
 */
//void *bsearch(const void *key, const void *base, size_t num, size_t width,
//              int (*compare)(const void *, const void *));

/* Performs the shell-metzner sort (not the quick sort algorithm). The contents
 * of the array are sorted into ascending order according to a comparison
 * function pointed to by compar.
 *
 * Parameters:
 *       [in] base: Pointer to base of search data
 *       [in] num: Number of elements
 *       [in] width: Width of elements
 *       [in] compare: Function that compares two elements
 *
 * Returns:
 *       (none)
 */
//void *qsort(const void *base, size_t num, size_t width,
//              int (*compare)(const void *, const void *));

//---------------------------------------------------------------------------
// Integer arithmetic functions
//---------------------------------------------------------------------------

#define labs abs

div_t div(signed int numer, signed int denom);
ldiv_t ldiv(signed long numer, signed long denom);

//---------------------------------------------------------------------------
// Multibyte character functions
//---------------------------------------------------------------------------

// Not supported

//---------------------------------------------------------------------------
// Multibyte string functions
//---------------------------------------------------------------------------

// Not supported


//---------------------------------------------------------------------------
// Internal implementation
//---------------------------------------------------------------------------

#include <stddef.h>
#include <string.h>

div_t div(signed int numer, signed int denom)
{
   div_t val;
   val.quot = numer / denom;
   val.rem = numer - (denom * val.quot);
   return (val);
}

ldiv_t ldiv(signed long numer, signed long denom)
{
   ldiv_t val;

   val.quot = numer / denom;
   val.rem = numer - (denom * val.quot);
   return (val);
}

#if defined(__PCD__)
float32 atoe(char * s)
{
   float32 pow10 = 1.0;
   float32 result = 0.0;
   unsigned int8 sign = 0;
   unsigned int8 expsign = 0;
   char c;
   unsigned int8 ptr = 0;
   unsigned int8 i;
   float32 exp = 1.0;
   unsigned int8 expcnt = 0;

   c = s[ptr++];

   if ((c>='0' && c<='9') || c=='+' || c=='-' || c=='.' || c=='E' || c=='e') {
      if(c == '-') {
         sign = 1;
         c = s[ptr++];
      }
      if(c == '+')
         c = s[ptr++];

      while((c >= '0' && c <= '9')) {
         result = 10*result + c - '0';
         c = s[ptr++];
      }

      if (c == '.') {
         c = s[ptr++];
         while((c >= '0' && c <= '9')) {
             pow10 = pow10*10;
             result += (c - '0')/pow10;
             c = s[ptr++];
         }
      }

      // Handling the exponent
      if (c=='e' || c=='E') {
         c = s[ptr++];

         if(c == '-') {
            expsign = 1;
            c = s[ptr++];
         }
         if(c == '+')
            c = s[ptr++];

         while((c >= '0' && c <= '9')) {
            expcnt = 10*expcnt + c - '0';
            c = s[ptr++];
         }

         for(i=0;i<expcnt;i++)
            exp*=10;

         if(expsign==1)
            result/=exp;
         else
            result*=exp;
      }
   }

   if (sign == 1)
      result = -1*result;
   return(result);
}
#endif

#if !defined(__PCD__)
float atoe(char * s)
{
   float pow10 = 1.0;
   float result = 0.0;
   unsigned int8 sign = 0;
   unsigned int8 expsign = 0;
   char c;
   unsigned int8 ptr = 0;
   unsigned int8 i;
   float exp = 1.0;
   unsigned int8 expcnt = 0;

   c = s[ptr++];

   if ((c>='0' && c<='9') || c=='+' || c=='-' || c=='.' || c=='E' || c=='e') {
      if(c == '-') {
         sign = 1;
         c = s[ptr++];
      }
      if(c == '+')
         c = s[ptr++];

      while((c >= '0' && c <= '9')) {
         result = 10*result + c - '0';
         c = s[ptr++];
      }

      if (c == '.') {
         c = s[ptr++];
         while((c >= '0' && c <= '9')) {
             pow10 = pow10*10;
             result += (c - '0')/pow10;
             c = s[ptr++];
         }
      }

      // Handling the exponent
      if (c=='e' || c=='E') {
         c = s[ptr++];

         if(c == '-') {
            expsign = 1;
            c = s[ptr++];
         }
         if(c == '+')
            c = s[ptr++];

         while((c >= '0' && c <= '9')) {
            expcnt = 10*expcnt + c - '0';
            c = s[ptr++];
         }

         for(i=0;i<expcnt;i++)
            exp*=10;

         if(expsign==1)
            result/=exp;
         else
            result*=exp;
      }
   }

   if (sign == 1)
      result = -1*result;
   return(result);
}
#endif

signed int atoi(char *s)
{
   signed int result;
   unsigned int sign, base, index;
   char c;

   index = 0;
   sign = 0;
   base = 10;
   result = 0;

   if (!s)
      return 0;
   // Omit all preceeding alpha characters
   c = s[index++];

   // increase index if either positive or negative sign is detected
   if (c == '-')
   {
      sign = 1;         // Set the sign to negative
      c = s[index++];
   }
   else if (c == '+')
   {
      c = s[index++];
   }

   if (c >= '0' && c <= '9')
   {

      // Check for hexa number
      if (c == '0' && (s[index] == 'x' || s[index] == 'X'))
      {
         base = 16;
         index++;
         c = s[index++];
      }

      // The number is a decimal number
      if (base == 10)
      {
         while (c >= '0' && c <= '9')
         {
            result = 10*result + (c - '0');
            c = s[index++];
         }
      }
      else if (base == 16)    // The number is a hexa number
      {
         c = toupper(c);
         while ( (c >= '0' && c <= '9') || (c >= 'A' && c<='F'))
         {
            if (c >= '0' && c <= '9')
               result = (result << 4) + (c - '0');
            else
               result = (result << 4) + (c - 'A' + 10);

            c = s[index++];
            c = toupper(c);
         }
      }
   }

   if (sign == 1 && base == 10)
       result = -result;

   return(result);
}

signed long atol(char *s)
{
   signed long result;
   unsigned int sign, base, index;
   char c;

   index = 0;
   sign = 0;
   base = 10;
   result = 0;

   if (!s)
      return 0;
   c = s[index++];

   // increase index if either positive or negative sign is detected
   if (c == '-')
   {
      sign = 1;         // Set the sign to negative
      c = s[index++];
   }
   else if (c == '+')
   {
      c = s[index++];
   }

   if (c >= '0' && c <= '9')
   {
      if (c == '0' && (s[index] == 'x' || s[index] == 'X'))
      {
         base = 16;
         index++;
         c = s[index++];
      }

      // The number is a decimal number
      if (base == 10)
      {
         while (c >= '0' && c <= '9')
         {
            result = 10*result + (c - '0');
            c = s[index++];
         }
      }
      else if (base == 16)    // The number is a hexa number
      {
         c = toupper(c);
         while ( (c >= '0' && c <= '9') || (c >= 'A' && c <='F'))
         {
            if (c >= '0' && c <= '9')
               result = (result << 4) + (c - '0');
            else
               result = (result << 4) + (c - 'A' + 10);

            c = s[index++];c = toupper(c);
         }
      }
   }

   if (base == 10 && sign == 1)
      result = -result;

   return(result);
}

/* A fast routine to multiply by 10
 */
signed int32 mult_with10(int32 num)
{
   return ( (num << 1) + (num << 3) );
}

#if sizeof(long)==2
signed int32 atoi32(char *s)
{
   signed int32 result;
   int8 sign, base, index;
   char c;

   index = 0;
   sign = 0;
   base = 10;
   result = 0;

   if (!s)
      return 0;
   c = s[index++];

   // increase index if either positive or negative sign is detected
   if (c == '-')
   {
      sign = 1;         // Set the sign to negative
      c = s[index++];
   }
   else if (c == '+')
   {
      c = s[index++];
   }

   if (c >= '0' && c <= '9')
   {
      if (c == '0' && (s[index] == 'x' || s[index] == 'X'))
      {
         base = 16;
         index++;
         c = s[index++];
      }

      // The number is a decimal number
      if (base == 10)
      {
         while (c >= '0' && c <= '9') {
            result = (result << 1) + (result << 3);  // result *= 10;
            result += (c - '0');
            c = s[index++];
         }
      }
      else if (base == 16)    // The number is a hexa number
      {
         c = toupper(c);
         while ((c >= '0' && c <= '9') || (c >= 'A' && c <='F'))
         {
            if (c >= '0' && c <= '9')
               result = (result << 4) + (c - '0');
            else
               result = (result << 4) + (c - 'A' + 10);

            c = s[index++];c = toupper(c);
         }
      }
   }

   if (base == 10 && sign == 1)
      result = -result;

   return(result);
}
#endif

#if defined(__PCD__)

signed int48 atoi48(char *s)
{
   signed int48 result;
   int8 sign, base, index;
   char c;

   index = 0;
   sign = 0;
   base = 10;
   result = 0;

   if (!s)
      return 0;
   c = s[index++];

   // increase index if either positive or negative sign is detected
   if (c == '-')
   {
      sign = 1;         // Set the sign to negative
      c = s[index++];
   }
   else if (c == '+')
   {
      c = s[index++];
   }

   if (c >= '0' && c <= '9')
   {
      if (c == '0' && (s[index] == 'x' || s[index] == 'X'))
      {
         base = 16;
         index++;
         c = s[index++];
      }

      // The number is a decimal number
      if (base == 10)
      {
         while (c >= '0' && c <= '9') {
            result = (result << 1) + (result << 3);  // result *= 10;
            result += (c - '0');
            c = s[index++];
         }
      }
      else if (base == 16)    // The number is a hexa number
      {
         c = toupper(c);
         while ((c >= '0' && c <= '9') || (c >= 'A' && c <='F'))
         {
            if (c >= '0' && c <= '9')
               result = (result << 4) + (c - '0');
            else
               result = (result << 4) + (c - 'A' + 10);

            c = s[index++];c = toupper(c);
         }
      }
   }

   if (base == 10 && sign == 1)
      result = -result;

   return(result);
}

signed int64 atoi64(char *s)
{
   signed int64 result;
   int8 sign, base, index;
   char c;

   index = 0;
   sign = 0;
   base = 10;
   result = 0;

   if (!s)
      return 0;
   c = s[index++];

   // increase index if either positive or negative sign is detected
   if (c == '-')
   {
      sign = 1;         // Set the sign to negative
      c = s[index++];
   }
   else if (c == '+')
   {
      c = s[index++];
   }

   if (c >= '0' && c <= '9')
   {
      if (c == '0' && (s[index] == 'x' || s[index] == 'X'))
      {
         base = 16;
         index++;
         c = s[index++];
      }

      // The number is a decimal number
      if (base == 10)
      {
         while (c >= '0' && c <= '9') {
            result = (result << 1) + (result << 3);  // result *= 10;
            result += (c - '0');
            c = s[index++];
         }
      }
      else if (base == 16)    // The number is a hexa number
      {
         c = toupper(c);
         while ((c >= '0' && c <= '9') || (c >= 'A' && c <='F'))
         {
            if (c >= '0' && c <= '9')
               result = (result << 4) + (c - '0');
            else
               result = (result << 4) + (c - 'A' + 10);

            c = s[index++];c = toupper(c);
         }
      }
   }

   if (base == 10 && sign == 1)
      result = -result;

   return(result);
}
#endif

char * itoa(signed int32 num, unsigned int base, char * s)
{
     unsigned int32 temp=1;
     unsigned int8 i,sign=0,cnt=0;
     char c;

     if(num<0) {
         sign=1;        // Check for negative number
         num*=-1;
     }

     while(temp>0) {
         temp=(num/base);
         s[cnt]=(num%base)+'0';    // Conversion

         if(s[cnt]>0x39)
            s[cnt]+=0x7;

         cnt++;
         num=temp;
     }

     if(sign==1) {
         s[cnt]=0x2D;      // Negative sign
         cnt++;
     }

     for(i = 0;i<(int8)(cnt/2);i++) {

         c=s[i];
         s[i]=s[cnt-i-1];        // Reverse the number
         s[cnt-i-1]=c;
     }
     s[cnt]='\0';     // End the string
     return s;
}

float strtof(char *s, char *endptr)
{
   float pow10 = 1.0;
   float result = 0.0;
   int1 skip = 1, sign = 0, point = 0;
   char c;
   unsigned int8 ptr = 0;

   if (!s)
      return 0;

   for(c=s[ptr++]; c!=0; c=s[ptr++])
   {
      if (skip && !isspace(c))
      {
         skip = 0;
         if (c == '+')
         {
            sign = 0;
            continue;
         }           
         else if (c == '-')
         {
            sign = 1;
            continue;
         }
      }
      if (!skip && (c == '.') && !point)
         point = 1;
      else if (!skip && isdigit(c))
      {
         c -= '0';
         if (point)
         {
            pow10 = pow10 * 10.0;
            result += (float)c / pow10;   
         }
         else
         {
            result = 10.0 * result + (float)c;
         }
      }
      else if (!skip)
         break;
   }

   if (sign)
      result = -1*result;
     
   if(endptr)
   {
      if (ptr) {
         ptr--;
       #IF LONG_POINTERS
         *((long *)endptr)= s+ptr;
       #ELSE
         *((char *)endptr)=s+ptr;
       #ENDIF
      }
      else
      {
      #IF LONG_POINTERS
      *((long *)endptr)= s;
      #ELSE
      *((char *)endptr)=s;
      #ENDIF
      }
   }

   return(result);
}

#if defined(__PCD__)
float48 strtof48(char *s, char *endptr)
{
   float48 pow10 = 1.0;
   float48 result = 0.0;
   int1 skip = 1, sign = 0, point = 0;
   char c;
   unsigned int8 ptr = 0;

   if (!s)
      return 0;

   for(c=s[ptr++]; c!=0; c=s[ptr++])
   {
      if (skip && !isspace(c))
      {
         skip = 0;
         if (c == '+')
         {
            sign = 0;
            continue;
         }           
         else if (c == '-')
         {
            sign = 1;
            continue;
         }
      }
      if (!skip && (c == '.') && !point)
         point = 1;
      else if (!skip && isdigit(c))
      {
         c -= '0';
         if (point)
         {
            pow10 = pow10 * 10.0;
            result += (float48)c / pow10;   
         }
         else
         {
            result = 10.0 * result + (float48)c;
         }
      }
      else if (!skip)
         break;
   }

   if (sign)
      result = -1*result;
     
   if(endptr)
   {
      if (ptr) {
         ptr--;
       #IF LONG_POINTERS
         *((long *)endptr)= s+ptr;
       #ELSE
         *((char *)endptr)=s+ptr;
       #ENDIF
      }
      else
      {
      #IF LONG_POINTERS
      *((long *)endptr)= s;
      #ELSE
      *((char *)endptr)=s;
      #ENDIF
      }
   }

   return(result);
}

float64 strtod(char *s, char *endptr)
{
   float64 pow10 = 1.0;
   float64 result = 0.0;
   int1 skip = 1, sign = 0, point = 0;
   char c;
   unsigned int8 ptr = 0;

   if (!s)
      return 0;

   for(c=s[ptr++]; c!=0; c=s[ptr++])
   {
      if (skip && !isspace(c))
      {
         skip = 0;
         if (c == '+')
         {
            sign = 0;
            continue;
         }           
         else if (c == '-')
         {
            sign = 1;
            continue;
         }
      }
      if (!skip && (c == '.') && !point)
         point = 1;
      else if (!skip && isdigit(c))
      {
         c -= '0';
         if (point)
         {
            pow10 = pow10 * 10.0;
            result += (float64)c / pow10;   
         }
         else
         {
            result = 10.0 * result + (float64)c;
         }
      }
      else if (!skip)
         break;
   }

   if (sign)
      result = -1*result;
     
   if(endptr)
   {
      if (ptr) {
         ptr--;
       #IF LONG_POINTERS
         *((long *)endptr)= s+ptr;
       #ELSE
         *((char *)endptr)=s+ptr;
       #ENDIF
      }
      else
      {
      #IF LONG_POINTERS
      *((long *)endptr)= s;
      #ELSE
      *((char *)endptr)=s;
      #ENDIF
      }
   }

   return(result);
}
#endif

unsigned long strtoul(char *s, char *endptr, signed int base)
{
   char *sc,*s1,*sd;
   unsigned long x=0;
   char sign;
   char digits[]="0123456789abcdefghijklmnopqstuvwxyz";
   for(sc=s;isspace(*sc);++sc);
   sign=*sc=='-'||*sc=='+'?*sc++:'+';
   if(sign=='-' || base <0 || base ==1|| base >36) // invalid base
   goto StrtoulGO;

   else if (base)
   {
      if(base==16 && *sc =='0'&&(sc[1]=='x' || sc[1]=='X'))
         sc+=2;
      if(base==8 && *sc =='0')
         sc+=1;
      if(base==2 && *sc =='0'&&sc[1]=='b')
         sc+=2;

   }
   else if(*sc!='0') // base is 0, find base
      base=10;
   else if (sc[1]=='x' || sc[1]=='X')
      base =16,sc+=2;
   else if(sc[1]=='b')
      base=2,sc+=2;
   else
      base=8;
   for (s1=sc;*sc=='0';++sc);// skip leading zeroes
   sd=memchr(digits,tolower(*sc),base);
   for(; sd!=0; )
   {
      x=x*base+(int16)(sd-digits);
      ++sc;
      sd=memchr(digits,tolower(*sc),base);
   }
   if(s1==sc)
   {
   StrtoulGO:
      if (endptr)
      {
         #IF LONG_POINTERS
         *((long *)endptr)= s;
         #ELSE
         *((char *)endptr)=s;
         #ENDIF
         }
   return 0;
   }
   if (endptr)
   {
         #IF LONG_POINTERS
         *((long *)endptr)= sc;
         #ELSE
         *((char *)endptr)=sc;
         #ENDIF
   }
   return x;
}


signed long strtol(char *s,char *endptr, signed int base)
{
   char *sc,*s1,*sd;
   signed long x=0;
   char sign;
   char digits[]="0123456789abcdefghijklmnopqstuvwxyz";
   for(sc=s;isspace(*sc);++sc);
   sign=*sc=='-'||*sc=='+'?*sc++:'+';
   if (base <0 || base ==1|| base >36) // invalid base
   goto StrtolGO;
   else if (base)
   {
      if(base==16 && *sc =='0'&&(sc[1]=='x' || sc[1]=='X'))
         sc+=2;
      if(base==8 && *sc =='0')
         sc+=1;
      if(base==2 && *sc =='0'&&sc[1]=='b')
         sc+=2;

   }
   else if(*sc!='0') // base is 0, find base
      base=10;
   else if (sc[1]=='x' || sc[1]=='X')
      base =16,sc+=2;
   else if(sc[1]=='b')
      base=2,sc+=2;
   else
      base=8;
   for (s1=sc;*sc=='0';++sc);// skip leading zeroes

   sd=memchr(digits,tolower(*sc),base);
   for(;sd!=0;)
   {
      x=x*base+(int16)(sd-digits);
      ++sc;
      sd=memchr(digits,tolower(*sc),base);
   }
   if(s1==sc)
   {
   StrtolGO:
      if (endptr)
      {
         #IF LONG_POINTERS
         *((long *)endptr)= s;
         #ELSE
         *((char *)endptr)=s;
         #ENDIF
      }
   return 0;
   }
   if(sign=='-')
      x  =-x;
   if (endptr)
   {
        #IF LONG_POINTERS
         *((long *)endptr)= sc;
        #ELSE
        *((char *)endptr)=sc;
        #ENDIF
   }
   return x;
}

signed int8 system(char *string)
{
   return 0;
}

int8 mblen(char *s,size_t n)
{
   return strlen(s);
}

int8 mbtowc(wchar_t *pwc,char *s,size_t n)
{
   *pwc=*s;
   return 1;
}

int8 wctomb(char *s,wchar_t wchar)
{
   *s=wchar;
   return 1;
}

size_t mbstowcs(wchar_t *pwcs,char *s,size_t n)
{
   strncpy(pwcs,s,n);
   return strlen(pwcs);
}

size_t wcstombs(char *s,wchar_t *pwcs,size_t n)
{
   strncpy(s,pwcs,n);
   return strlen(s);
}

unsigned int32 _Randseed;

unsigned int16 rand(void)
{
   _Randseed = _Randseed * 1103515245 + 12345;
   return ((unsigned int16)(_Randseed >> 16) % RAND_MAX);
}

void srand(unsigned int32 seed)
{
   _Randseed = seed;
}

#if !defined(__PCD__)
typedef signed int8 (*_Cmpfun)(char * p1,char * p2);
#else
typedef signed int16 (*_Cmpfun)(char * p1,char * p2);
#endif
void qsort(char * qdata, unsigned int qitems, unsigned int qsize, _Cmpfun cmp) {
   unsigned int m,j,i,l;
   int1 done;
   unsigned int8 t[16];
   m = qitems/2;
   while( m > 0 ) {
     for(j=0; j<(qitems-m); ++j) {
        i = j;
        do
        {
           done=1;
           l = i+m;
           if( (*cmp)(qdata+i*qsize, qdata+l*qsize) > 0 ) {
              memcpy(t, qdata+i*qsize, qsize);
              memcpy(qdata+i*qsize, qdata+l*qsize, qsize);
              memcpy(qdata+l*qsize, t, qsize);
              if(m <= i)
                i -= m;
                done = 0;
           }
        } while(!done);
     }
     m = m/2;
   }
}
char *bsearch(char *key, char *base, size_t num, size_t width,_Cmpfun cmp)
{
   char *p, *q;
   size_t n;
   size_t pivot;
   signed int val;
   p = base;
   n = num;
   while (n > 0)
   {
      pivot = n >> 1;
      q = p + width * pivot;

      val = (*cmp)(key, q);

      if (val < 0)
         n = pivot;
      else if (val == 0)
         return ((char *)q);
      else {
         p = q + width;
         n -= pivot + 1;
      }
   }
   return NULL;      // There's no match
}
#endif


Any comments will be appreciated

thank you
jaume


Last edited by jamalavedra on Mon Feb 06, 2017 1:28 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 12:38 pm     Reply with quote

Straight away, this was what I was talking about:

xinc1 = -1;
xinc2 = -1;

Yet these are declared as int16.

These need to be _signed int16_. As does anything else where signs are used, or may occur.

There are several other similar places.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 12:51 pm     Reply with quote

I made a few changes to the glcd_pixel() function. The only real important
one is to type cast the 'array_pos' math to be 16-bit. It was doing 8-bit
math and truncating the result. This is probably the cause of writing
only occuring in the upper zone.

I cleaned up your code a little bit by moving the 'array_pos' declaration
to the start of the routine. I added a test to make sure the input x,y
are not 0, since this is illegal.

Ttelmah, since there are range checks on the input x, y, I don't see the
need for signed math here, so I didn't specify it.

Quote:
void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour)
{
unsigned int16 array_pos; // *** Put declaration here

if (x > SCREEN_WIDTH || y > SCREEN_HEIGHT) return;

if ((x == 0) || (y == 0)) return; // *** ADD THIS LINE ***

// Real screen coordinates are 0-63, not 1-64.
x -= 1;
y -= 1;

array_pos = (int16)x + (((int16)y / 8) * 128); // *** ADD (int16) in 2 places

.
.
.

}
jamalavedra



Joined: 25 Oct 2016
Posts: 62

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 1:04 pm     Reply with quote

PCM programmer wrote:
I made a few changes to the glcd_pixel() function. The only real important
one is to type cast the 'array_pos' math to be 16-bit. It was doing 8-bit
math and truncating the result. This is probably the cause of writing
only occuring in the upper zone.

I cleaned up your code a little bit by moving the 'array_pos' declaration
to the start of the routine. I added a test to make sure the input x,y
are not 0, since this is illegal.

Ttelmah, since there are range checks on the input x, y, I don't see the
need for signed math here, so I didn't specify it.

Quote:
void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour)
{
unsigned int16 array_pos; // *** Put declaration here

if (x > SCREEN_WIDTH || y > SCREEN_HEIGHT) return;

if ((x == 0) || (y == 0)) return; // *** ADD THIS LINE ***

// Real screen coordinates are 0-63, not 1-64.
x -= 1;
y -= 1;

array_pos = (int16)x + (((int16)y / 8) * 128); // *** ADD (int16) in 2 places

.
.
.

}


I tried out your guess and it worked perfectly. Thank you Very Happy
Any thoughts on why the text part isn't working? where the text should be a random pattern of pixels appear.
thanks
jaume
Ttelmah



Joined: 11 Mar 2010
Posts: 19224

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 1:36 pm     Reply with quote

The one I was pointing out, will cause problems according to the gradient of lines. It's the handling for lines that work in the opposite direction (so go from a high X to low X for example).
The delta's need to be declared as signed, or these won't work.
I guessed this one would exist, since the code is always assuming that the integers are signed, and this particular one was 'bound' to exist in the line handling.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 1:38 pm     Reply with quote

What happens if you just write one letter, as shown below ?
Does it work ? I'm trying to determine if the text is not actually
random dots, but it's over-writing the previous text. If we just
write one letter and it works, then that's probably what is happening.
If it works, try it with some other characters, not just "A".
Quote:
draw_text("A", 10, 10, Tahoma10, 1);


Where do these font files come from ? Did you make them ?
Can you provide a link, or post the Tahoma font file ?
jamalavedra



Joined: 25 Oct 2016
Posts: 62

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 1:48 pm     Reply with quote

this is the link where I got the Fonts from https://github.com/edeca/Electronics/tree/master/Include/fonts

When I only write one letter, such as "A", nothing appears. When I write several letters, such as "ABCde" random pattern appears. I believe it is random because the pattern changes reardless if I change or not the letters on the message.

thanks
temtronic



Joined: 01 Jul 2010
Posts: 9111
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 5:53 pm     Reply with quote

That link to those fonts was NOT written in CCS C, actually it's a driver not just a font file.so a LOT of that code HAS to be converted into CCS C.

You should go back to square one. Using the datasheet for the GLCD, create a simple program to turn on a pixel and confirm it is at the correct location. The PDF file does show the command set and it's fairly close to a CGLD( Character LCD). Doing this 'low level' programming will confirm the display does function properly. Ther'es even a simple 'all on / all off' command, does THAT work ?
I really think you've got a LOT of NON CCS compatible code and the 'numbers' are not correct,thus giving you garbage or random data on the GLCD.

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 06, 2017 5:56 pm     Reply with quote

There appears to be a problem with fetching the correct data from the
array if it's declared as 'const'. Based on my tests, if it's in ram, it
should work. The array is 1176 bytes so it will take up about 1/3 of
the ram in your 18LF2685.

Edit the font file, font_tahoma.h, and remove 'const' from the array
declaration. This will put the font data in RAM:
Code:
unsigned char Tahoma10[] =



temtronic wrote:

That link to those fonts was NOT written in CCS C, actually it's a driver
not just a font file.so a LOT of that code HAS to be converted into CCS C.

Temtronic,
His draw_char() function does actually use a font file of the type
that he has listed on the Github website. I changed the font array
declaration to RAM (removed 'const') and I edited the glcd_pixel()
routine to merely print out the x,y coordinates of the "dot" and the
color (on or off). This allowed me to generate the vertical line
of dots for each column of the character box, and display it in the
MPLAB vs. 8.92 Simulator using the UART1 output window.

Here is the function, modified for debugging purposes:
Code:

void glcd_pixel(unsigned char x, unsigned char y, unsigned char colour)
{
printf("x:%x, y:%x, color:%x \r", x, y, colour);
}

Thus for the final character in the font table, the tilde '~', I got the
output given below. Each block represents a column in the font cell.
The width of the font cell is 7 pixels, so there are 7 columns. The dots
in each column start at the top of the font cell and go to the bottom.

Thus you can see the tilde '~' starts with a short vertical up-stroke
(that's the two 01's) in the first column. The it goes sideways to
the right for a couple dots and then squiggles around and finishes
with a vertical upstroke in the final column. So, I think the routine
is working OK, temtronic. It just requires the font array to be
declared in RAM instead of as 'const'. I don't currently know why
that is, and I'm not actively investigating it at this time.
Code:
width = 07
x:0a, y:0a, color:00
x:0a, y:0b, color:00
x:0a, y:0c, color:00
x:0a, y:0d, color:00
x:0a, y:0e, color:00
x:0a, y:0f, color:01
x:0a, y:10, color:01
x:0a, y:11, color:00
x:0a, y:12, color:00
x:0a, y:13, color:00
x:0a, y:14, color:00

x:0b, y:0a, color:00
x:0b, y:0b, color:00
x:0b, y:0c, color:00
x:0b, y:0d, color:00
x:0b, y:0e, color:01
x:0b, y:0f, color:00
x:0b, y:10, color:00
x:0b, y:11, color:00
x:0b, y:12, color:00
x:0b, y:13, color:00
x:0b, y:14, color:00

x:0c, y:0a, color:00
x:0c, y:0b, color:00
x:0c, y:0c, color:00
x:0c, y:0d, color:00
x:0c, y:0e, color:01
x:0c, y:0f, color:00
x:0c, y:10, color:00
x:0c, y:11, color:00
x:0c, y:12, color:00
x:0c, y:13, color:00
x:0c, y:14, color:00

x:0d, y:0a, color:00
x:0d, y:0b, color:00
x:0d, y:0c, color:00
x:0d, y:0d, color:00
x:0d, y:0e, color:00
x:0d, y:0f, color:01
x:0d, y:10, color:00
x:0d, y:11, color:00
x:0d, y:12, color:00
x:0d, y:13, color:00
x:0d, y:14, color:00

x:0e, y:0a, color:00
x:0e, y:0b, color:00
x:0e, y:0c, color:00
x:0e, y:0d, color:00
x:0e, y:0e, color:00
x:0e, y:0f, color:00
x:0e, y:10, color:01
x:0e, y:11, color:00
x:0e, y:12, color:00
x:0e, y:13, color:00
x:0e, y:14, color:00

x:0f, y:0a, color:00
x:0f, y:0b, color:00
x:0f, y:0c, color:00
x:0f, y:0d, color:00
x:0f, y:0e, color:00
x:0f, y:0f, color:00
x:0f, y:10, color:01
x:0f, y:11, color:00
x:0f, y:12, color:00
x:0f, y:13, color:00
x:0f, y:14, color:00

x:10, y:0a, color:00
x:10, y:0b, color:00
x:10, y:0c, color:00
x:10, y:0d, color:00
x:10, y:0e, color:01
x:10, y:0f, color:01
x:10, y:10, color:00
x:10, y:11, color:00
x:10, y:12, color:00
x:10, y:13, color:00
x:10, y:14, color:00

Done
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5  Next
Page 2 of 5

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group