Skip to content

Commit

Permalink
Add command for setting instructions via large binary block.
Browse files Browse the repository at this point in the history
Should be much faster.
  • Loading branch information
carterturn committed Feb 5, 2024
1 parent 23fb9c1 commit dde2cfe
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 1 deletion.
Binary file modified build/prawnblaster/prawnblaster.uf2
Binary file not shown.
Binary file modified build/prawnblaster/prawnblasteroverclock.uf2
Binary file not shown.
129 changes: 128 additions & 1 deletion prawnblaster/prawnblaster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ unsigned int instructions[60008];
// max_waits + 4
unsigned int waits[404];

char readstring[256] = "";
#define SERIAL_BUFFER_SIZE 256
char readstring[SERIAL_BUFFER_SIZE] = "";
// This contains the number of clock cycles for a half period, which is currently 5 (there are 5 ASM instructions)
const unsigned int non_loop_path_length = 5;

Expand Down Expand Up @@ -1148,6 +1149,132 @@ void loop()
fast_serial_printf("%u %u\r\n", half_period, reps);
}
}
else if (strncmp(readstring, "setb ", 5) == 0)
{
// set a large block of instructions encoded in a binary blob of fixed length.
unsigned int start_addr;
unsigned int inst_count;
unsigned int pseudoclock;
int parsed = sscanf(readstring, "%*s %u %u %u", &pseudoclock, &start_addr, &inst_count);
int address_offset = pseudoclock * (max_instructions * 2 / num_pseudoclocks_in_use + 2);
if (parsed < 3)
{
fast_serial_printf("invalid request\n");
}
else if (pseudoclock < 0 || pseudoclock > 3)
{
fast_serial_printf("The specified pseudoclock must be between 0 and 3 (inclusive)\r\n");
}
else if (start_addr >= max_instructions || start_addr + inst_count >= max_instructions)
{
fast_serial_printf("invalid address or too many instructions\r\n");
}
// It takes 8 bytes to describe an instruction: 4 bytes for reps, 4 bytes for half period
uint32_t inst_per_buffer = SERIAL_BUFFER_SIZE / 8;
unsigned int addr = start_addr;
while(inst_count > inst_per_buffer){
fast_serial_read(readstring, 8*inst_per_buffer);
for (int i = 0; i < inst_per_buffer; i++)
{
uint32_t reps = ((readstring[8*i + 7] << 24)
| (readstring[8*i + 6] << 16)
| (readstring[8*i + 5] << 8)
| (readstring[8*i + 4]));
uint32_t half_period = ((readstring[8*i + 3] << 24)
| (readstring[8*i + 2] << 16)
| (readstring[8*i + 1] << 8)
| (readstring[8*i + 0]));

if (reps == 0)
{
// This indicates either a stop or a wait instruction
instructions[address_offset + addr * 2] = 0;
if (half_period == 0)
{
// It's a stop instruction
instructions[address_offset + addr * 2 + 1] = 0;
addr++;
}
else if (half_period >= 6)
{
// It's a wait instruction. See "set" command for why we do this.
instructions[address_offset + addr * 2 + 1] = (half_period - 4) / 2;
addr++;
}
else
{
fast_serial_printf("invalid request\r\n");
}
}
else if (half_period < (non_loop_path_length))
{
fast_serial_printf("half-period too short\r\n");
}
else if (reps < 1)
{
fast_serial_printf("reps must be at least one\r\n");
}
else
{
instructions[address_offset + addr * 2] = reps;
instructions[address_offset + addr * 2 + 1] = half_period - non_loop_path_length;
addr++;
}
}
inst_count -= inst_per_buffer;
}
// In this if statement, we read a final serial buffer and load it into instructions.
if(inst_count > 0){
fast_serial_read(readstring, 8*inst_count);
for(int i = 0; i < inst_count; i++){
uint32_t reps = ((readstring[8*i + 7] << 24)
| (readstring[8*i + 6] << 16)
| (readstring[8*i + 5] << 8)
| (readstring[8*i + 4]));
uint32_t half_period = ((readstring[8*i + 3] << 24)
| (readstring[8*i + 2] << 16)
| (readstring[8*i + 1] << 8)
| (readstring[8*i + 0]));

if (reps == 0)
{
// This indicates either a stop or a wait instruction
instructions[address_offset + addr * 2] = 0;
if (half_period == 0)
{
// It's a stop instruction
instructions[address_offset + addr * 2 + 1] = 0;
addr++;
}
else if (half_period >= 6)
{
// It's a wait instruction. See "set" command for why we do this.
instructions[address_offset + addr * 2 + 1] = (half_period - 4) / 2;
addr++;
}
else
{
fast_serial_printf("invalid request\r\n");
}
}
else if (half_period < (non_loop_path_length))
{
fast_serial_printf("half-period too short\r\n");
}
else if (reps < 1)
{
fast_serial_printf("reps must be at least one\r\n");
}
else
{
instructions[address_offset + addr * 2] = reps;
instructions[address_offset + addr * 2 + 1] = half_period - non_loop_path_length;
addr++;
}
}
}
fast_serial_printf("ok\r\n");
}
else if (strncmp(readstring, "go high", 7) == 0)
{
unsigned int pseudoclock;
Expand Down

0 comments on commit dde2cfe

Please sign in to comment.