test
Dependencies: mbed Prelude_OV5642 Arducam_UTFT_SPI Arducam_OV5642 Arduino WIZnetInterface_Ricky
Revision 6:cc373209ef74, committed 2022-01-13
- Comitter:
- RyusukeIwata
- Date:
- Thu Jan 13 10:01:56 2022 +0000
- Parent:
- 5:e47189da7d92
- Commit message:
- test
Changed in this revision
diff -r e47189da7d92 -r cc373209ef74 SDFileSystem.lib --- a/SDFileSystem.lib Thu Oct 29 23:35:16 2015 +0000 +++ b/SDFileSystem.lib Thu Jan 13 10:01:56 2022 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/mbed_official/code/SDFileSystem/#7b35d1709458 +https://os.mbed.com/users/RyusukeIwata/code/Prelude_OV5642/#f0d44a5a63cb
diff -r e47189da7d92 -r cc373209ef74 main.cpp --- a/main.cpp Thu Oct 29 23:35:16 2015 +0000 +++ b/main.cpp Thu Jan 13 10:01:56 2022 +0000 @@ -3,16 +3,14 @@ #include "OV5642.h" #include "OV5642_regs.h" #include "SDFileSystem.h" -#include "Arduino.h" -#include "EthernetInterface.h" #include <stdio.h> #include <string.h> -ArduCAM myCAM(D11, D12, D13, D10, D14, D15); -ArduLCD myGLCD(D11, D12, D13, D10); -SDFileSystem sd(D11, D12, D13, D9, "sd"); +ArduCAM myCAM(p5, p6, p7, p25, p9, p10); +ArduLCD myGLCD(p5, p6, p7, p25); +SDFileSystem sd(p5, p6, p7, p8, "sd"); -Serial pc(USBTX, USBRX); +Serial pc(USBTX, USBRX, 115200); bool isShowFlag = true; char fnamecamera[32]; char fnamecntcamera=0; @@ -31,12 +29,9 @@ bool gDataSockReady = false; bool gDataPutGetStart = false; bool ftpclientrun = false; -int remote_port; -char ftpServer_data_ip_addr[4]={0,}; -char ftpServer_data_ip_addr_str[20]={0,}; -static char buf[256]; -static char ID[]={"abc"}; //Set FTPServer Login ID -static char PASSWORD[]={"123"}; //Set FTPServer Login Password +int iwata_flag=0; + + enum CommandFirst { f_nocmd, f_put, @@ -67,25 +62,53 @@ char fnamecnt=0; char gMsgBuf[10]; char User_Keyboard_MSG_Cnt; -/* Function*/ -char* User_Keyboard_MSG(void); -int pportc(char * arg); -void FTP_server_uploader(); +///* Function*/ +//char* User_Keyboard_MSG(void); +//int pportc(char * arg); +//void FTP_server_uploader(); void setup(); void loop(); -void itoa( unsigned long long int value, char *str); +//void itoa( unsigned long long int value, char *str); int main() { - *(volatile uint32_t *)(0x41001014) = 0x0060200; //clock 24MHz + int finish_flag = 0; + pc.printf("hello world\r\n"); + pc.printf("ARDUCHIP_TRIG , SHUTTER_MASK : %x, %x\r\n", ARDUCHIP_TRIG , SHUTTER_MASK); + + //*(volatile uint32_t *)(0x41001014) = 0x0060200; //clock 24MHz setup(); + pc.printf("setup finish\r\n"); + + + //loop(); //FTP_server_uploader(); - while(1) + + for(int j = 0; j<2; j++) + //while(1) { loop(); - } + } + + //while(1){ + for(int j = 0; j < 5; j++){ + pc.printf("[main] read_reg = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); + if((myCAM.read_reg(ARDUCHIP_TRIG) == 8) | (myCAM.read_reg(ARDUCHIP_TRIG) == 9) ){ + //setup(); + loop(); + //finish_flag = 1; + } + wait(1.0); + //if(finish_flag == 1){ + // break; + //} + } + + + pc.printf("loop all finish\r\n"); + } void setup() @@ -93,7 +116,7 @@ uint8_t vid,pid; uint8_t temp; - pc.baud(115200); + //pc.baud(115200); pc.printf("ArduCAM Start!\r\n"); @@ -143,10 +166,14 @@ static int i = 0; uint8_t temp,temp_last; uint8_t start_capture = 0; - - //Wait trigger from shutter buttom - if(myCAM.get_bit(ARDUCHIP_TRIG , SHUTTER_MASK)) + + //Wait trigger from shutter buttom + //pc.printf("%x\r\n",myCAM.get_bit(ARDUCHIP_TRIG , SHUTTER_MASK)); + //if(myCAM.get_bit(ARDUCHIP_TRIG , SHUTTER_MASK)) + pc.printf("=== [0]iwata_flag = %d, start_capture = %d ===\r\n",iwata_flag, start_capture); + if(iwata_flag) { + pc.printf("=== [1] myCAM.get_bit ===\r\n"); isShowFlag = false; myCAM.set_mode(MCU2LCD_MODE); myCAM.set_format(JPEG); @@ -157,47 +184,67 @@ //Wait until buttom released while(myCAM.get_bit(ARDUCHIP_TRIG, SHUTTER_MASK)); wait_ms(1000); - start_capture = 1; + start_capture = 1; + iwata_flag = 0; + pc.printf("[1-1] read_reg_if = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); } else { + pc.printf("===[2] myCAM.get_bit else ===\r\n"); if(isShowFlag ) { - + pc.printf("[2-1] read_reg = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); if(!myCAM.get_bit(ARDUCHIP_TRIG,VSYNC_MASK)) //New Frame is coming { myCAM.set_mode(MCU2LCD_MODE); //Switch to MCU myGLCD.resetXY(); myCAM.set_mode(CAM2LCD_MODE); //Switch to CAM - while(!myCAM.get_bit(ARDUCHIP_TRIG,VSYNC_MASK)); //Wait for VSYNC is gone + pc.printf("[2-2] read_reg = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); + while(!myCAM.get_bit(ARDUCHIP_TRIG,VSYNC_MASK)){ + //pc.printf("[2-3] %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); + } //Wait for VSYNC is gone + pc.printf("[2-3] read_reg = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); + } + if(myCAM.read_reg(ARDUCHIP_TRIG) == 1){ + iwata_flag = 1; } } } if(start_capture) { + pc.printf("===[3] start capture ===\r\n"); //Flush the FIFO myCAM.flush_fifo(); //Clear the capture done flag myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); - pc.printf("Start Capture\r\n"); + pc.printf("[3-1] after start_capture read_reg_if = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); } - + pc.printf("[before 4] read_reg = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); if(myCAM.get_bit(ARDUCHIP_TRIG ,CAP_DONE_MASK)) { - pc.printf("Capture Done!\r\n"); + pc.printf("=== [4]Capture Done! ===\r\n"); + pc.printf("[4-1] read_reg = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); //Construct a file name snprintf(fnamecamera, sizeof(fnamecamera), "/sd/jpss%04d.jpg", fnamecntcamera); + pc.printf("[4-2]\r\n"); fnamecntcamera++; + pc.printf("[4-3]\r\n"); //Open the new file outFile = fopen(fnamecamera,"w"); + pc.printf("[4-4]\r\n"); if (! outFile) { pc.printf("open file failed\r\n"); return; } + else + { + pc.printf("open file okay\r\n"); + } + //Read first dummy byte //myCAM.read_fifo(); @@ -236,216 +283,216 @@ myCAM.set_format(BMP); myCAM.InitCAM(); isShowFlag = true; + pc.printf("finish saving!\r\n"); + pc.printf("[4-2] read_reg_if = %x\r\n", myCAM.read_reg(ARDUCHIP_TRIG)); } } /* itoa: convert n to characters in s */ -void itoa( unsigned long long int value, char *str) -{ - int i,j; - char temp[30]; - for(i=0; value > 0; i++){ - str[i] = value%10+'0'; - value=value/10; - } - for(j=0;i>=0;j++,i--){ - temp[j]=str[i-1]; - } - for(i=0;i<j;i++){ - str[i]=temp[i]; - } -} - -void FTP_server_uploader(){ +//void itoa( unsigned long long int value, char *str) +//{ +// int i,j; +// char temp[30]; +// for(i=0; value > 0; i++){ +// str[i] = value%10+'0'; +// value=value/10; +// } +// for(j=0;i>=0;j++,i--){ +// temp[j]=str[i-1]; +// } +// for(i=0;i<j;i++){ +// str[i]=temp[i]; +// } +//} - char Msg_c; - int remain_filesize; - int send_byte; - - pc.printf("Hello FTP Camera!\r\n"); - - uint8_t mac_addr[6] = {0x00, 0x08, 0xdc, 0x12, 0x34, 0x45}; - const char ip_addr[] = "192.168.0.123"; // WIZwiki-W7500 IP-address - const char mask_addr[] = "255.255.255.0"; - const char gateway_addr[] = "192.168.0.1"; - const char ftpServer_control_ip_addr[] = "192.168.0.209"; // my IP address - - - EthernetInterface eth; - eth.init(mac_addr, ip_addr, mask_addr, gateway_addr); //Use Static - eth.connect(); - - TCPSocketConnection FTP_CONTROL_SOCK; - TCPSocketConnection FTP_DATA_SOCK; - - - pc.printf("\r\n----------------------------------------\r\n"); - pc.printf("Press menu key\r\n"); - pc.printf("----------------------------------------\r\n"); - pc.printf("1> Snapshot Picture and Send to FTPServer\r\n"); - pc.printf("----------------------------------------\r\n"); - Msg_c = pc.getc(); - if(Msg_c==0x31){ - - ftpclientrun = true; - while(ftpclientrun){ - //while 2 - while(!FTP_CONTROL_SOCK.is_connected()){ - pc.printf("Connecting...FTPServer\r\nIP:%s, PORT:%d\r\n", ftpServer_control_ip_addr, FTP_SERVER_PORT); - FTP_CONTROL_SOCK.connect(ftpServer_control_ip_addr, FTP_SERVER_PORT); - FTP_CONTROL_SOCK.set_blocking(false, 15000); // Timeout after (1.5)s - }//end of while 2 - - //while 3 - while(true) - { - //gDataSockReady if - if(gDataSockReady){ - gDataSockReady = false; - //FTPCommand.First switch case - switch(FTPCommand.First){ - case f_put: - FTP_CONTROL_SOCK.send(STOR, sizeof(STOR)-1); - FTP_CONTROL_SOCK.send(fname_server, sizeof(fname_server)); - FTP_CONTROL_SOCK.send(END, sizeof(END)-1); - break; - }//end of FTPCommand.First switch case - }//end of gDataSockReady if - /* received from FTPServer */ - int n = FTP_CONTROL_SOCK.receive(buf, sizeof(buf)); - if (n <= 0) break; - buf[n] = '\0'; - pc.printf("\r\nReceived message from server: '%s'\r\n", buf); - - //buf if - if (!strncmp(buf, "220", 3)){ - FTP_CONTROL_SOCK.send(USER, sizeof(USER)-1); - FTP_CONTROL_SOCK.send(ID, sizeof(ID)); - FTP_CONTROL_SOCK.send(END, sizeof(END)-1); - } - else if(!strncmp(buf, "331", 3)){ - FTP_CONTROL_SOCK.send(PASS, sizeof(PASS)-1); - FTP_CONTROL_SOCK.send(PASSWORD, sizeof(PASSWORD)); - FTP_CONTROL_SOCK.send(END, sizeof(END)-1); - } - else if(!strncmp(buf, "230", 3)){ - FTP_CONTROL_SOCK.send(PASV, sizeof(PASV)-1); - FTP_CONTROL_SOCK.send(END, sizeof(END)-1); - FTPCommand.First = f_put; - } - else if(!strncmp(buf, "227", 3)){ - if (pportc(buf) == -1){ - pc.printf("Bad port syntax\r\n"); - } - else{ - pc.printf("Go Open Data Sock...\r\n "); - FTPClient.dsock_state = DATASOCK_READY; - } - } - else if(!strncmp(buf, "150", 3)){ - switch(FTPCommand.First){ - case f_put: - FTPCommand.First = f_nocmd; - FTPCommand.Second = s_put; - gDataPutGetStart = true; - break; - } - } - else if(!strncmp(buf, "226", 3)){ - ftpclientrun = false; - FTP_CONTROL_SOCK.close(); - }//end of buf if - - - //DATASOCK_READY if - if(FTPClient.dsock_state == DATASOCK_READY){ - while(!FTP_DATA_SOCK.is_connected()){ - pc.printf("Connecting...FTPServer Data sock\r\nIP:%s, PORT:%d\r\n", ftpServer_data_ip_addr_str, remote_port); - FTP_DATA_SOCK.connect(ftpServer_control_ip_addr, remote_port); - FTP_DATA_SOCK.set_blocking(false, 15000); // Timeout after (1.5)s - } - FTPClient.dsock_state = DATASOCK_IDLE; - gDataSockReady = true; - }//end of DATASOCK_READY if - - //gDataPutGetStart if - if(gDataPutGetStart){ - //FTPCommand.Second switch case - switch(FTPCommand.Second){ - case s_put: - pc.printf("put waiting...\r\n"); - snprintf(fname, sizeof(fname), "/sd/jpss0000.jpg"); - fp_jpeg = fopen(fname, "r"); - fseek(fp_jpeg, 0, SEEK_END); // seek to end of file - remain_filesize = ftell(fp_jpeg); // get current file pointer - fseek(fp_jpeg, 0, SEEK_SET); // seek back to beginning of file - do{ - memset(buf, 0, sizeof(buf)); - if(remain_filesize > MAX_SS) - send_byte = MAX_SS; - else - send_byte = remain_filesize; - fread (buf, 1, send_byte, fp_jpeg); - FTP_DATA_SOCK.send(buf, send_byte); - remain_filesize -= send_byte; - pc.printf("#"); - }while(remain_filesize!=0); - fclose(fp_jpeg); - gDataPutGetStart = false; - FTPCommand.Second = s_nocmd; - FTP_DATA_SOCK.close(); - break; - - }//end of FTPCommand.Second switch case - }//end of gDataPutGetStart if - }//end of while 3 - } - } -} +//void FTP_server_uploader(){ +// +// char Msg_c; +// int remain_filesize; +// int send_byte; +// +// pc.printf("Hello FTP Camera!\r\n"); +// +// uint8_t mac_addr[6] = {0x00, 0x08, 0xdc, 0x12, 0x34, 0x45}; +// const char ip_addr[] = "192.168.0.123"; // WIZwiki-W7500 IP-address +// const char mask_addr[] = "255.255.255.0"; +// const char gateway_addr[] = "192.168.0.1"; +// const char ftpServer_control_ip_addr[] = "192.168.0.209"; // my IP address +// +// +// +// +// TCPSocketConnection FTP_CONTROL_SOCK; +// TCPSocketConnection FTP_DATA_SOCK; +// +// +// pc.printf("\r\n----------------------------------------\r\n"); +// pc.printf("Press menu key\r\n"); +// pc.printf("----------------------------------------\r\n"); +// pc.printf("1> Snapshot Picture and Send to FTPServer\r\n"); +// pc.printf("----------------------------------------\r\n"); +// Msg_c = pc.getc(); +// if(Msg_c==0x31){ +// +// ftpclientrun = true; +// while(ftpclientrun){ +// //while 2 +// while(!FTP_CONTROL_SOCK.is_connected()){ +// pc.printf("Connecting...FTPServer\r\nIP:%s, PORT:%d\r\n", ftpServer_control_ip_addr, FTP_SERVER_PORT); +// FTP_CONTROL_SOCK.connect(ftpServer_control_ip_addr, FTP_SERVER_PORT); +// FTP_CONTROL_SOCK.set_blocking(false, 15000); // Timeout after (1.5)s +// }//end of while 2 +// +// //while 3 +// while(true) +// { +// //gDataSockReady if +// if(gDataSockReady){ +// gDataSockReady = false; +// //FTPCommand.First switch case +// switch(FTPCommand.First){ +// case f_put: +// FTP_CONTROL_SOCK.send(STOR, sizeof(STOR)-1); +// FTP_CONTROL_SOCK.send(fname_server, sizeof(fname_server)); +// FTP_CONTROL_SOCK.send(END, sizeof(END)-1); +// break; +// }//end of FTPCommand.First switch case +// }//end of gDataSockReady if +// /* received from FTPServer */ +// int n = FTP_CONTROL_SOCK.receive(buf, sizeof(buf)); +// if (n <= 0) break; +// buf[n] = '\0'; +// pc.printf("\r\nReceived message from server: '%s'\r\n", buf); +// +// //buf if +// if (!strncmp(buf, "220", 3)){ +// FTP_CONTROL_SOCK.send(USER, sizeof(USER)-1); +// FTP_CONTROL_SOCK.send(ID, sizeof(ID)); +// FTP_CONTROL_SOCK.send(END, sizeof(END)-1); +// } +// else if(!strncmp(buf, "331", 3)){ +// FTP_CONTROL_SOCK.send(PASS, sizeof(PASS)-1); +// FTP_CONTROL_SOCK.send(PASSWORD, sizeof(PASSWORD)); +// FTP_CONTROL_SOCK.send(END, sizeof(END)-1); +// } +// else if(!strncmp(buf, "230", 3)){ +// FTP_CONTROL_SOCK.send(PASV, sizeof(PASV)-1); +// FTP_CONTROL_SOCK.send(END, sizeof(END)-1); +// FTPCommand.First = f_put; +// } +// else if(!strncmp(buf, "227", 3)){ +// if (pportc(buf) == -1){ +// pc.printf("Bad port syntax\r\n"); +// } +// else{ +// pc.printf("Go Open Data Sock...\r\n "); +// FTPClient.dsock_state = DATASOCK_READY; +// } +// } +// else if(!strncmp(buf, "150", 3)){ +// switch(FTPCommand.First){ +// case f_put: +// FTPCommand.First = f_nocmd; +// FTPCommand.Second = s_put; +// gDataPutGetStart = true; +// break; +// } +// } +// else if(!strncmp(buf, "226", 3)){ +// ftpclientrun = false; +// FTP_CONTROL_SOCK.close(); +// }//end of buf if +// +// +// //DATASOCK_READY if +// if(FTPClient.dsock_state == DATASOCK_READY){ +// while(!FTP_DATA_SOCK.is_connected()){ +// pc.printf("Connecting...FTPServer Data sock\r\nIP:%s, PORT:%d\r\n", ftpServer_data_ip_addr_str, remote_port); +// FTP_DATA_SOCK.connect(ftpServer_control_ip_addr, remote_port); +// FTP_DATA_SOCK.set_blocking(false, 15000); // Timeout after (1.5)s +// } +// FTPClient.dsock_state = DATASOCK_IDLE; +// gDataSockReady = true; +// }//end of DATASOCK_READY if +// +// //gDataPutGetStart if +// if(gDataPutGetStart){ +// //FTPCommand.Second switch case +// switch(FTPCommand.Second){ +// case s_put: +// pc.printf("put waiting...\r\n"); +// snprintf(fname, sizeof(fname), "/sd/jpss0000.jpg"); +// fp_jpeg = fopen(fname, "r"); +// fseek(fp_jpeg, 0, SEEK_END); // seek to end of file +// remain_filesize = ftell(fp_jpeg); // get current file pointer +// fseek(fp_jpeg, 0, SEEK_SET); // seek back to beginning of file +// do{ +// memset(buf, 0, sizeof(buf)); +// if(remain_filesize > MAX_SS) +// send_byte = MAX_SS; +// else +// send_byte = remain_filesize; +// fread (buf, 1, send_byte, fp_jpeg); +// FTP_DATA_SOCK.send(buf, send_byte); +// remain_filesize -= send_byte; +// pc.printf("#"); +// }while(remain_filesize!=0); +// fclose(fp_jpeg); +// gDataPutGetStart = false; +// FTPCommand.Second = s_nocmd; +// FTP_DATA_SOCK.close(); +// break; +// +// }//end of FTPCommand.Second switch case +// }//end of gDataPutGetStart if +// }//end of while 3 +// } +// } +//} -char* User_Keyboard_MSG(void) -{ - User_Keyboard_MSG_Cnt = 0; - memset(gMsgBuf, 0, sizeof(gMsgBuf)); - do{ - gMsgBuf[User_Keyboard_MSG_Cnt] = pc.getc(); - if(gMsgBuf[User_Keyboard_MSG_Cnt]==0x08){ - User_Keyboard_MSG_Cnt--; - } - else{ - User_Keyboard_MSG_Cnt++; - } - }while(gMsgBuf[User_Keyboard_MSG_Cnt-1]!=0x0d); - return gMsgBuf; -} - -int pportc(char * arg) -{ - int i; - char* tok=0; - strtok(arg,"("); - for (i = 0; i < 4; i++) - { - if(i==0) tok = strtok(NULL,",\r\n"); - else tok = strtok(NULL,","); - ftpServer_data_ip_addr[i] = (uint8_t)atoi(tok); - if (!tok){ - pc.printf("bad pport : %s\r\n", arg); - return -1; - } - } - remote_port = 0; - for (i = 0; i < 2; i++){ - tok = strtok(NULL,",\r\n"); - remote_port <<= 8; - remote_port += atoi(tok); - if (!tok){ - pc.printf("bad pport : %s\r\n", arg); - return -1; - } - } - pc.printf("ip : %d.%d.%d.%d, port : %d\r\n", ftpServer_data_ip_addr[0], ftpServer_data_ip_addr[1], ftpServer_data_ip_addr[2], ftpServer_data_ip_addr[3], remote_port); - sprintf(ftpServer_data_ip_addr_str, "%d.%d.%d.%d", ftpServer_data_ip_addr[0], ftpServer_data_ip_addr[1], ftpServer_data_ip_addr[2], ftpServer_data_ip_addr[3]); - return 0; -} - +//char* User_Keyboard_MSG(void) +//{ +// User_Keyboard_MSG_Cnt = 0; +// memset(gMsgBuf, 0, sizeof(gMsgBuf)); +// do{ +// gMsgBuf[User_Keyboard_MSG_Cnt] = pc.getc(); +// if(gMsgBuf[User_Keyboard_MSG_Cnt]==0x08){ +// User_Keyboard_MSG_Cnt--; +// } +// else{ +// User_Keyboard_MSG_Cnt++; +// } +// }while(gMsgBuf[User_Keyboard_MSG_Cnt-1]!=0x0d); +// return gMsgBuf; +//} +// +//int pportc(char * arg) +//{ +// int i; +// char* tok=0; +// strtok(arg,"("); +// for (i = 0; i < 4; i++) +// { +// if(i==0) tok = strtok(NULL,",\r\n"); +// else tok = strtok(NULL,","); +// ftpServer_data_ip_addr[i] = (uint8_t)atoi(tok); +// if (!tok){ +// pc.printf("bad pport : %s\r\n", arg); +// return -1; +// } +// } +// remote_port = 0; +// for (i = 0; i < 2; i++){ +// tok = strtok(NULL,",\r\n"); +// remote_port <<= 8; +// remote_port += atoi(tok); +// if (!tok){ +// pc.printf("bad pport : %s\r\n", arg); +// return -1; +// } +// } +// pc.printf("ip : %d.%d.%d.%d, port : %d\r\n", ftpServer_data_ip_addr[0], ftpServer_data_ip_addr[1], ftpServer_data_ip_addr[2], ftpServer_data_ip_addr[3], remote_port); +// sprintf(ftpServer_data_ip_addr_str, "%d.%d.%d.%d", ftpServer_data_ip_addr[0], ftpServer_data_ip_addr[1], ftpServer_data_ip_addr[2], ftpServer_data_ip_addr[3]); +// return 0; +//} +//
diff -r e47189da7d92 -r cc373209ef74 mbed.bld --- a/mbed.bld Thu Oct 29 23:35:16 2015 +0000 +++ b/mbed.bld Thu Jan 13 10:01:56 2022 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/34e6b704fe68 \ No newline at end of file +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file