It's a FT2232D chip, and the LED is connected to BDBUS6.
The library is less documented than I might like (better than FTDI's own library though, which doesn't even work on modern kernels), the only example code I can find that does this uses a deprecated function (I tried, it doesn't seem to work), and I'm absolutely stumped.
The harder I try with this thing, the more difficult it seems. I'm not looking for someone to do my homework for me so much as I just need a nudge in the right direction. Any help appreciated (even speculative).
Update: I've been trying this, though ftdi_enable_bitbang() is deprecated. The following code compiles, it runs without barfing, but no blinkenlighten. Schematics of the device in question are available at http://www.semtech.com/images/datasheet/sx1211ska_v1_std.pdf , page 23. BDBUS6 and BDBUS7 are hooked up to the LEDs.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <ftdi.h>
#define FTDI_VID 0x0403
#define FTDI_PID 0x6010
static struct ftdi_context ftdic_context;
int main(void) {
int ret;
unsigned int i;
unsigned char c = 0;
// Initialize bitbang.
// ret = ft2232_bb_init();
ftdi_usb_open(&ftdic_context, FTDI_VID, FTDI_PID);
ftdi_set_interface(&ftdic_context, INTERFACE_B);
ftdi_enable_bitbang(&ftdic_context, 0xb0);
// Trying to blink some lights.
printf("\nNow let's try to blinkenlights...\n");
for (i = 0; i < 20; i++) {
c ^= 0x80;
ftdi_write_data(&ftdic_context, &c, 1);
sleep(1);
}
return EXIT_SUCCESS;
}
You need to initialize the ftdi context before you can open a device with it.
ftdi_init(&ftdic_context);
Also you need to set the interface channel before you open the device.
Heres the function I use to set up a ftdi context
int initFTDI(struct ftdi_context * ftdic)
{
unsigned char Mask = 0x1F;
int ret=0;
fprintf(stderr,"start init\n");
ftdi_init(ftdic);
//for multi-channel ftdi chips eg(ft2232)
if(ftdi_set_interface(ftdic,INTERFACE_B))
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if((ret = ftdi_usb_open(ftdic, VID, PID)) < 0){
fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
return EXIT_FAILURE;
}
if(ftdi_usb_reset(ftdic))
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_usb_purge_buffers(ftdic)) //clean buffers
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_write_data_set_chunksize(ftdic,65536)) //64k transfer size
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_read_data_set_chunksize(ftdic,4096)) //64k transfer size
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_event_char(ftdic,false,0)) //disable event chars
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_error_char(ftdic,false,0)) //disable error chars
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_latency_timer(ftdic,2)) //Set the latency timer to 1mS (default is 16mS)
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_set_baudrate(ftdic,921600))
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if(ftdi_setflowctrl(ftdic,SIO_RTS_CTS_HS)) //set flow control
fprintf(stderr,"%s\n",ftdi_get_error_string(ftdic));
if ((ret = ftdi_set_bitmode( ftdic, 0x00, BITMODE_RESET )) < 0 )
{
fprintf(stderr, "can't set bitmode to %x: %d (%s)\n", BITMODE_RESET, ret, ftdi_get_error_string(ftdic));
fprintf( stderr, "RESET\n" );
return EXIT_FAILURE;
}
if ((ret = ftdi_set_bitmode( ftdic, Mask, BITMODE_BITBANG )) < 0 )
fprintf(stderr, "can't set bitmode to %x: %d (%s)\n", BITMODE_BITBANG, ret, ftdi_get_error_string(ftdic));
fprintf( stderr, "RESET\n" );
return EXIT_FAILURE;
}
//fprintf(stderr,"end init\n");
return ret;
}
ftdi_enable_bitbang
is deprecated,
you should use
ftdi_set_bitmode(&ftdic, LED,BITMODE_BITBANG);
instead, see the documentation:
Same Answer as here: I'm having trouble finding example code for libftdi's mpsse (SPI) mode
http://flashrom.org/Downloads
Its mainly MPSSE mode, but it also sets the nCS signal via bitbang command.
Related
I'm writing a daemon which checks the battery capacity. This is for a solar powered embedded device running Linux. I've read that it's a bad idea to use sleep() in daemons, thus I'm trying to use events. So I wrote some PoCs, but I'm not getting any events! My first implementation, as they recommended to me, uses libudev and poll():
#include <fcntl.h>
#include <libudev.h>
#include <poll.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
struct udev *udev;
struct udev_monitor *mon;
struct pollfd fds[1];
int fd;
udev = udev_new();
if (udev == NULL)
return 1;
mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL);
udev_monitor_enable_receiving(mon);
fd = udev_monitor_get_fd(mon);
fds[0].fd = fd;
fds[0].events = POLLIN;
fds[0].revents = 0;
if (poll(fds, 1, -1) > 0) {
/* Never gets here! */
struct udev_device *const dev = udev_monitor_receive_device(mon);
if (dev != NULL) {
puts(udev_device_get_sysname(dev));
udev_device_unref(dev);
}
else
fputs("udev_monitor_receive_device() failed\n", stderr);
}
udev_unref(udev);
return 0;
}
They only event I get, is when I plug/unplug the charger! Then I thought that the status bar I use in my laptop's installation does show the battery capacity. I looked at the source and they're using inotify to monitor the battery's uevent. But I've read everywhere that I shouldn't use inotify for sysfs! I tried nonetheless:
#include <stdio.h>
#include <sys/inotify.h>
#include <unistd.h>
#define BAT_PATH "/sys/class/power_supply/BAT0"
int main(void)
{
struct inotify_event ev = {0};
int wd, ret = 1;
ssize_t len;
const int fd = inotify_init1(IN_CLOEXEC);
if (fd < 0) {
perror("inotify_init() failed");
return ret;
}
/* else */
wd = inotify_add_watch(fd, BAT_PATH "/uevent", IN_ACCESS);
if (wd < 0)
goto end;
/* else */
len = read(fd, &ev, sizeof(ev));
/* Again... never gets here. */
if (len > 0 && (ev.mask & IN_ACCESS))
puts("It worked!");
inotify_rm_watch(fd, wd);
ret = 0;
end:
close(fd);
return ret;
}
Turns out that doesn't work either! How can it work for my status bar but not work when I try it? Am I doing something horribly wrong? Thank you.
Regarding your first implementation (would comment but not enough rep. as i know nothing about libudev): the guide i followed to successfully use sysfs to poll() a GPIO for interrupt suggests to look for a POLLPRI event, instead of POLLIN as you show in the first implementation (see man poll for event types).
More importantly, you say you get a single event when you connect/disconnect charger, do you mean a single event per software execution? If this is the case, it might be due to the fact that you don't clear the interrupt flag: after poll() hits, in sysfs one needs to int len = read(fds[0].fd, *buf, SIZE); to mark the interrupt as served, and also lseek(fds[0].fd, 0, 0); in order for the next read() to be succesful (see my other answer here for a code example).
i dont know whether this answer will help you or not, but i am writing answer because if any other users face same issue they can get it resolved.
the solution is:
you need to monitor kernel Events, so you need to change line
form
mon = udev_monitor_new_from_netlink(udev, "udev");
to
mon = udev_monitor_new_from_netlink(udev, "kernel");
then you will get events.
I need to transfer data to BeagleBone Black via Modbus RTU using Rs485. To work with Modbus RTU,but I don't know how to toggle rts in rs-485.HELP
Modbus RTU data transmission code
how to add RS485 code to this,to use the Modbus library libmodbus
#include "modbus-rtu.h"
#include <stdio.h>
#include <errno.h>
int main(){
int connected;
modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;
ctx = modbus_new_rtu("/dev/ttyS4", 9600, 'N', 8, 1);
if(ctx == NULL) {
fprintf(stderr, "Unable to create the libmodbus context\n");
}
else {
modbus_set_slave(ctx, 1);
modbus_set_debug(ctx, TRUE);
connected = modbus_connect(ctx);
printf("modbus_set_slave return: %d\n", rc);
if (rc != 0)
{
printf("modbus_set_slave: %s \n"modbus_strerror(errno));
}
rc = modbus_read_registers(ctx, 0, 3, tab_reg);
for (i = 0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
if(rc == -1)
{
fprintf(stderr, "%s\n", modbus_strerror(errno));
}
modbus_close(ctx);
modbus_free(ctx);
}
return 0;
}
First I would check if your hardware support automatic (hardware) half-duplex direction control.
If not, then you can take a look at this answer. In there you have all the details you need to compile and install libmodbus with support for toggling the line with software.
I'm using this solution in my RPi and CHIP computers but you should be able to use it right away on your BBB. You might find a small caveat if the GPIO file name has a 3 or 4-digit number (take a look in /sys/class/gpio). If that's the case, take a look here, I had to modify the code to correct that problem.
I have connected GPIO Pin 17(in WiringPi Pin17 = Pin0) of my raspberry pi 1 with an interrupt source (an IR-LEDemitter/receiver which triggers an interrupt whenever the IR ray gets interrupted by some obstacle). For setting up the ISR, I have been using the WiringPi library (I have already tried it with the pigpio library as well, but I have the same problem there as well).
To verify that I am actually receiving interrupts on Pin17, I have checked it with my logic analyzer, and there are definitely some interrupts occuring on this pin as you can see:
Here is my code:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <wiringPi.h>
#include "MCP3008Driver.h"
#include "DHT11.h"
#define INT_PIN 0
volatile int eventCounter = 0;
void myInterrupt(void){
printf("hello ISR!\n");
eventCounter++;
}
volatile sig_atomic_t stopFlag = 0;
static void stopHandler(int sign) { /* can be called asynchronously */
stopFlag = 1; /* set flag */
}
int main(void) {
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
// sets up the wiringPi library
if (wiringPiSetup () < 0) {
printf("Unable to setup wiring pi\n");
fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror
(errno));
return 1;
}
// set Pin 17/0 to generate an interrupt on high-to-low transitions
// and attach myInterrupt() to the interrupt
if(wiringPiISR(INT_PIN, INT_EDGE_FALLING, &myInterrupt) < 0){
printf("unable to setup ISR\n");
fprintf(stderr, "Unable to setup ISR: %s\n", strerror(errno));
}
DHT11_data data;
configureSPI();
while(1){
if(stopFlag){
printf("\n Ctrl-C signal caught! \n");
printf("Closing application. \n");
return 0;
}
//read_dht_data(&data);
int analogBoiler = readChannel(0);
int analogHeater = readChannel(1);
int analogPress = readChannel(2);
int analogACS712 = readChannel(3);
int analogDynamo = readChannel(4);
printf("Channel 0 / Boiler = %f\n", evaluateChannelValue(ePT100_BOILER, analogBoiler));
printf("Channel 1 / Heater = %f\n", evaluateChannelValue(ePT100_HEATER, analogHeater));
printf("Channel 2 / Pressure = %f\n", evaluateChannelValue(ePRESS, analogPress));
printf("Channel 3 / Power ACS712 = %f\n", evaluateChannelValue(eACS712, analogACS712));
printf("Channel 4 / Power Dynamo = %f\n", evaluateChannelValue(eDYNAMO, analogDynamo));
//printf("Humidity Environment: %f\n", data.humidity);
//printf("Temperature (Celsius) Environment: %f\n", data.temp_celsius);
// display counter value every second.
printf("%d\n", eventCounter);
sleep(5);
}
return 0;
}
The methods wiringPiSetup and wiringPiISR are successfully called and are not returning an error.
I am building this example the the following linking options: -lwiringPi -lm -lpthread. Maybe I am missing a linking option?
I have been using this code here as a reference. So what am I doing wrong here? Thank you for any advice you can give me!
I'm not entirely sure why but I found that removing the unary operator in front of the function call input to wiringPiISR solved my problems.
So instead of calling
wiringPiISR(INT_PIN, INT_FALLING_EDGE, &MyInterrupt)
call
wiringPiISR(INT_PIN, INT_FALLING_EDGE, MyInterrupt)
My guess is that this has something to do with the fact the wiringPiISR is taking that argument as pointer (*function) so putting the address of call in front of it causes something weird to happen when it goes to try and call the MyInterrupt function, for me it caused my program to crash!
Hope this helps / maybe someone else will be able to elaborate more on why this would happen.
I have multiple slaves on a RS485 bus. I have been using pymodbus so far but I'm not quite happy with it's performance and other issues. So I wanted to to test libmodus and use that instead.
I wrote a minimal program that reads the model number of my slaves
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <modbus.h>
#include <errno.h>
char *bigendian_vec_to_str(uint16_t *vec, size_t vec_size, char *buff, size_t buff_len)
{
memset(buff, 0, sizeof *buff * buff_len);
int i;
for(i = 0; i < vec_size; ++i)
{
uint16_t fl = vec[i] >> 8;
uint16_t sl = vec[i] & 0xff;
if(2*i >= buff_len - 1)
return buff;
if(fl == 0)
return buff;
buff[2 * i] = fl;
if(2*i + 1 >= buff_len - 1)
return buff;
if(sl == 0)
return buff;
buff[2 * i + 1] = sl;
}
return buff;
}
char *get_model_name_of(modbus_t *modbus, int slave, char *buff, size_t buff_len)
{
modbus_flush(modbus);
modbus_set_slave(modbus, slave);
int rc;
uint16_t reg[9];
memset(reg, 0, sizeof reg);
rc = modbus_read_registers(modbus, 0xe, 8, reg);
if (rc == -1) {
fprintf(stderr, "Error %d while reading: %s\n", errno, modbus_strerror(errno));
return NULL;
}
return bigendian_vec_to_str(reg, 8, buff, buff_len);
}
int main(void)
{
modbus_t *modbus = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
modbus_rtu_set_serial_mode(modbus, MODBUS_RTU_RS485);
if (modbus_connect(modbus) == -1) {
fprintf(stderr, "Connexion failed: %s\n", modbus_strerror(errno));
modbus_free(modbus);
return -1;
}
char buff[1024];
int i;
for(i = 2; i < 5; ++i)
{
printf("Model of slave %d: %s\n", i, get_model_name_of(modbus, i, buff, sizeof buff));
}
modbus_free(modbus);
return 0;
}
When I ran this code I got
Model of slave 2: LEFS25B-600
Error 110 while reading: Connection timed out
Model of slave 3: (null)
Model of slave 4: LEHF10K2-16
and it seemed strange that the 2nd module was not responding. So I looped get_model_name_of through 2,3,4,2,3,4,2,3,4.... and every second read attempt ended with Error 110 while reading: Connection timed out. After the iine modbus_set_slave(modbus, slave); I added
usleep(0.005 * 1000000);
and then I didn't get timeouts anymore. I read the man pages twice and I didn't find anything warning me about this. I also searched google but none of the "similar" threads I found were of any help.
What is the best way to deal with multiple slaves? Why does adding a sleep of half of milisecond help here? I mean the code on libmodus does
static int _modbus_set_slave(modbus_t *ctx, int slave)
{
/* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
if (slave >= 0 && slave <= 247) {
ctx->slave = slave;
} else {
errno = EINVAL;
return -1;
}
return 0;
}
is setting an internal value in the context. Are there any time constraints between the change of an internal value in the context and reading/writing to the bus? If so, how long should I wait after a set_slave? Why does libmodbus set the slave id globally instead of having it as a parameter in the read/write method as other libraries (like pymodbus) do?
Or am I using this API just incorrectly?
Thanks
I may be wrong.. but.. as I understand it. The modbus master sends out a request, targeted at a specfic slave number. The intention is to recieve a reply from the targeted slave and then send a request to the next slave and await a reply from second slave. If the requests are sent out without waiting for reply from the first slave.. then there is a possibility to miss the reply from the second slave(or third or whatever number slave) , while the first slave reply is being sent and recieved by the master.
I am not good in C programming.. but I recommend you check this..as I think that may be why you adding a delay seems to help... ( Also.. part of Modbus protocol does require a pause in signal transmission to define start and end of transmission.)
If I am correct , then the use of a delay will only work well if you know the size of data being sent and the time to calculate a response..For other situations a handshake of some kind would be safe.. Such as read a coil.. that indicates whether data is refreshed and ready to be read from the slave as a possible traffic light . to control timing of requests going to other slave and to avoid collision of responses.
Again.. I am not good in C and if I have misinterpreted the program.. please ignore what I have said.. If it helps.. I would be happy hear.
Peter
I'm begining to learn linux and ALSA and I was wondering if there is a way to store the sound I record from a microphone a directly to the buffer. I read here http://www.linuxjournal.com/article/6735?page=0,2 how to make my recording program. But what I need is a little more complex. I need to record sound untill I hit a key. The reason I need this is because I'm messing with a RaspberryPI(debian on it) and to see if I could turn it into a sound monitoring/detecting device.
My main problem is now that when I try to use it to record (./Rec >name.raw ) it does nothing. It just ouputs an empty .raw file.
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <termios.h>
#include <alsa/asoundlib.h>
struct termios stdin_orig; // Structure to save parameters
void term_reset() {
tcsetattr(STDIN_FILENO,TCSANOW,&stdin_orig);
tcsetattr(STDIN_FILENO,TCSAFLUSH,&stdin_orig);
}
void term_nonblocking() {
struct termios newt;
tcgetattr(STDIN_FILENO, &stdin_orig);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // non-blocking
newt = stdin_orig;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
atexit(term_reset);
}
int main() {
int key=0;
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* One channel (mono) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* 16000 bits/second sampling rate */
val = 16000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 2048 frames. */
frames = 2048;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 2; /* 2 bytes/sample, 1 channels */
buffer = (char *) malloc(size);
while (key == 0)
{
rc = snd_pcm_readi(handle, buffer, frames);
if (rc == -EPIPE)
{
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(handle);
}
else if (rc < 0)
{
fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
}
else if (rc != (int)frames)
{
fprintf(stderr, "short read, read %d frames\n", rc);
}
rc = write(1, buffer, size);
if (rc != size)
fprintf(stderr, "short write: wrote %d bytes\n", rc);
key = getchar();
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
Here is how I did that with python. Tested to work on my desktop Debian with USB Plantronics headphones. You need to install python-qt4 and python-pyaudio packages for this to work.
Also, you'll need to set your input device to microphone. In GNOME I switched both input and output devices via System Tools -> System Settings -> Sound. If you have Raspbian, not Debian on your Raspberry, as I do, it's gonna be tougher, cause there's LXDE instead of GNOME. You can use alsamixer and F6 button there to set audio cards, but the problem is that ALSA is low-level interface, while most Linuxes use some sound server on top of it, such as PulseAudio or JACK. You'll need some luck/spent time to make sure you switched input/output device to your mic/headphones.
If you use Jack microphone, plugged in through Jack input of your Raspberry Pi, note that Raspberry's Jack is input only, so you won't be able to play back your recordings and need some USB headphones to listen to your wav.
Personally, I feel that ALSA is very poorly documented (I suppose it's intentional job security) and I don't like to deal with it.
import pyaudio
import wave
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
# This is Qt part: we create a window, which has a "stop" flag.
# Stop flag defaults to False, but is set to True, when you press a key.
# Value of that flag is checked in main loop and loop exits when flag is True.
app = QApplication(sys.argv)
class MyWindow(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.stop = False
def keyPressEvent(self, event):
print "keyPressedEvent caught!"
self.stop = True
window = MyWindow()
window.show()
# This is sound processing part: we create an input stream to read from microphone.
p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(2),
channels = 2,
rate=44100,
input=True,
output=False,
frames_per_buffer=1024)
# This is main loop: we iteratively poll audio and gui: audio data are stored in output_buffer,
# whereas gui is checked for stop flag value (if keyPressedEvent happened, flag will be set
# to True and break our main loop).
output_buffer = ""
while True:
app.processEvents()
data = stream.read(1024)
output_buffer += data
if window.stop: break
stream.stop_stream()
stream.close()
# Here we output contents of output_buffer as .wav file
output_wav = wave.open("output.wav", 'w')
output_wav.setparams((2, 2, 44100, len(output_buffer),"NONE","not compressed"))
output_wav.writeframesraw(output_buffer)
p.terminate()
This code shows you how to capture from ALSA in C++ in a while loop :
https://github.com/flatmax/gtkiostream/blob/master/test/ALSACaptureTest.C#L95
You can alter the loop there to record forever, replace :
while (N>0){
with
while (1){
Now you'll need some extra code. Firstly to read a character non-blocking add this to the top of the file :
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define ngetc(c) (read (0, (c), 1))
ngetc is a non-blocking read from stdin. It returns -1 when nothing is read. It returns > 1 when you press the enter key.
So finally putting this all together, change :
while (N>0){
with
while (1){
int enter=ngetc(&ch);
if (enter>0)
break;