Cumulus Firware Compilation

This is the right place to discuss on how to implement hardware vsync, adding a VIA or AY chipset, puting multiple roms, or how to design a new flash expansion card.
Godzil
Squad Leader
Posts: 756
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Cumulus Firware Compilation

Post by Godzil » Fri Jan 30, 2015 4:43 pm

Chema: I recommend you to dump your SD card and analyse the output in a hexeditor.

FAT16 structure are quite well documented, I suspect that the code/your code try to use some value hardcoded when the fat formating is not "reliable" on where things are.

(On a previous project, there were some code that was searching for the first FAT block in a partition to use it, which was absolutely false because due to the way FAT is formated, the FAT sector could be at multiple places, due to this the code was using an invalid FAT sector and was listing file that does not exist.

FS like FAT are generally simple to implement, but it's also really easy to do a simple mistake that broke everything. You should double check your changes, and looking at a dump in a hexeditor generally helps a lot. You could also test the FAT reading code by making a PC application that open the dump file. it may help to debug your code, as I suspect you don't have the tool to debug on the PIC chip

User avatar
Chema
Game master
Posts: 2078
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Cumulus Firware Compilation

Post by Chema » Fri Jan 30, 2015 7:25 pm

Indeed, Godzil. You're right about this. And that is what I tried to do. However at some places I still had to hack a bit (could not manage to follow the official ways).

I dumped the card into a file and wrote a test program, there is where I make my tests. However I forgot about trying to read more than one sector :( When I saw it readed the first bytes correctly I thought it as working.

On the good side, I did not break anything in the process and my FAT32 SDHC card still works perfectly...

What puzzles me is why Microsoft formatted cards do not work. There must be some field I am not interpreting correctly. It keeps on saying the card has 6000+ reserved sectors and FAT size is something above 700 bytes... But that is another story. I would be happy if it supported FAT16 SD cards under normal formats and conditions. And in the meantime made sure the problem is in the FAT code. All this will be useful for the future firmware :)

Godzil
Squad Leader
Posts: 756
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Cumulus Firware Compilation

Post by Godzil » Sat Jan 31, 2015 11:51 am

How do you search for the FAT block? it may move, I think the bootblock give an hint on where to search it.

I strongly suspect that the Windows formater and the other one you used does not use the same parameter for formating, or block size and this led to some important structure not beeing at the same place.

Just to try, do a zeroing of your card (write zero everywhere) before trying to format with the windows one, I think that a non quick format will do something similar, but I'm not sure. The reason is that an old FAT block entry could be left, and you may not use the correct one...

User avatar
Chema
Game master
Posts: 2078
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Cumulus Firware Compilation

Post by Chema » Mon Feb 02, 2015 11:08 am

Yep Godzil. The FAT driver in Cumulus is really not complete and does not seem to handle all cases, though it seems to try by looking at the code.

I reached a point where my modified FAT code works reading files on an SD card with FAT16 and MBR as well as SDHC FAT32 with MBR cards (using images), but Cumulus fails. Probably I am not replicating the sequence of calls correctly, but I really fear this is not the problem now.

More testing is needed, again trying to follow the sequence of actions and errors, which is something not easy when the code you want to test is the one interfacing with the SD card using the SPI interface. This requires using the cumulus itself and is a bit tedious and time-consuming.

Not sure if I will go further or not. I have learned a lot of things in the process but I am not sure if it is worth the effort, to be honest.

I strongly suggest that for the future Cumulus rewrite firmware we switch to a decent fat driver. Have a look at this:
http://elm-chan.org/fsw/ff/00index_e.html

It is source code which can be adapted to any microcontroller using SPI interface with an SD/MMC card and seems to support well any type of FAT or card.

But it is not a simple patch of the firmware. It needs a lot of code rewrite.

Godzil
Squad Leader
Posts: 756
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Cumulus Firware Compilation

Post by Godzil » Mon Feb 02, 2015 1:10 pm

Chema: Nice find :)

For the current uC the cumulus use the "Petit" version seems more appropriate:

http://elm-chan.org/fsw/ff/00index_p.html

Godzil
Squad Leader
Posts: 756
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Cumulus Firware Compilation

Post by Godzil » Tue Feb 03, 2015 5:43 pm

Chema: you should try to test the Petit version of FatFS, the few needed function to make should already exist in the cumulus in a similar form.

It should work with partitioned and non partitioned SD card (taking only the first one) and FAT16/32 filesystem.
The "disk_initialize" function should just reply if the SD card is inserted or not, it is not to do a format on the SDcard ;)

The read function is made to read part of one or multiple sectors, the "sector" parameter is simply the same as the SD card sector (the 512 block)

If the Petit version work correctly, we may evaluate the need to use the complete version, I'm not sure this is really needed because the only function that could be useful is the file create, but I'm not really certain that this would be a really interesting feature..

What we need is all the 4 commandm read, dir, lseek and write, and we should at least support FAT16 and FAT32.

Tell me if you need help, or you don't have time to test this, you can make a simple layer between currently used fat functions and the Petit FatFS function for managing the FAT so that you won't have too much change to do.

User avatar
Chema
Game master
Posts: 2078
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Cumulus Firware Compilation

Post by Chema » Wed Feb 04, 2015 12:09 pm

I saw the Petit version but I am not sure it is easy (or even possible) to adapt it, because I think the firmware expects to be able to keep several files open at the same time (not as the PetitFS version).

I will try to dig in a bit more on this, but to be honest I am not sure if I will have the time and if it is of any interest. After all people are using SDHC cards without problems and it seems there is not a real demand for SD card support anymore.

Godzil
Squad Leader
Posts: 756
Joined: Sat May 21, 2011 7:21 pm
Location: Between UK and France
Contact:

Re: Cumulus Firware Compilation

Post by Godzil » Wed Feb 04, 2015 12:44 pm

Oh! I forgot that we had to support 4 floppy at the same time..

You're right, the Petit version can't fit for the final version unless constantely open/close file :(

zaxon
1st Star Corporal
Posts: 10
Joined: Thu Jun 29, 2017 9:51 am

Re: Cumulus Firware Compilation

Post by zaxon » Sat Jul 01, 2017 11:10 am

Hello all ,thanks for add and sorry about my poor english. I know, it is really old topic but i have problem with Cumulus and i hope somebody here can help me. I do few Cumulus boards for friends but i'm stuck on bootloader . With some issues i'm finally compile it and load to cumulus but when i try update from SD card CUMULUS.BIN file, is hanging on start. I try lot of diffrent SDHC memory cards without sukcess. Any clue?
Software what i use: MPLAB x 3.65 , C18 compiler 4.47 , Pickit 2.

User avatar
iss
Squad Leader
Posts: 515
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Cumulus Firware Compilation

Post by iss » Sat Jul 01, 2017 11:29 am

Welcome zaxon!
Attached is my compiled version of the PIC firmware - it's for S1D15G10 display and it works fine for me.
BTW, there are many hardware bugs in Cumulus and I don't recommend to bother with it, but this is of course
only my very personal opinion...
Attachments
Cumulus-S1D15G10.bin.zip
(14.19 KiB) Downloaded 29 times

zaxon
1st Star Corporal
Posts: 10
Joined: Thu Jun 29, 2017 9:51 am

Re: Cumulus Firware Compilation

Post by zaxon » Sat Jul 01, 2017 11:54 am

Hi thanks. But i need bootloader first ;)And here is my problem, bootloader what i have , cannot load BIN file from memory card. I try 8 diffrent cards. Also my Cumulus use PCF8833 display. I was read all topics here, http://forum.defence-force.org/viewtopi ... &start=120 , is similiar problem. How to resolve it?

User avatar
iss
Squad Leader
Posts: 515
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Cumulus Firware Compilation

Post by iss » Sat Jul 01, 2017 12:46 pm

Okay, for me the problem is in the fat32.c source (function 'uint8_t fat32_init(void)', line #97)

Code: Select all

......
	if (sectors_per_cluster < 16)
		return 0;	
.......
I see two easy and quick-to-do solutions:
1. Format the SD-card so it has less than 16 sectors per cluster
2. Dirty hack - just remove or comment above lines and recompile source for your display.
... and post the results of your tests :)

zaxon
1st Star Corporal
Posts: 10
Joined: Thu Jun 29, 2017 9:51 am

Re: Cumulus Firware Compilation

Post by zaxon » Sat Jul 01, 2017 1:09 pm

Again, first i need compile working SD bootloader. I have brand new Cumulus with empty PIC. You talking about firmware.

Code: Select all

/* Cumulus 18F46K20 Firmware
 * SD Card Bootloader.
 * Copyright 2010 Retromaster.
 * 
 *  This file is part of Cumulus Firmware.
 * 
 *  Cumulus Firmware is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or any later version. 
 *
 *  Cumulus Firmware is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Cumulus Firmware.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "p18f46K20.h" 
#include "delays.h" 

#ifdef TEXT_SUPPORT
#define NOFONT8X16
#include "fonts.h" 
#endif

/* Config */
#pragma config FOSC = ECIO6
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = ON
#pragma config BOREN = OFF
#pragma config MCLRE = ON
#pragma config WDTEN = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF 
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CP2 = OFF
#pragma config CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF

typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef long int32_t;

#pragma udata
uint32_t fpp_begin_lba;
uint32_t fat_begin_lba;
uint32_t sectors_per_fat;
uint32_t cluster_begin_lba;
uint8_t sectors_per_cluster;
uint8_t fat_count;
uint16_t root_dir_first_cluster;
uint16_t reserved_sector_count;

#pragma udata sector_buffer_section
uint8_t sector_buffer[512];

#define RM_RESET_VECTOR 			0x001000
#define RM_HIGH_INTERRUPT_VECTOR    0x001008 
#define RM_LOW_INTERRUPT_VECTOR     0x001018 

/* Vector remapping */
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
void _high_ISR (void)
{
    _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000018
void _low_ISR (void)
{
    _asm goto RM_LOW_INTERRUPT_VECTOR _endasm
}

#pragma code
far rom char str_cumulus_bin[] = "CUMULUS BIN";

uint8_t erase_program_verify_page(uint16_t address, uint8_t* buf)
{
	uint8_t i;
	far rom uint8_t* rom_ptr;
    rom_ptr = (far rom uint8_t*) address;
 
	/* Dummy read, required for loading the table pointer */
	i = *rom_ptr;

	/* Erase */
    EECON1bits.EEPGD = 1;     
    EECON1bits.CFGS = 0;      
    EECON1bits.FREE = 1;      
    EECON1bits.WREN = 1;      
    INTCONbits.GIE = 0;     
    EECON2 = 0x55;          
    EECON2 = 0xAA; 
    EECON1bits.WR = 1;      
    INTCONbits.GIE = 1;                   

	/* Write 64 bytes */
    for (i = 0; i < 64; i++) 
        rom_ptr[i] = buf[i];    

    EECON1bits.EEPGD = 1;               
    EECON1bits.CFGS = 0;                
    EECON1bits.FREE = 0;                
    EECON1bits.WREN = 1;                
    INTCONbits.GIE = 0;     
    EECON2 = 0x55;          
    EECON2 = 0xAA; 
    EECON1bits.WR = 1;      
    INTCONbits.GIE = 1;     
    EECON1bits.WREN = 0;           

	/* Verify 64 bytes */
    for (i = 0; i < 64; i++) 
        if (rom_ptr[i] != buf[i])
			return 0;

	return 1;          
}

#define PCF8833
//#define S1D15G10

#ifdef PCF8833

/* LCD Controller Commands */
#define SLEEPOUT   0x88  /* sleep out */
#define INVON      0x84  /* inversion ON */
#define SETCON     0xA4  /* write contrast */
#define DISPON     0x94  /* display ON */
#define CASET      0x54 /* column address set */
#define PASET      0xD4  /* page address set */
#define RAMWR      0x34 /* memory write */
#define MADCTL     0x6C  /* memory access control */
#define COLMOD     0x5C /* interface pixel format */

#endif 

#ifdef S1D15G10

#define DISON     0xF5      // Display on 
#define DISINV    0xE5      // Inverse display 
#define COMSCN    0xDD      // Common scan direction 
#define DISCTL    0x53      // Display control 
#define SLPOUT    0x29      // Sleep out 
//#define PASET     0xAE      // Page address set 
#define PASET     0xA8      // Page address set 
//#define CASET     0xA8      // Column address set 
#define CASET     0xAE      // Column address set 
#define DATCTL    0x3D      // Data scan direction, etc. 
#define RAMWR     0x3A      // Writing to memory 
#define OSCON     0x8B      // Internal oscillation on 
#define PWRCTR    0x04      // Power control 
#define VOLCTR    0x81      // Electronic volume control 
 
#endif

#if defined(PCF8833) || defined(S1D15G10)

/* Initialize EUSART module used for 9-bit SPI transmission. */
static void init_EUSART(void)
{
	/* Set baud rate */
	BAUDCONbits.CKTXP = 1;
	BAUDCONbits.BRG16 = 0;
	SPBRGH = 0;
	SPBRG = 1;

	/* Set TRIS bits */
	TRISCbits.TRISC6 = 1;
	TRISCbits.TRISC7 = 1;
	
	/* Synchronous Master mode */
	TXSTAbits.SYNC = 1;
	TXSTAbits.CSRC = 1;
	RCSTAbits.SPEN = 1;
	 
	/* Receive disabled, transmit enabled */
	RCSTAbits.SREN = 0;
	RCSTAbits.CREN = 0;
	TXSTAbits.TXEN = 1;
	
	/* 9-bit transmission */
	TXSTAbits.TX9 = 1;
}

/* Write given command byte to LCD */
static void n6610_write_command(uint8_t command)
{
	uint8_t value;

	/* Move highest bit into TX9D */
	if (command & 0x80)
		TXSTAbits.TX9D = 1;
	else 
		TXSTAbits.TX9D = 0;

	/* Command byte */
 	value = (command << 1);	

	/* Wait until EUSART transmitter is free */
	while (!TXSTAbits.TRMT);
	TXREG = value;	
}

/* Write given data byte to LCD */
static void n6610_write_data(uint8_t data)
{
	uint8_t value;

	/* Move highest bit into TX9D */
	if (data & 0x80)
		TXSTAbits.TX9D = 1;
	else 
		TXSTAbits.TX9D = 0;

	/* Data byte */
	value = (data << 1) | 1;

	/* Wait until EUSART transmitter is free */
	while (!TXSTAbits.TRMT);
	TXREG = value;		
}

static const rom uint8_t reverse_table[16] = {
0b0000,
0b1000,
0b0100,
0b1100,
0b0010,
0b1010,
0b0110,
0b1110,
0b0001,
0b1001,
0b0101,
0b1101,
0b0011,
0b1011,
0b0111,
0b1111
};

static uint8_t reverse_bits(uint8_t value)
{
	uint8_t rev;

	rev = reverse_table[value & 0x0F] << 4;
	rev |= reverse_table[(value & 0xF0) >> 4];

	return rev;
}

/* Draws given area with given color. Area width must be multiple of 2. */
static void n6610_fill_area(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t v1, uint8_t v2, uint8_t v3)
{ 
	uint8_t i, j;

	x = (x & 0xFE);
	w = (w & 0xFE);

  	/* Page address set */
	n6610_write_command(CASET); 
	n6610_write_data(reverse_bits(x)); 
	n6610_write_data(reverse_bits(x + w - 1)); 

	/* Column address set */
	n6610_write_command(PASET); 
 	n6610_write_data(reverse_bits(y)); 
	n6610_write_data(reverse_bits(y + h - 1)); 
 
 	/* Fill memory */
 	n6610_write_command(RAMWR); 
	
	for (i = 0; i < w / 2; i ++)
 		for (j = 0; j < h; j ++)
		{
			n6610_write_data(v1);
			n6610_write_data(v2);
			n6610_write_data(v3);
		}
} 

#ifdef TEXT_SUPPORT
/* Draws given character in b/w using the 6x8 Font. */
void n6610_draw_char(uint8_t x, uint8_t y, char c)
{ 
	uint8_t i, j, v;
	rom unsigned char* char_base;

	c -= 31;

	x = (x & 0xFE) | 0x01;

  	/* Page address set */
	n6610_write_command(CASET); 
	n6610_write_data(reverse_bits(x + 1)); 
	n6610_write_data(reverse_bits(x + 6)); 

	/* Column address set */
	n6610_write_command(PASET); 
 	n6610_write_data(reverse_bits(y)); 
	n6610_write_data(reverse_bits(y + 7)); 
 
 	/* Fill memory */
 	n6610_write_command(RAMWR); 

	char_base = (rom unsigned char*) _FONT6X8 + ((uint16_t) c) * 8;
	for (i = 0; i < 8; i ++)
	{
		v = char_base[i];

		for (j = 0; j < 6 / 2; j ++)
		{				
			switch (v & 0xC0)
			{
			case 0x00:
				n6610_write_data(0x00);
				n6610_write_data(0x00);
				n6610_write_data(0x00);
				break;
			case 0x40:
				n6610_write_data(0x00);
				n6610_write_data(0xF0);
				n6610_write_data(0xFF);
				break;
			case 0x80: 
				n6610_write_data(0xFF);
				n6610_write_data(0x0F);
				n6610_write_data(0x00);
				break;
			case 0xC0:
				n6610_write_data(0xFF);
				n6610_write_data(0xFF);
				n6610_write_data(0xFF);
				break;
			}

			v = v << 2;
		}
	}
} 

/* Draws given string in b/w using the 6x8 font */
void n6610_draw_rom_str(uint8_t x, uint8_t y, const far rom char* c)
{
	while (*c)
	{
		n6610_draw_char(x, y, *c);
		c ++;
		x += 6;
	}
}

#pragma romdata
rom char hex_lookup[16] = 
{ 
	'0', '1', '2', '3', 
	'4', '5', '6', '7', 
	'8', '9', 'A', 'B', 
	'C', 'D', 'E', 'F' 
};

#pragma code
void n6610_debug_message_short(uint8_t y, const far rom char* msg, uint16_t val)
{
	uint8_t start;
	int8_t j;
	
	// Draw string.
	n6610_draw_rom_str(0, y, msg);

	/* Print out value in hex */
	for (j = 0; j < 4; j ++)
	{
		n6610_draw_char(120 - j * 6, y, hex_lookup[val & 0xF]);
		val = val >> 4;
	}
}
#endif
#endif

#ifdef PCF8833
/* Initialize LCD controller */
void n6610_init(void)
{
	/* Initialize EUSART module for 9-bit synchronous transmission */
	init_EUSART();

	/* Setup RST and CS pins */
	TRISCbits.TRISC0 = 0;
	TRISCbits.TRISC1 = 0;

	/* Reset */
	PORTCbits.RC1 = 0;
	Delay1KTCYx(1000);
	PORTCbits.RC1 = 1;
	Delay1KTCYx(1000);

	/* Chip Select */
	PORTCbits.RC0 = 0;
	
 	/* Sleep out  (command 0x11) */
 	n6610_write_command(SLEEPOUT); 

	/* Color Interface Pixel Format  (command 0x3A) */
 	n6610_write_command(COLMOD); 
 	n6610_write_data(0xC0);   /* 0x03 = 12 bits-per-pixel */

	/* Memory access controller  (command 0x36).   */
 	n6610_write_command(MADCTL); 
	n6610_write_data(0x06);   /* 0xE0 = mirror y, vertical, reverse rgb */

	/* Write contrast  (command 0x25) */
 	n6610_write_command(SETCON); 
	n6610_write_data(0x22);   /* contrast 0x40  */
	Delay1KTCYx(2); 

 	/* Display On  (command 0x29) */
  	n6610_write_command(DISPON);
}
#endif

#ifdef S1D15G10
/* Initialize LCD controller */
void n6610_init(void)
{
	/* Initialize EUSART module for 9-bit synchronous transmission */
	init_EUSART();

	/* Setup RST and CS pins */
	TRISCbits.TRISC0 = 0;
	TRISCbits.TRISC1 = 0;

	/* Reset */
	PORTCbits.RC1 = 0;
	Delay1KTCYx(1000);
	PORTCbits.RC1 = 1;
	Delay1KTCYx(1000);

	/* Chip Select */
	PORTCbits.RC0 = 0;

	/* Display control */
 	n6610_write_command(DISCTL); 
 	n6610_write_data(0x00); // P1: 0x00 = 2 divisions, switching period=8 (default) 
	n6610_write_data(0x04); // P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32) 
 	n6610_write_data(0x00); // P3: 0x00 = no inversely highlighted lines 
	
 	/* COM scan */
 	n6610_write_command(COMSCN); 
	n6610_write_data(0x80);  // P1: 0x01 = Scan 1->80, 160<-81 

	/* Internal oscilator ON */
 	n6610_write_command(OSCON); 
 
 	/* Sleep out */
 	n6610_write_command(SLPOUT); 

	/* Power control */
 	n6610_write_command(PWRCTR); 
	n6610_write_data(0xF0);   // reference voltage regulator on, circuit voltage follower on, BOOST ON 
 
 	/* Inverse display */
 	n6610_write_command(DISINV);

	/* Data control */
 	n6610_write_command(DATCTL); 
	n6610_write_data(0x60); // P1: 0x05 = page address normal, col address inverted, address scan in page direction 
	n6610_write_data(0x00); // P2: 0x00 = RGB sequence (default value) 
	n6610_write_data(0x40); // P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A) 

	/* Voltage control (contrast setting) */
 	n6610_write_command(VOLCTR); 
	n6610_write_data(0x24); // P1 = 32  volume value  (adjust this setting for your display  0 .. 63) 
	n6610_write_data(0xC0); // P2 = 3    resistance ratio  (determined by experiment) 
 
	/* allow power supply to stabilize */
 	Delay1KTCYx(100); 
 
 	/* turn on the display */
 	n6610_write_command(DISON); 
}
#endif

#define CARD_TYPE_SD 0
#define CARD_TYPE_SDHC 1

uint8_t card_type;

/* SPI Send/Receive byte */
static uint8_t SPI(uint8_t d) 
{  
	char received = 0;
	
	SSPBUF = d;
	while (SSPSTATbits.BF != 1);		
	received = SSPBUF;
	
	return received;
}

/* Send a command to SD/MMC */
uint8_t card_command(uint8_t cmd, uint16_t addrH, uint16_t addrL, uint8_t crc)
{	
	SPI(0xFF);
	SPI(cmd);
	SPI((uint8_t) (addrH >> 8));
	SPI((uint8_t) addrH);
	SPI((uint8_t) (addrL >> 8));
	SPI((uint8_t) addrL);
	SPI(crc);
	SPI(0xFF);	
	return SPI(0xFF);	// return the last received character
}

/* Initalize SD/MMC Card */
uint8_t card_init(void) 
{ 
	uint8_t i;
	
	/* Slow clock during card identification */
	TRISCbits.TRISC3 = 0;	
	TRISCbits.TRISC5 = 0;	
	SSPCON1bits.SSPEN = 0;
	SSPCON1 = 0x12;			// CKP High, SPI Master, clock = Fosc/64
	SSPSTATbits.SMP = 0;
	//SSPSTATbits.SMP = 1;
	SSPSTATbits.CKE = 0;
	SSPCON1bits.SSPEN = 1;
	
	/* Raise Chip Select */
	TRISCbits.TRISC2 = 0;
	PORTCbits.RC2 = 1;	
	
	/* Switch card to SPI Mode */
	for(i = 0; i < 10; i ++) 
		SPI(0xFF); 
		
	/* Lower Chip Select */
	PORTCbits.RC2 = 0;

	/* Send CMD0 */
	if (card_command(0x40, 0x0000, 0x0000, 0x95) != 0x01) 
		return 0;

	card_type = CARD_TYPE_SD;	
	if ((card_command(0x48, 0x0000, 0x1AA, 0x87) & 4) == 0)	
	{
		SPI(0xFF);
		SPI(0xFF);		
		if ((SPI(0xFF) & 1) == 0)
			return 0;
		if (SPI(0xFF) != 0xAA)
			return 0;
			
		/* Send ACMD41 */ 	
		while (1)
		{
			uint8_t result;

			card_command(0x77, 0x0000, 0x0000, 0xFF);
			result = card_command(0x69, 0x4000, 0x0000, 0xFF);
			if (result == 0x00)
				break;								
		}
	
		/* Send CMD58 */
		if (card_command(0x7A, 0x0000, 0x0000, 0xFF))
			return 0;			
		  
		if(SPI(0xFF) & 0x40)
			card_type = CARD_TYPE_SDHC;

		SPI(0xFF);
		SPI(0xFF);
		SPI(0xFF);							
	}							
	else
	{	
		/* Send CMD1 */ 	
		while (card_command(0x41, 0x0000, 0x0000, 0xFF) != 0x00);
	}

	/* Raise Chip Select */
	PORTCbits.RC2 = 1;
	
	/* Speed up the clock */
	SSPCON1bits.SSPEN = 0;
	//SSPCON1 = 0x11;			// CKP High, SPI Master, clock = Fosc/16
	SSPCON1 = 0x10;			// CKP High, SPI Master, clock = Fosc/4
	SSPSTATbits.SMP = 0;
	//SSPSTATbits.SMP = 1;
	SSPSTATbits.CKE = 0;
	SSPCON1bits.SSPEN = 1;
	
	return 1;
}

/* Reads one sector of 512 bytes from the card */
uint8_t card_read(uint32_t sector, uint8_t* buffer) 
{
	uint16_t i;
	uint8_t result;
	uint8_t card_response; 
	
	uint32_t address = (card_type == CARD_TYPE_SDHC) ? (sector) : (sector << 9);		
		
	/* Lower Chip Select */
	PORTCbits.RC2 = 0;

	/* Send CMD17 */
	result = card_command(0x51, (uint16_t) (address >> 16), (uint16_t) address, 0xFF);	
				
	while (result != 0)
		result = SPI(0xFF);
			
	/* Wait until 0xFE is received */
	while ((card_response = SPI(0xFF)) == (uint8_t) 0xFF);
		
	if (card_response != 0xFE)	
		return 0;						
	
	/* Read data */
	for(i = 0; i < 512; i ++) 
		buffer[i] = SPI(0xFF);  
			
	/* Receive CRC */
	SPI(0xFF); 
	SPI(0xFF);
		
	/* Let the card finish */
	SPI(0xFF); 
			
	return 1;	
}

#define LE16(card_sector, X)	(((uint16_t) card_sector[(X)]) + 			\
							    (((uint16_t) card_sector[(X) + 1]) << 8)) 	
				 
#define LE32(card_sector, X)	(((uint32_t) card_sector[(X)]) + 			\
								(((uint32_t) card_sector[(X) + 1]) << 8) +  	\
								(((uint32_t) card_sector[(X) + 2]) << 16) + 	\
								(((uint32_t) card_sector[(X) + 3]) << 24))		
				 
#define LBA(X) (cluster_begin_lba + ((X) - 2) * sectors_per_cluster)

/* Initializes FAT32 support */
uint8_t fat32_init(void)
{
	uint16_t bytes_per_sector;	

	/* Read sector 0 into the sector buffer */
	if (!card_read(0, sector_buffer))
		return 0;

	/* Depending on whether SD Card controller firmware reports 
	 * itself as removable media or not, it may or may not have an
	 * MBR. If there is no MBR, sector 0 will be the boot sector, as
	 * in a floppy. If the first byte of sector 0 is 0xEB, we assume
	 * it's the boot sector (LBR).
	 */
	 		
	if (sector_buffer[0] != 0xEB)
	{
		/* Find out the starting sector of the first primary partition */ 
		fpp_begin_lba = LE32(sector_buffer, 454);		

		/* Read FAT32 Volume ID into the sector buffer */
		if (!card_read(fpp_begin_lba, sector_buffer))
			return 0;
	}
	else
		fpp_begin_lba = 0; 				
	
	/* Compute important FAT locations */
	reserved_sector_count = LE16(sector_buffer, 14);
	fat_count = sector_buffer[16];
	sectors_per_fat = LE32(sector_buffer, 36);
	
	fat_begin_lba = fpp_begin_lba + reserved_sector_count;
	cluster_begin_lba = fpp_begin_lba + reserved_sector_count + (fat_count * sectors_per_fat);
	
	sectors_per_cluster = sector_buffer[13];	
	root_dir_first_cluster = LE32(sector_buffer, 44);

	return 1;
}

/* Looks for Cumulus.BIN in the SD Card */
void update_firmware(void)
{
	uint8_t i;
	uint8_t s;
	uint8_t* dir_entry;
	uint32_t cluster;
	uint32_t size;
	uint16_t address;
	int32_t bytes_left;
	uint32_t sector;

	if (!card_init())
		goto error;			
	if (!fat32_init())
		goto error;			

	/* Read directory first sector into the sector buffer */
	if (!card_read(LBA(root_dir_first_cluster), sector_buffer))
		goto error;			

	size = 0;
	dir_entry = sector_buffer;
	
	while (dir_entry[0])
	{
		for (i = 0; i < 11; i ++)
			if (dir_entry[i] != str_cumulus_bin[i])
				break;
		
		if (i == 11)
		{
			/* Get the cluster number */
			cluster = ((uint32_t) dir_entry[26]) + 
					  ((uint32_t) dir_entry[27] << 8) + 
					  ((uint32_t) dir_entry[20] << 16) + 
					  ((uint32_t) dir_entry[21] << 24);	
							
			/* Get the size */
			size = LE32(dir_entry, 28);

			break;
		}

		dir_entry += 0x20;
	}
												
	if (size && size < 65536)
	{
#ifdef TEXT_SUPPORT
		n6610_draw_rom_str(2, 48, (const far rom char*) "Updating firmware");
#endif

		s = 0;
		address = 0;
		bytes_left = size;
		sector = LBA(cluster);
		
		while (bytes_left > 0)
		{		
			if (!card_read(sector, sector_buffer))
				return;
		
			for (i = 0; i < 8; i ++)
			{
				if (bytes_left <= 0)		
					break;
		
				if (address >= 0x1000)
				{
					//n6610_debug_message_short(18 + i * 8, (const far rom char*) "Writing Block", address);
					if (!erase_program_verify_page(address, sector_buffer + ((uint16_t) i) * 64))
						goto error;
				}

				address += 64;
				bytes_left -= 64;
		
				//Delay10KTCYx(20);
			}

			n6610_fill_area(s, 56, 2, 16, 0xF0, 0x00, 0x0F);
		
			s += 1;
			sector ++;
		}
	}	
	else
		goto error;

	n6610_fill_area(0, 0, 132, 132, 0xF0, 0x00, 0x0F);
	return;

error:

	/* Turn screen to red */
	n6610_fill_area(0, 0, 132, 132, 0x0F, 0xF0, 0x00);

#ifdef TEXT_SUPPORT
		n6610_draw_rom_str(2, 48, (const far rom char*) "Update failed!");			
#endif
}
	
void main(void) 
{
	OSCCON = 0x60;          // IRCFx = 110 (8 MHz)
    OSCTUNEbits.PLLEN = 1;  // x4 PLL enabled = 32MHz

	/* No Analog Pins */		
	ANSELH = 0x00;
	ANSEL = 0x00;
	
	/* Update firmware? */
	if (PORTEbits.RE2 == 0 && PORTEbits.RE1 == 0)
	{
		n6610_init();
		n6610_fill_area(0, 0, 132, 132, 0x00, 0x0F, 0xF0);

		update_firmware();		

		/* Halt */
		while (1);
	}

	_asm goto RM_RESET_VECTOR _endasm
} 

User avatar
Chema
Game master
Posts: 2078
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Cumulus Firware Compilation

Post by Chema » Sat Jul 01, 2017 1:38 pm

Hi zaxxon! Glad to see you finals built some cumulus :)

I worked a bit on the firmware and it was really picky with the card used and the way it is was formatted. The boot loader uses the same code, so maybe the problem lies there.

The card should be SDHC, modern fast cards don't work IIRC, and it should be formatted with something such as this tool:

https://www.sdcard.org/downloads/formatter_4/index.html

With FAT32 and MBR.

Also, a stupid detail, be sure the file name of the bin file is all in caps.

Good luck!

zaxon
1st Star Corporal
Posts: 10
Joined: Thu Jun 29, 2017 9:51 am

Re: Cumulus Firware Compilation

Post by zaxon » Sat Jul 01, 2017 2:57 pm

No luck...
Farious formats and cards, also formatted by this formatter.Start and hanging.
Image

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest