main.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (C) 2018 Tom Li <tomli at tomli.me>.
  3. *
  4. * This software is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation; either version 3, or (at your option) any
  7. * later version.
  8. *
  9. * This software is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. * or FITNESS FOR A PARTICULAR PURPOSE.
  12. *
  13. * See COPYING for terms and conditions.
  14. *
  15. * GPL or LGPL does __not__ require attribution beyond preserving and
  16. * following the license, but if you find my code is useful or inspirational
  17. * to your own project, I'd be thankful if you attribute my name.
  18. */
  19. #include <stdio.h>
  20. #include <stdint.h>
  21. #include <stdbool.h>
  22. #include <string.h>
  23. #include "syscalls.h"
  24. #define VARNAME "TESTVAR"
  25. #define VARSIZE 35970
  26. void demo(void);
  27. __at(0xA5F4) static uint16_t fillrect_color;
  28. __at(0x4000) static uint8_t bank1[16384];
  29. int main(void) {
  30. /* toggle 15 MHz CPU frequency */
  31. uint8_t orig_cpu = cpuclk_get();
  32. cpuclk_set(CPUCLK_FULL);
  33. /* cleanup the screen and reset the cursor */
  34. clear_screen();
  35. cursor_row = 0;
  36. cursor_col = 0;
  37. /*
  38. * First example: Hello, world.
  39. *
  40. * On different machines, the methods for inputs and outputs are
  41. * different. SDCC's solution to this problem is defining a prototype
  42. * for "putchar()", etc, and requiring a user's to supply their own
  43. * implementation in order to make "printf()", etc, useful.
  44. *
  45. * My implementation of "putchar()" can be found in "syscalls.c".
  46. *
  47. * NOTE: stdio library is HUGE. This program is less than 900 bytes,
  48. * but stdio makes it compile to 4000+ bytes! If size and speed matters,
  49. * don't use stdio library. But for most programs doing simple calculations,
  50. * it doesn't, feel free to use them.
  51. */
  52. printf("Hello, world.\n\n");
  53. printf("...(press a key)...\n");
  54. getkey();
  55. /* second demo */
  56. demo();
  57. exit:
  58. /* wait for a keypress before exit */
  59. getkey();
  60. clear_screen();
  61. /* restore the original CPU frequency */
  62. cpuclk_set(orig_cpu);
  63. return 0;
  64. }
  65. void demo(void) {
  66. uint16_t page;
  67. uint16_t addr;
  68. /* looking for the Flash page and offset for our APPVAR */
  69. if (findsym(FINDSYM_APPVAR, VARNAME, &page, &addr) != 0) {
  70. printf("error:\n");
  71. printf("cannot find data variable.\n");
  72. return;
  73. }
  74. else {
  75. /* TODO: add a magic header for sanity check */
  76. }
  77. /*
  78. * Save the original page number in Bank1, and map our page to
  79. * Bank1 instead.
  80. */
  81. uint16_t orig_page = bank1_get();
  82. bank1_swap(page);
  83. /* initial x, y position, and maximum x position */
  84. uint16_t x = 30;
  85. uint16_t y = 50;
  86. uint16_t x_max = 255 + x;
  87. uint16_t idx = addr;
  88. for (uint16_t i = 0; i < VARSIZE / 3; i++) {
  89. uint8_t length = bank1[idx];
  90. idx++;
  91. if (idx == 0x4000U) {
  92. page++;
  93. bank1_swap(page);
  94. idx = 0;
  95. }
  96. uint16_t color = bank1[idx];
  97. idx++;
  98. if (idx == 0x4000U) {
  99. page++;
  100. bank1_swap(page);
  101. idx = 0;
  102. }
  103. color |= ((bank1[idx]) << 8);
  104. idx++;
  105. if (idx == 0x4000U) {
  106. page++;
  107. bank1_swap(page);
  108. idx = 0;
  109. }
  110. /*
  111. * This converts BGR to RGB by swapping the first/last five bits.
  112. * For the last five bits, we extract and bitshift it to the beginning,
  113. * and for the first five bits, we extract and bitstift it to the end.
  114. * Then, we clear the original first and last five bits, and apply the
  115. * bitshifted version on it to swap them.
  116. */
  117. uint16_t tmp = (color & 0x001FU) << 11;
  118. tmp |= (color & 0xF800U) >> 11;
  119. color &= 0xFFE0U & 0x07FFU;
  120. color |= tmp;
  121. fillrect_color = color;
  122. uint16_t x_end = x + length;
  123. if (x_end < x_max) {
  124. fillrect(x, x_end, y, y + 1);
  125. x = x_end;
  126. }
  127. else if (x_end == x_max) {
  128. fillrect(x, x_end, y, y + 1);
  129. x = 30;
  130. y++;
  131. }
  132. else {
  133. fillrect(x, x_max, y, y + 1);
  134. x_end -= 255;
  135. y++;
  136. fillrect(30, x_end, y, y + 1);
  137. x = x_end;
  138. }
  139. }
  140. bank1_swap(orig_page);
  141. }