NoOneYouKnow
Member
Hello all! I've been working on this project for some time now, and I think I finally have a good handle of it all. If someone could take a look at this, I would really appreciate it.
I started with a simple LED flasher to simulate muzzle flash in a prop firearm and turn a flashlight on and off with a 12F629. Here is the original schematic and code;
**broken link removed**
So I took this code, and thanks to an excellent project by Andres Olivares **broken link removed**, I came up with a design to simulate muzzle flash, and play one sound when firing, and a separate sound when out of ammo.
This is what I have currently.
**broken link removed**
I started with a simple LED flasher to simulate muzzle flash in a prop firearm and turn a flashlight on and off with a 12F629. Here is the original schematic and code;
**broken link removed**
Code:
#include "PIC12F629.h"
#include "system.h"
#pragma DATA _CONFIG, _CPD_OFF &
_CP_OFF &
_BODEN_ON &
_MCLRE_OFF &
_PWRTE_ON &
_WDT_OFF &
_INTRC_OSC_NOCLKOUT
#pragma CLOCK_FREQ 4000000
#define TRIGGER gpio.0
#define MUZZLE gpio.5
void main()
{
cmcon = 7; // Digital I/O
trisio = 0b00000001; // GP0 Input
gpio = 0; // All Outputs '0'
option_reg.NOT_GPPU = 0; // Weak Pull-Ups
wpu.0 = 1; // GP0 Weak Pull-Up
while (TRIGGER == 0) // While Trigger is Low
{
delay_ms(20);
if (TRIGGER == 0)
{
MUZZLE = 1; // MUZZLE On
delay_ms(75); // Muzzle Flash
MUZZLE = 0; // MUZZLE Off
delay_ms(191);
}
}
}
So I took this code, and thanks to an excellent project by Andres Olivares **broken link removed**, I came up with a design to simulate muzzle flash, and play one sound when firing, and a separate sound when out of ammo.
This is what I have currently.
**broken link removed**
Code:
M6D Deluxe.c
#include "M6DDeluxe.h"
#include "mmc_driver.h"
#include "vs1011_driver.h"
#include "fat_driver.h"
unsigned int32 current_sector;
unsigned int32 current_file;
unsigned char play_sound;
unsigned char ammo_count;
unsigned char lzr_on;
unsigned char FIRED;
//Funciones generales
void player_init()
{
//Okazumods - Gokussj5okazu
ADCON1 = 0b00001111; // Port A Digital I/O
TRIS_A = 0b00100000; // PortA.5 Input
TRIS_B = 0b11110001; // PortB Inputs
volume = 0x7F; // Volume = 127
current_sector = 0x00;
current_file = 0;
play_sound = 0;
ammo_count = 8;
lzr_on = 0;
MUZZLE = 0;
FIRED = 0;
}
void main()
{
while (TRIGGER)
{
FIRED = 0;
}
if (!TRIGGER)
{
delay_ms(20);
if( !TRIGGER)
{
if (FIRED == 0)
{
if (ammo_count > 0)
{
current_file = 0;
MUZZLE = 1;
play_sound = 1;
ammo_count --;
FIRED = 1;
delay_ms(75);
MUZZLE = 0;
delay_ms(191);
}
else
{
current_file = 1;
play_sound = 1;
delay_ms(286);
}
}
}
}
if (!RELOAD)
{
ammo_count = 8;
}
if (!LZRSW)
{
delay_ms(20);
if (!LZRSW)
{
if (lzr_on == 0)
{
LZR = 1;
}
else
{
LZR = 0;
}
}
}
int mmc_result;
char cmd;
player_init();
delay_ms(10);
mmc_result = mmc_init();
LED = mmc_result;
if (mmc_result != 0)
{
while (1);
}
delay_ms(100);
resetvs1011_hard();
blink_led(3);
find_first_fat32_partition();
read_volumeid();
while (play_sound == 1)
{
//mmc_read_block_to_vs1011(current_sector);
//current_sector++;
cmd = play_file(current_file);
}
}
Code:
fat_driver.h
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define EOD 0
#define UNUSED 1
#define LFNAME 2
#define NFNAME 3
#define FILE_NOT_FOUND 2
#define NEXT_TRACK 0
#define PREVIOUS_TRACK 1
unsigned int8 sector_buffer[512];
unsigned int8 dir_entry[32];
unsigned int16 bytes_per_sector;
unsigned int8 sectors_per_cluster;
unsigned int16 number_of_reserved_sectors;
unsigned int8 number_of_fats;
unsigned int32 sectors_per_fat;
unsigned int32 root_directory_first_cluster;
unsigned int32 partition_lba_begin;
unsigned int32 fat_begin_lba;
unsigned int32 cluster_begin_lba;
void sector_to_serial()
{
unsigned long i;
unsigned long j;
unsigned long count;
count = 0;
for (i = 0; i < 32; i++)
{
for (j = 0; j < 16; j++)
{
printf("%2X ", sector_buffer[count]);
count++;
}
printf("\r\n");
}
}
void read_mbr()
{
unsigned int32 sector_number;
unsigned int16 i;
sector_number = 0;
XCS = 1;
XDCS = 1;
SSPEN = 1;
mmc_open_block(sector_number);
for (i = 0; i < 512; i++)
{
sector_buffer[i] = SPI_READ(0xFF);
}
mmc_close_block();
SSPEN = 0;
}
void read_sector(unsigned int32 sector_number)
{
unsigned int16 i;
unsigned int32 lba;
XCS = 1;
XDCS = 1;
SSPEN = 1;
lba = partition_lba_begin + sector_number;
mmc_open_block(lba);
for (i = 0; i < 512; i++)
{
sector_buffer[i] = SPI_READ(0xFF);
}
mmc_close_block();
SSPEN = 0;
}
void mmc_read_block_to_vs1011_test(int32 block_number)
{
unsigned int8 i, j;
unsigned int16 count;
read_sector(block_number);
XCS = 1;
XDCS = 1;
MMC_CS = 0;
SPI_READ(0xFF);
MMC_CS = 1;
SSPEN = 0;
XDI_TRIS = 0;
XDCS = 0;
count = 0;
for (i = 0; i < 16; i++)
{
while (!XDREQ);
for (j = 0; j < 32; j++)
{
vs_spi_write(sector_buffer[count]);
count++;
}
}
XDCS = 1;
XDI_TRIS = 1;
SSPEN = 1;
SPI_READ(0xFF);
}
int read_direntry(int8 num)
{
unsigned int16 offset;
unsigned int16 i;
offset = (unsigned int16)num * 32;
for (i = 0; i < 32; i++)
{
dir_entry[i] = sector_buffer[offset + i];
}
return TRUE;
}
unsigned int32 make_int32(unsigned int8 lsb, unsigned int8 mb1, unsigned int8 mb2, unsigned int8 msb)
{
int32 result = 0;
result = (unsigned int32)msb;
result <<= 8;
result |= (unsigned int32)mb2;
result <<= 8;
result |= (unsigned int32)mb1;
result <<= 8;
result |= (unsigned int32)lsb;
return result;
}
unsigned int16 make_int16(unsigned int8 lsb, unsigned int8 msb)
{
unsigned int16 result = 0;
result = (unsigned int16)msb;
result <<= 8;
result |= (unsigned int16)lsb;
return result;
}
unsigned int8 find_first_fat32_partition()
{
int8 part_sig;
partition_lba_begin = 0;
read_mbr();
part_sig = sector_buffer[0x1C2];
if ((part_sig != 0x0B) && (part_sig != 0x0C))
{
// Data is not a valid FAT32 file system
return FALSE;
}
// Look for the offset
partition_lba_begin = make_int32(sector_buffer[0x1C6], sector_buffer[0x1C6 + 1], sector_buffer[0x1C6 + 2], sector_buffer[0x1C6 + 3]);
return TRUE;
}
unsigned int8 read_volumeid()
{
unsigned int16 signature;
unsigned int8 part_sig;
signature = 0;
// Leemos el primer sector despues del offset
read_sector(0);
// Signature
signature = make_int16(sector_buffer[0x1FE], sector_buffer[0x1FE + 1]);
#ifdef DEBUG
printf("Sector Zero Signtaure: %LX\r\n", signature);
#endif
if (signature == 0xAA55)
{
// Bytes per Sector
bytes_per_sector = make_int16(sector_buffer[0x0B], sector_buffer[0x0B + 1]);
#ifdef DEBUG
printf("Bytes per sector: %Lu\r\n", bytes_per_sector);
#endif
// Sectors per Cluster
sectors_per_cluster = sector_buffer[0x0D];
#ifdef DEBUG
printf("Sectors per cluster: %u\r\n", sectors_per_cluster);
#endif
// Number of Reserved Sectors
number_of_reserved_sectors = make_int16(sector_buffer[0x0E], sector_buffer[0x0E + 1]);
#ifdef DEBUG
printf("Number of reserved sectors: %Lu\r\n", number_of_reserved_sectors);
#endif
// Number of FATs
number_of_fats = sector_buffer[0x10];
#ifdef DEBUG
printf("Number of FATs: %u\r\n", number_of_fats);
#endif
// Sectors per FAT
sectors_per_fat = make_int32(sector_buffer[0x24], sector_buffer[0x24 + 1], sector_buffer[0x24 + 2], sector_buffer[0x24 + 3]);
#ifdef DEBUG
printf("Sectors per FAT: %Lu\r\n", sectors_per_fat);
#endif
// Root Directory First Cluster
root_directory_first_cluster = make_int32(sector_buffer[0x2C], sector_buffer[0x2C + 1], sector_buffer[0x2C + 2], sector_buffer[0x2C + 3]);
#ifdef DEBUG
printf("Root Directory First Cluster: %Lu\r\n", root_directory_first_cluster);
#endif
// Computamos otros valores usando los datos obtenidos
fat_begin_lba = number_of_reserved_sectors;
#ifdef DEBUG
printf("FAT Begin LBA: %Lu\r\n", fat_begin_lba);
#endif
cluster_begin_lba = fat_begin_lba + (number_of_fats * sectors_per_fat);
#ifdef DEBUG
printf("Cluster Begin LBA: %Lu\r\n", cluster_begin_lba);
#endif
return TRUE;
} else {
return FALSE;
}
}
unsigned int32 compute_lba(unsigned int32 cluster_number)
{
return cluster_begin_lba + ((cluster_number - 2) * ((unsigned int32)sectors_per_cluster));
}
unsigned int8 check_if_eod()
{
if (dir_entry[0] == 0x00)
{
return TRUE;
}
else
{
return FALSE;
}
}
unsigned int8 get_attrib()
{
return dir_entry[0x0B];
}
unsigned int8 determine_direntry_type()
{
unsigned int8 attr;
if (check_if_eod() == TRUE)
{
return EOD;
}
else
{
if (dir_entry[0] == 0xE5)
{
return UNUSED;
}
else
{
attr = get_attrib();
if (bit_test(attr, 0) && bit_test(attr, 1) && bit_test(attr, 2) && bit_test(attr, 3))
{
return LFNAME;
}
else
{
return NFNAME;
}
}
}
}
void get_filename()
{
unsigned int i;
printf("FILE: ");
for (i = 0; i < 8; i++)
{
printf("%c", dir_entry[i]);
}
printf(".");
for (i = 8; i < 11; i++)
{
printf("%c", dir_entry[i]);
}
printf("\r\n");
}
unsigned int32 read_fat(unsigned int32 cluster_number)
{
unsigned int32 calc;
unsigned int32 offset;
unsigned int32 rest;
unsigned int32 soff;
calc = cluster_number / ((unsigned int32)bytes_per_sector / 4);
offset = fat_begin_lba + calc;
rest = cluster_number - (calc * ((unsigned int32)bytes_per_sector / 4));
soff = rest * 4;
read_sector(offset);
return make_int32(sector_buffer[soff], sector_buffer[soff + 1], sector_buffer[soff + 2], sector_buffer[soff + 3]);
}
unsigned int32 get_file_first_cluster()
{
return make_int32(dir_entry[0x1A], dir_entry[0x1A + 1], dir_entry[0x14], dir_entry[0x14 + 1]);
}
unsigned int32 get_file_size()
{
return make_int32(dir_entry[0x1C], dir_entry[0x1C + 1], dir_entry[0x1C + 2], dir_entry[0x1C + 3]);
}
char get_file(unsigned int32 first_cluster, unsigned int32 size)
{
unsigned int32 current_cluster;
unsigned int32 current_lba;
unsigned int32 current_sector;
unsigned int32 length_count;
current_cluster = first_cluster;
current_lba = compute_lba(current_cluster);
current_sector = 0;
length_count = 0;
mmc_read_block_to_vs1011(partition_lba_begin + current_lba);
//mmc_read_block_to_serial(partition_lba_begin + current_lba);
#ifdef DEBUG
printf("GETFILE: Current LBA = %Lu\r\n", current_lba);
#endif
do
{
length_count += 512;
#ifdef DEBUG2
printf("GETFILE: Length count = %Lu from %Lu\r\n", length_count, size);
#endif
if (length_count <= size)
{
#ifdef DEBUG2
printf("GETFILE: Incrementing current sector count...\r\n");
#endif
current_sector++;
if (current_sector < sectors_per_cluster)
{
#ifdef DEBUG2
printf("GETFILE: Incrementing current LBA count...\r\n");
#endif
current_lba++;
}
else
{
#ifdef DEBUG2
printf("GETFILE: Resetting current sector count...\r\n");
#endif
current_sector = 0;
#ifdef DEBUG2
printf("GETFILE: Reading FAT for next cluster information...\r\n");
#endif
current_cluster = read_fat(current_cluster);
#ifdef DEBUG2
printf("GETFILE: Computing LBA for current sector count...\r\n");
#endif
current_lba = compute_lba(current_cluster);
}
mmc_read_block_to_vs1011(partition_lba_begin + current_lba);
//mmc_read_block_to_serial(partition_lba_begin + current_lba);
#ifdef DEBUG
printf("GETFILE: Current LBA = %Lu\r\n", current_lba);
#endif
}
else
{
#ifdef DEBUG2
printf("GETFILE: File length reached!\r\n");
#endif
break;
}
#ifdef DEBUG2
printf("GETFILE: Current cluster = %Lu\r\n", current_cluster);
#endif
}
while (current_cluster < 0xFFFFFFF8);
#ifdef DEBUG
printf("GETFILE: Sending extra zeroes...\r\n");
#endif
morezeroes();
#ifdef DEBUG
printf("GETFILE: End of File!\r\n");
#endif
LED = 0;
return 0;
}
void read_root_directory()
{
unsigned int32 current_cluster;
unsigned int32 current_lba;
unsigned int32 current_sector;
signed int8 current_direntry;
unsigned int32 file_cluster;
unsigned int32 file_size;
unsigned int8 entry_type;
unsigned int8 attrib;
char cmd;
//unsigned int8 i;
current_cluster = root_directory_first_cluster;
#ifdef DEBUG
printf("ROOT: Current Cluster = %Lu\r\n", current_cluster);
#endif
current_lba = compute_lba(current_cluster);
#ifdef DEBUG
printf("ROOT: Root Directory LBA = %Lu\r\n", current_lba);
#endif
current_direntry = 0;
current_sector = 0;
#ifdef DEBUG
printf("ROOT: Reading current LBA...\r\n");
#endif
read_sector(current_lba);
do
{
cmd = 0;
#ifdef DEBUG
printf("ROOT: Reading dir entry...\r\n");
#endif
read_direntry(current_direntry);
#ifdef DEBUG
printf("ROOT: Determining dir entry type...\r\n");
#endif
entry_type = determine_direntry_type();
#ifdef DEBUG
printf("ROOT: Entry type = %u\r\n", entry_type);
#endif
if (entry_type == NFNAME)
{
#ifdef DEBUG
printf("ROOT: Getting attrib...\r\n");
#endif
attrib = get_attrib();
#ifdef DEBUG
printf("ROOT: Attrib = %X\r\n", attrib);
#endif
if (!bit_test(attrib, 3) && !bit_test(attrib, 4))
{
#ifdef DEBUG
printf("ROOT: It's a file...\r\n");
get_filename();
#endif
file_cluster = get_file_first_cluster();
#ifdef DEBUG
printf("ROOT: File first cluster = %Lu\r\n", file_cluster);
#endif
file_size = get_file_size();
#ifdef DEBUG
printf("ROOT: Playing file...\r\n");
#endif
cmd = get_file(file_cluster, file_size);
#ifdef DEBUG2
printf("ROOT: Waiting for PLAY signal for next file...\r\n");
while (PLAY_PAUSE);
#endif
read_sector(current_lba);
}
#ifdef DEBUG
else
{
if (bit_test(attrib, 3))
{
printf("ROOT: It's the Volume ID...\r\n");
} else {
printf("ROOT: It's a subdirectory...\r\n");
}
}
#endif
}
if (cmd == 0)
{
current_direntry++;
if (current_direntry > 15)
{
current_direntry = 0;
current_sector++;
if (current_sector < sectors_per_cluster)
{
current_lba++;
}
else
{
current_sector = 0;
current_cluster = read_fat(current_cluster);
current_lba = compute_lba(current_cluster);
}
read_sector(current_lba);
}
} else {
current_direntry--;
if (current_direntry < 0)
{
current_direntry = 15;
current_sector--;
if (current_sector > sectors_per_cluster)
{
current_lba--;
}
else
{
current_sector = sectors_per_cluster;
current_cluster = read_fat(current_cluster);
current_lba = compute_lba(current_cluster);
}
read_sector(current_lba);
}
}
}
while (check_if_eod() == FALSE);
}
char play_file(unsigned int32 file_index)
{
unsigned int32 current_cluster;
unsigned int32 current_lba;
unsigned int32 current_sector;
unsigned int8 current_direntry;
unsigned int32 file_cluster;
unsigned int32 file_size;
unsigned int32 current_index;
unsigned int8 entry_type;
unsigned int8 attrib;
char cmd;
current_cluster = root_directory_first_cluster;
current_lba = compute_lba(current_cluster);
current_direntry = 0;
current_sector = 0;
read_sector(current_lba);
current_index = 0;
cmd = FILE_NOT_FOUND;
do
{
read_direntry(current_direntry);
entry_type = determine_direntry_type();
if (entry_type == NFNAME)
{
attrib = get_attrib();
if (!bit_test(attrib, 3) && !bit_test(attrib, 4))
{
get_filename();
file_cluster = get_file_first_cluster();
file_size = get_file_size();
if (current_index == file_index)
{
cmd = get_file(file_cluster, file_size);
return cmd;
}
current_index++;
read_sector(current_lba);
}
}
current_direntry++;
if (current_direntry > 15)
{
current_direntry = 0;
current_sector++;
if (current_sector < sectors_per_cluster)
{
current_lba++;
}
else
{
current_sector = 0;
current_cluster = read_fat(current_cluster);
current_lba = compute_lba(current_cluster);
}
read_sector(current_lba);
}
}
while (check_if_eod() == FALSE);
return cmd;
}