
|
This is very poorly written, and very very simplistic, owing to the fact it was just a small thing to see if it could work. There is no stack, no registers for storage, and very few opcodes. Aside from that, it did work, and very basic PIC functionality could be implemented! Programming could be performed by sending a CMD_WRITE_EEPROM byte, the desired EEPROM address, then the value. That could be done in a loop to program the whole block of ROM; yes, terribly inefficient I know. Also, only half of the ROM could be addressed, I didn't get round to implementing the code to address over an 8-bit word by squashing two bytes together by using endianness.
Compiled using AVR Studio 4 targeting an ATMega8515 // Include library files
#include <avr/io.h>
#include <stdlib.h>
#define F_CPU 3680000UL //Define crystal/RC osc frequency
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
//Definitions
#define CMD_PING 3
#define CMD_READ_EEPROM 4
#define CMD_WRITE_EEPROM 5
#define ACK_OK 100
#define ACK_ERROR 99
// Prototypes
void init_usart(unsigned int baud);
void init_io(void);
void txbyte(unsigned char data);
unsigned char rxbyte(void);
void startup_tasks(void);
void out_debug(unsigned char output);
void out(unsigned char output);
unsigned char out_state(void);
void machine(void);
// Let's go
int main(void)
{
startup_tasks(); //Boot procedure for microcontroller
while(1)
{ //Infinite loop, let ISRs do all the hard work from now on
machine();
}
}
void machine()
{
unsigned char pc = 1;
unsigned char acc = 0;
unsigned char opc;
while(pc != 256)
{
opc = (unsigned char)eeprom_read_byte((uint8_t*)pc);
pc++;
switch(opc)
{
case 2: //Output
out(acc);
break;
case 1: //Load Accumulator
acc = (unsigned char)eeprom_read_byte((uint8_t*)pc + 1);
pc++;
break;
case 3: //Increment
acc++;
break;
case 4: //Decrement
acc--;
break;
case 5: //Delay
_delay_ms(1000);
break;
case 6: //Jump
pc = (unsigned char)eeprom_read_byte((uint8_t*)pc + 1);
break;
case 7: //Jump on zero
if (acc == 0)
{
pc = (unsigned char)eeprom_read_byte((uint8_t*)pc + 1);
}
else
{
pc++;
}
break;
case 8: //Jump on non-zero
if (acc > 0)
{
pc = (unsigned char)eeprom_read_byte((uint8_t*)pc + 1);
}
else
{
pc++;
}
break;
case 9: //Add x to accumulator
acc += (unsigned char)eeprom_read_byte((uint8_t*)pc + 1);
pc++;
break;
case 10: //Sub x from acc
acc -= (unsigned char)eeprom_read_byte((uint8_t*)pc + 1);
pc++;
break;
}
}
}
void startup_tasks(void)
{
init_usart(23); //Init the USART (Serial) for 3.68Mhz clock at 9600 Baud
init_io();
sei(); //Enable interrupts
}
void out_debug(unsigned char output)
{
//Procedure to output byte to 'debug' port
PORTA = output;
}
void out(unsigned char output)
{
//Procedure to output byte to output port
PORTB = output;
}
unsigned char out_state(void)
{
//Procedure to get the current output state
return PORTB;
}
void init_usart(unsigned int baud)
{
// Setup serial I/O for communication
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
UCSRC = (1 << URSEL) | (3 << UCSZ0);
}
SIGNAL (SIG_UART_RECV)
{
//USART RX interrupt service routine
switch(UDR)
{
case(CMD_PING):
txbyte(ACK_OK);
break;
case CMD_READ_EEPROM:
txbyte((unsigned char)eeprom_read_byte((uint8_t*)rxbyte()));
break;
case CMD_WRITE_EEPROM:
eeprom_write_byte ((uint8_t*)rxbyte(), (uint8_t)rxbyte());
txbyte(ACK_OK);
break;
default:
txbyte(ACK_ERROR);
break;
}
}
void init_io(void)
{
DDRB = 255;
DDRA = 255;
}
void txbyte(unsigned char data)
{
while ( !( UCSRA & (1<<UDRE)) ); //Wait for empty slot to send data
UDR = data; //Send it
}
unsigned char rxbyte (void)
{
while ( !(UCSRA & (1<<RXC)) ); //Wait until there is a byte to be read from RX buffer
return UDR; //Get it
}
|
Online SoundCloud Downloader, NEW!Download tracks posted on SoundCloud for free in high-quality MP3! SoundScrape.netUseful eBay Links |