c++/rgb-assembler/rgb-assembler.cpp
author František Kučera <franta-hg@frantovo.cz>
Sat, 23 Dec 2017 17:33:49 +0100
changeset 17 8f0a5552db78
parent 16 5c142e9c00e5
child 18 4975c24cc361
permissions -rw-r--r--
index in read() and write() is in same units as memory type
     1 #include <cstdlib>
     2 #include <iostream>
     3 #include <wchar.h>
     4 #include <locale.h>
     5 #include <cstring>
     6 
     7 #include <chrono>
     8 #include <thread>
     9 
    10 using namespace std;
    11 
    12 typedef uint16_t address_t;
    13 typedef uint8_t octet_t;
    14 typedef uint8_t command_t;
    15 typedef uint8_t sleep_t;
    16 typedef uint8_t color_t;
    17 typedef uint8_t led_t;
    18 
    19 // TODO: strong typedefs http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html ?
    20 
    21 const address_t MEMORY_SIZE = 1024;
    22 
    23 /**
    24  * Skip to the given address.
    25  * parameter: address_t
    26  */
    27 const command_t CMD_GOTO = 0x70;
    28 
    29 /**
    30  * Compare values on two addresses and go to one of given three addresses.
    31  * parameter: address_t a
    32  * parameter: address_t b
    33  * parameter: address_t GOTO target when a == b
    34  * parameter: address_t GOTO target when a > b
    35  * parameter: address_t GOTO target when a < b
    36  */
    37 const command_t CMD_GOTO_COMPARE = 0x80;
    38 
    39 /**
    40  * Wait given time in ms.
    41  * parameter: sleep_t
    42  */
    43 const command_t CMD_SLEEP = 0xFF;
    44 
    45 /**
    46  * Set RGB LED color.
    47  * parameter: led_t LED number
    48  * parameter: color_t red
    49  * parameter: color_t green
    50  * parameter: color_t blue
    51  */
    52 const command_t CMD_COLOR = 0xAA;
    53 
    54 /**
    55  * Stop program.
    56  */
    57 const command_t CMD_END = 0xED;
    58 
    59 /**
    60  * Increase value at given address
    61  * parameter: address_t
    62  */
    63 const command_t CMD_INCREMENT = 0x11;
    64 
    65 /**
    66  * Decrease value at given address
    67  * parameter: address_t
    68  */
    69 const command_t CMD_DECREMENT = 0x12;
    70 
    71 /**
    72  * Placeholder for unsupported command.
    73  * Just for testing.
    74  */
    75 const command_t CMD_INVALID = 0x1;
    76 
    77 // TODO: more commands, better numbers
    78 
    79 /**
    80  * Reads data on given position in memory and increments the index (position).
    81  * 
    82  * @param memory array of bytes / octets
    83  * @param index offset in same units as memory type
    84  * @return value found at given position
    85  */
    86 template<typename T> T read(octet_t * memory, address_t &index) {
    87 	// TODO: for addresses: map higher memory to static hardcoded areas or peripherals
    88 	T * value = reinterpret_cast<T*> (memory + index);
    89 	index += sizeof (T);
    90 	return *value;
    91 }
    92 
    93 /**
    94  * Writes data to given position in memory and increments the index (position).
    95  * @param memory array of bytes / octets
    96  * @param index offset in same units as memory type
    97  * @param value value to be written at given position
    98  */
    99 template<typename T> void write(octet_t * memory, address_t &index, const T value) {
   100 	T * m = reinterpret_cast<T*> (memory + index);
   101 	*m = value;
   102 	index += sizeof (value);
   103 }
   104 
   105 int main(int argc, char* argv[]) {
   106 
   107 	setlocale(LC_ALL, "");
   108 
   109 	octet_t * memory = (octet_t*) malloc(MEMORY_SIZE);
   110 
   111 	// Sample program / data:
   112 	// TODO: load bytes from file, stdin, serial port, network…
   113 	{
   114 		address_t a = 0;
   115 		write<command_t>(memory, a, CMD_SLEEP);
   116 		write<sleep_t>(memory, a, 255);
   117 		write<command_t>(memory, a, CMD_SLEEP);
   118 		write<sleep_t>(memory, a, 10);
   119 		write<command_t>(memory, a, CMD_SLEEP);
   120 		write<sleep_t>(memory, a, 255);
   121 		write<command_t>(memory, a, CMD_GOTO);
   122 		write<address_t>(memory, a, a + sizeof (address_t) + 2 * sizeof (command_t));
   123 		write<command_t>(memory, a, CMD_INVALID);
   124 		write<command_t>(memory, a, CMD_INVALID);
   125 		write<command_t>(memory, a, CMD_SLEEP);
   126 		write<sleep_t>(memory, a, 255);
   127 		write<command_t>(memory, a, CMD_COLOR);
   128 		write<led_t>(memory, a, 23);
   129 		write<color_t>(memory, a, 0);
   130 		write<color_t>(memory, a, 200);
   131 		write<color_t>(memory, a, 255);
   132 		write<command_t>(memory, a, CMD_INCREMENT);
   133 		write<address_t>(memory, a, 0);
   134 		write<command_t>(memory, a, CMD_DECREMENT);
   135 		write<address_t>(memory, a, 0);
   136 		write<command_t>(memory, a, CMD_GOTO_COMPARE);
   137 		write<address_t>(memory, a, 0);
   138 		write<address_t>(memory, a, 0 + sizeof (command_t) + sizeof (sleep_t));
   139 		write<address_t>(memory, a, a - 3 * sizeof (address_t) - 2 * sizeof (command_t));
   140 		write<address_t>(memory, a, 0);
   141 		write<address_t>(memory, a, a + sizeof (address_t));
   142 		write<command_t>(memory, a, CMD_END);
   143 	}
   144 
   145 	for (address_t i = 0; i < MEMORY_SIZE;) {
   146 		wprintf(L"command %*d = ", 4, i);
   147 		command_t command = read<command_t>(memory, i);
   148 		wprintf(L"%02X  ", command);
   149 
   150 		switch (command) {
   151 			case CMD_GOTO:
   152 			{
   153 				i = read<address_t>(memory, i);
   154 				wprintf(L"GOTO %*d\n", 5, i);
   155 				break;
   156 			}
   157 			case CMD_SLEEP:
   158 			{
   159 				sleep_t delay = read<sleep_t>(memory, i);
   160 				wprintf(L"SLEEP %*d ms\n", 4, delay);
   161 				this_thread::sleep_for(chrono::milliseconds(delay));
   162 				break;
   163 			}
   164 			case CMD_COLOR:
   165 			{
   166 				led_t led = read<led_t>(memory, i);
   167 				color_t r = read<color_t>(memory, i);
   168 				color_t g = read<color_t>(memory, i);
   169 				color_t b = read<color_t>(memory, i);
   170 				wprintf(L"COLOR  %02X %02X %02X → %d\n", r, g, b, led);
   171 				break;
   172 			}
   173 			case CMD_INCREMENT:
   174 			case CMD_DECREMENT:
   175 			{
   176 				address_t address = read<address_t>(memory, i);
   177 				address_t address_r = address;
   178 				address_t address_w = address_r;
   179 				octet_t value = read<octet_t>(memory, address_r);
   180 				value = command == CMD_INCREMENT ? value + 1 : value - 1;
   181 				write<octet_t>(memory, address_w, value);
   182 				wprintf(L"%sCREMENT %*d → %02X\n", (command == CMD_INCREMENT ? "IN" : "DE"), 5, address, value);
   183 				break;
   184 			}
   185 			case CMD_GOTO_COMPARE:
   186 			{
   187 				address_t aa = read<address_t>(memory, i);
   188 				address_t ab = read<address_t>(memory, i);
   189 				address_t eq = read<address_t>(memory, i);
   190 				address_t gt = read<address_t>(memory, i);
   191 				address_t lt = read<address_t>(memory, i);
   192 
   193 				octet_t a = read<octet_t>(memory, aa);
   194 				octet_t b = read<octet_t>(memory, ab);
   195 
   196 				if (a == b) i = eq;
   197 				else if (a > b) i = gt;
   198 				else i = lt;
   199 
   200 				wprintf(L"GOTO COMPARE  a = %02X, b = %02X, eq = %d, gt = %d, lt = %d → %d\n", a, b, eq, gt, lt, i);
   201 				break;
   202 			}
   203 			case CMD_END:
   204 			{
   205 				wprintf(L"END\n");
   206 				i = MEMORY_SIZE;
   207 				break;
   208 			}
   209 			default:
   210 			{
   211 				wprintf(L"invalid command\n");
   212 			}
   213 		}
   214 
   215 	}
   216 
   217 	free(memory);
   218 	memory = nullptr;
   219 	wprintf(L"all done\n");
   220 	return 0;
   221 }
   222